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

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'netcore/System.Private.CoreLib/shared/System/Globalization')
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/BidiCategory.cs33
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/Calendar.cs732
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CalendarAlgorithmType.cs18
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs460
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs448
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs380
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CalendarWeekRule.cs15
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CalendricalCalculationsHelper.cs412
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs321
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfoData.cs1576
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs302
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs249
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs1148
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs606
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs1503
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CompareOptions.cs20
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs421
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs718
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.cs2252
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Unix.cs36
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs59
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.cs1166
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs104
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/CultureTypes.cs27
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs1380
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs2604
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs712
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs6106
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeStyles.cs49
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs45
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/DigitShapes.cs13
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs692
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/GlobalizationExtensions.cs29
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs488
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs660
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarTypes.cs18
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs904
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs447
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Unix.cs15
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs83
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs473
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs162
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs145
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs129
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs871
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs48
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Unix.cs96
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs198
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs294
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs216
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs371
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs187
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs1235
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/LocaleData.Unix.cs4573
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Unix.cs134
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Windows.cs148
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs750
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/NumberStyles.cs70
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs418
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs198
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/SortKey.cs110
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs83
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs296
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs198
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs234
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs92
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs57
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs55
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs870
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs168
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs658
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs1705
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanStyles.cs13
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs653
-rw-r--r--netcore/System.Private.CoreLib/shared/System/Globalization/UnicodeCategory.cs40
75 files changed, 0 insertions, 43199 deletions
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/BidiCategory.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/BidiCategory.cs
deleted file mode 100644
index abe69508932..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/BidiCategory.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- internal enum BidiCategory
- {
- LeftToRight = 0,
- LeftToRightEmbedding = 1,
- LeftToRightOverride = 2,
- RightToLeft = 3,
- RightToLeftArabic = 4,
- RightToLeftEmbedding = 5,
- RightToLeftOverride = 6,
- PopDirectionalFormat = 7,
- EuropeanNumber = 8,
- EuropeanNumberSeparator = 9,
- EuropeanNumberTerminator = 10,
- ArabicNumber = 11,
- CommonNumberSeparator = 12,
- NonSpacingMark = 13,
- BoundaryNeutral = 14,
- ParagraphSeparator = 15,
- SegmentSeparator = 16,
- Whitespace = 17,
- OtherNeutrals = 18,
- LeftToRightIsolate = 19,
- RightToLeftIsolate = 20,
- FirstStrongIsolate = 21,
- PopDirectionIsolate = 22,
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/Calendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
deleted file mode 100644
index 7d86971a879..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
+++ /dev/null
@@ -1,732 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- // This abstract class represents a calendar. A calendar reckons time in
- // divisions such as weeks, months and years. The number, length and start of
- // the divisions vary in each calendar.
- //
- // Any instant in time can be represented as an n-tuple of numeric values using
- // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0
- // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An implementation of
- // Calendar can map any DateTime value to such an n-tuple and vice versa. The
- // DateTimeFormat class can map between such n-tuples and a textual
- // representation such as "8:46 AM March 20th 1999 AD".
- //
- // Most calendars identify a year which begins the current era. There may be any
- // number of previous eras. The Calendar class identifies the eras as enumerated
- // integers where the current era (CurrentEra) has the value zero.
- //
- // For consistency, the first unit in each interval, e.g. the first month, is
- // assigned the value one.
- // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar,
- // since most of the calendars (or all?) have the same way of calcuating hour/minute/second.
-
- public abstract class Calendar : ICloneable
- {
- // Number of 100ns (10E-7 second) ticks per time unit
- internal const long TicksPerMillisecond = 10000;
- internal const long TicksPerSecond = TicksPerMillisecond * 1000;
- internal const long TicksPerMinute = TicksPerSecond * 60;
- internal const long TicksPerHour = TicksPerMinute * 60;
- internal const long TicksPerDay = TicksPerHour * 24;
-
- // Number of milliseconds per time unit
- internal const int MillisPerSecond = 1000;
- internal const int MillisPerMinute = MillisPerSecond * 60;
- internal const int MillisPerHour = MillisPerMinute * 60;
- internal const int MillisPerDay = MillisPerHour * 24;
-
- // Number of days in a non-leap year
- internal const int DaysPerYear = 365;
- // Number of days in 4 years
- internal const int DaysPer4Years = DaysPerYear * 4 + 1;
- // Number of days in 100 years
- internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
- // Number of days in 400 years
- internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
-
- // Number of days from 1/1/0001 to 1/1/10000
- internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
-
- internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
-
- private int _currentEraValue = -1;
-
- private bool _isReadOnly = false;
-
- public virtual DateTime MinSupportedDateTime => DateTime.MinValue;
-
- public virtual DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public virtual CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.Unknown;
-
- protected Calendar()
- {
- }
-
- internal virtual CalendarId ID => CalendarId.UNINITIALIZED_VALUE;
-
- // Return the Base calendar ID for calendars that didn't have defined data in calendarData
- internal virtual CalendarId BaseCalendarID => ID;
-
- public bool IsReadOnly => _isReadOnly;
-
- public virtual object Clone()
- {
- object o = MemberwiseClone();
- ((Calendar)o).SetReadOnlyState(false);
- return o;
- }
-
- public static Calendar ReadOnly(Calendar calendar)
- {
- if (calendar == null)
- {
- throw new ArgumentNullException(nameof(calendar));
- }
- if (calendar.IsReadOnly)
- {
- return calendar;
- }
-
- Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone());
- clonedCalendar.SetReadOnlyState(true);
- return clonedCalendar;
- }
-
- internal void VerifyWritable()
- {
- if (_isReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- }
-
- internal void SetReadOnlyState(bool readOnly)
- {
- _isReadOnly = readOnly;
- }
-
- /// <summary>
- /// This is used to convert CurrentEra(0) to an appropriate era value.
- /// </summary>
- internal virtual int CurrentEraValue
- {
- get
- {
- // The following code assumes that the current era value can not be -1.
- if (_currentEraValue == -1)
- {
- Debug.Assert(BaseCalendarID != CalendarId.UNINITIALIZED_VALUE, "[Calendar.CurrentEraValue] Expected a real calendar ID");
- _currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra;
- }
-
- return _currentEraValue;
- }
- }
-
- public const int CurrentEra = 0;
-
- internal int _twoDigitYearMax = -1;
-
- internal static void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue)
- {
- if (ticks < minValue.Ticks || ticks > maxValue.Ticks)
- {
- throw new ArgumentException(SR.Format(SR.Argument_ResultCalendarRange, minValue, maxValue));
- }
- }
-
- internal DateTime Add(DateTime time, double value, int scale)
- {
- // From ECMA CLI spec, Partition III, section 3.27:
- //
- // If overflow occurs converting a floating-point type to an integer, or if the floating-point value
- // being converted to an integer is a NaN, the value returned is unspecified.
- //
- // Based upon this, this method should be performing the comparison against the double
- // before attempting a cast. Otherwise, the result is undefined.
- double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5));
- if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis)))
- {
- throw new ArgumentOutOfRangeException(nameof(value), value, SR.ArgumentOutOfRange_AddValue);
- }
-
- long millis = (long)tempMillis;
- long ticks = time.Ticks + millis * TicksPerMillisecond;
- CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return new DateTime(ticks);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding the given number of
- /// milliseconds to the specified DateTime. The result is computed by rounding
- /// the number of milliseconds given by value to the nearest integer,
- /// and adding that interval to the specified DateTime. The value
- /// argument is permitted to be negative.
- /// </summary>
- public virtual DateTime AddMilliseconds(DateTime time, double milliseconds)
- {
- return Add(time, milliseconds, 1);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding a fractional number of
- /// days to the specified DateTime. The result is computed by rounding the
- /// fractional number of days given by value to the nearest
- /// millisecond, and adding that interval to the specified DateTime. The
- /// value argument is permitted to be negative.
- /// </summary>
- public virtual DateTime AddDays(DateTime time, int days)
- {
- return Add(time, days, MillisPerDay);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding a fractional number of
- /// hours to the specified DateTime. The result is computed by rounding the
- /// fractional number of hours given by value to the nearest
- /// millisecond, and adding that interval to the specified DateTime. The
- /// value argument is permitted to be negative.
- /// </summary>
- public virtual DateTime AddHours(DateTime time, int hours)
- {
- return Add(time, hours, MillisPerHour);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding a fractional number of
- /// minutes to the specified DateTime. The result is computed by rounding the
- /// fractional number of minutes given by value to the nearest
- /// millisecond, and adding that interval to the specified DateTime. The
- /// value argument is permitted to be negative.
- /// </summary>
- public virtual DateTime AddMinutes(DateTime time, int minutes)
- {
- return Add(time, minutes, MillisPerMinute);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding the given number of
- /// months to the specified DateTime. The result is computed by incrementing
- /// (or decrementing) the year and month parts of the specified DateTime by
- /// value months, and, if required, adjusting the day part of the
- /// resulting date downwards to the last day of the resulting month in the
- /// resulting year. The time-of-day part of the result is the same as the
- /// time-of-day part of the specified DateTime.
- ///
- /// In more precise terms, considering the specified DateTime to be of the
- /// form y / m / d + t, where y is the
- /// year, m is the month, d is the day, and t is the
- /// time-of-day, the result is y1 / m1 / d1 + t,
- /// where y1 and m1 are computed by adding value months
- /// to y and m, and d1 is the largest value less than
- /// or equal to d that denotes a valid day in month m1 of year
- /// y1.
- /// </summary>
- public abstract DateTime AddMonths(DateTime time, int months);
-
- /// <summary>
- /// Returns the DateTime resulting from adding a number of
- /// seconds to the specified DateTime. The result is computed by rounding the
- /// fractional number of seconds given by value to the nearest
- /// millisecond, and adding that interval to the specified DateTime. The
- /// value argument is permitted to be negative.
- /// </summary>
- public virtual DateTime AddSeconds(DateTime time, int seconds)
- {
- return Add(time, seconds, MillisPerSecond);
- }
-
- // Returns the DateTime resulting from adding a number of
- // weeks to the specified DateTime. The
- // value argument is permitted to be negative.
- public virtual DateTime AddWeeks(DateTime time, int weeks)
- {
- return AddDays(time, weeks * 7);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding the given number of
- /// years to the specified DateTime. The result is computed by incrementing
- /// (or decrementing) the year part of the specified DateTime by value
- /// years. If the month and day of the specified DateTime is 2/29, and if the
- /// resulting year is not a leap year, the month and day of the resulting
- /// DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
- /// parts of the result are the same as those of the specified DateTime.
- /// </summary>
- public abstract DateTime AddYears(DateTime time, int years);
-
- /// <summary>
- /// Returns the day-of-month part of the specified DateTime. The returned
- /// value is an integer between 1 and 31.
- /// </summary>
- public abstract int GetDayOfMonth(DateTime time);
-
- /// <summary>
- /// Returns the day-of-week part of the specified DateTime. The returned value
- /// is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
- /// Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
- /// Thursday, 5 indicates Friday, and 6 indicates Saturday.
- /// </summary>
- public abstract DayOfWeek GetDayOfWeek(DateTime time);
-
- /// <summary>
- /// Returns the day-of-year part of the specified DateTime. The returned value
- /// is an integer between 1 and 366.
- /// </summary>
- public abstract int GetDayOfYear(DateTime time);
-
- /// <summary>
- /// Returns the number of days in the month given by the year and
- /// month arguments.
- /// </summary>
- public virtual int GetDaysInMonth(int year, int month)
- {
- return GetDaysInMonth(year, month, CurrentEra);
- }
-
- /// <summary>
- /// Returns the number of days in the month given by the year and
- /// month arguments for the specified era.
- /// </summary>
- public abstract int GetDaysInMonth(int year, int month, int era);
-
- /// <summary>
- /// Returns the number of days in the year given by the year argument
- /// for the current era.
- /// </summary>
- public virtual int GetDaysInYear(int year)
- {
- return GetDaysInYear(year, CurrentEra);
- }
-
- /// <summary>
- /// Returns the number of days in the year given by the year argument
- /// for the current era.
- /// </summary>
- public abstract int GetDaysInYear(int year, int era);
-
- /// <summary>
- /// Returns the era for the specified DateTime value.
- /// </summary>
- public abstract int GetEra(DateTime time);
-
- /// <summary>
- /// Get the list of era values.
- /// </summary>
- /// <returns>The int array of the era names supported in this calendar or null if era is not used.</returns>
- public abstract int[] Eras { get; }
-
- // Returns the hour part of the specified DateTime. The returned value is an
- // integer between 0 and 23.
- public virtual int GetHour(DateTime time)
- {
- return (int)((time.Ticks / TicksPerHour) % 24);
- }
-
- // Returns the millisecond part of the specified DateTime. The returned value
- // is an integer between 0 and 999.
- public virtual double GetMilliseconds(DateTime time)
- {
- return (double)((time.Ticks / TicksPerMillisecond) % 1000);
- }
-
- // Returns the minute part of the specified DateTime. The returned value is
- // an integer between 0 and 59.
- public virtual int GetMinute(DateTime time)
- {
- return (int)((time.Ticks / TicksPerMinute) % 60);
- }
-
- // Returns the month part of the specified DateTime. The returned value is an
- // integer between 1 and 12.
- public abstract int GetMonth(DateTime time);
-
- // Returns the number of months in the specified year in the current era.
- public virtual int GetMonthsInYear(int year)
- {
- return GetMonthsInYear(year, CurrentEra);
- }
-
- // Returns the number of months in the specified year and era.
- public abstract int GetMonthsInYear(int year, int era);
-
- // Returns the second part of the specified DateTime. The returned value is
- // an integer between 0 and 59.
- public virtual int GetSecond(DateTime time)
- {
- return (int)((time.Ticks / TicksPerSecond) % 60);
- }
-
- /// <summary>
- /// Get the week of year using the FirstDay rule.
- /// </summary>
- /// <remarks>
- /// The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year.
- /// Assume f is the specifed firstDayOfWeek,
- /// and n is the day of week for January 1 of the specified year.
- /// Assign offset = n - f;
- /// Case 1: offset = 0
- /// E.g.
- /// f=1
- /// weekday 0 1 2 3 4 5 6 0 1
- /// date 1/1
- /// week# 1 2
- /// then week of year = (GetDayOfYear(time) - 1) / 7 + 1
- ///
- /// Case 2: offset &lt; 0
- /// e.g.
- /// n=1 f=3
- /// weekday 0 1 2 3 4 5 6 0
- /// date 1/1
- /// week# 1 2
- /// This means that the first week actually starts 5 days before 1/1.
- /// So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1
- /// Case 3: offset > 0
- /// e.g.
- /// f=0 n=2
- /// weekday 0 1 2 3 4 5 6 0 1 2
- /// date 1/1
- /// week# 1 2
- /// This means that the first week actually starts 2 days before 1/1.
- /// So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1
- /// </remarks>
- internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek)
- {
- int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
- // Calculate the day of week for the first day of the year.
- // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year. Note that
- // this value can be less than 0. It's fine since we are making it positive again in calculating offset.
- int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
- int offset = (dayForJan1 - firstDayOfWeek + 14) % 7;
- Debug.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0");
- return (dayOfYear + offset) / 7 + 1;
- }
-
- private int GetWeekOfYearFullDays(DateTime time, int firstDayOfWeek, int fullDays)
- {
- int dayForJan1;
- int offset;
- int day;
-
- int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
-
- // Calculate the number of days between the first day of year (1/1) and the first day of the week.
- // This value will be a positive value from 0 ~ 6. We call this value as "offset".
- //
- // If offset is 0, it means that the 1/1 is the start of the first week.
- // Assume the first day of the week is Monday, it will look like this:
- // Sun Mon Tue Wed Thu Fri Sat
- // 12/31 1/1 1/2 1/3 1/4 1/5 1/6
- // +--> First week starts here.
- //
- // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1.
- // Assume the first day of the week is Monday, it will look like this:
- // Sun Mon Tue Wed Thu Fri Sat
- // 1/1 1/2 1/3 1/4 1/5 1/6 1/7
- // +--> First week starts here.
- //
- // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1.
- // Assume the first day of the week is Monday, it will look like this:
- // Sat Sun Mon Tue Wed Thu Fri Sat
- // 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8
- // +--> First week starts here.
-
- // Day of week is 0-based.
- // Get the day of week for 1/1. This can be derived from the day of week of the target day.
- // Note that we can get a negative value. It's ok since we are going to make it a positive value when calculating the offset.
- dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
-
- // Now, calculate the offset. Subtract the first day of week from the dayForJan1. And make it a positive value.
- offset = (firstDayOfWeek - dayForJan1 + 14) % 7;
- if (offset != 0 && offset >= fullDays)
- {
- // If the offset is greater than the value of fullDays, it means that
- // the first week of the year starts on the week where Jan/1 falls on.
- offset -= 7;
- }
-
- // Calculate the day of year for specified time by taking offset into account.
- day = dayOfYear - offset;
- if (day >= 0)
- {
- // If the day of year value is greater than zero, get the week of year.
- return day / 7 + 1;
- }
-
- // Otherwise, the specified time falls on the week of previous year.
- // Call this method again by passing the last day of previous year.
- // the last day of the previous year may "underflow" to no longer be a valid date time for
- // this calendar if we just subtract so we need the subclass to provide us with
- // that information
- if (time <= MinSupportedDateTime.AddDays(dayOfYear))
- {
- return GetWeekOfYearOfMinSupportedDateTime(firstDayOfWeek, fullDays);
- }
-
- return GetWeekOfYearFullDays(time.AddDays(-(dayOfYear + 1)), firstDayOfWeek, fullDays);
- }
-
- private int GetWeekOfYearOfMinSupportedDateTime(int firstDayOfWeek, int minimumDaysInFirstWeek)
- {
- int dayOfYear = GetDayOfYear(MinSupportedDateTime) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
- int dayOfWeekOfFirstOfYear = (int)GetDayOfWeek(MinSupportedDateTime) - dayOfYear % 7;
-
- // Calculate the offset (how many days from the start of the year to the start of the week)
- int offset = (firstDayOfWeek + 7 - dayOfWeekOfFirstOfYear) % 7;
- if (offset == 0 || offset >= minimumDaysInFirstWeek)
- {
- // First of year falls in the first week of the year
- return 1;
- }
-
- int daysInYearBeforeMinSupportedYear = DaysInYearBeforeMinSupportedYear - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
- int dayOfWeekOfFirstOfPreviousYear = dayOfWeekOfFirstOfYear - 1 - (daysInYearBeforeMinSupportedYear % 7);
-
- // starting from first day of the year, how many days do you have to go forward
- // before getting to the first day of the week?
- int daysInInitialPartialWeek = (firstDayOfWeek - dayOfWeekOfFirstOfPreviousYear + 14) % 7;
- int day = daysInYearBeforeMinSupportedYear - daysInInitialPartialWeek;
- if (daysInInitialPartialWeek >= minimumDaysInFirstWeek)
- {
- // If the offset is greater than the minimum Days in the first week, it means that
- // First of year is part of the first week of the year even though it is only a partial week
- // add another week
- day += 7;
- }
-
- return day / 7 + 1;
- }
-
- protected virtual int DaysInYearBeforeMinSupportedYear => 365;
-
- /// <summary>
- /// Returns the week of year for the specified DateTime. The returned value is an
- /// integer between 1 and 53.
- /// </summary>
- public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
- {
- if (firstDayOfWeek < DayOfWeek.Sunday || firstDayOfWeek > DayOfWeek.Saturday)
- {
- throw new ArgumentOutOfRangeException(
- nameof(firstDayOfWeek),
- firstDayOfWeek,
- SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday));
- }
-
- return rule switch
- {
- CalendarWeekRule.FirstDay => GetFirstDayWeekOfYear(time, (int)firstDayOfWeek),
- CalendarWeekRule.FirstFullWeek => GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 7),
- CalendarWeekRule.FirstFourDayWeek => GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4),
- _ => throw new ArgumentOutOfRangeException(
- nameof(rule),
- rule,
- SR.Format(SR.ArgumentOutOfRange_Range, CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek)),
- };
- }
-
- /// <summary>
- /// Returns the year part of the specified DateTime. The returned value is an
- /// integer between 1 and 9999.
- /// </summary>
- public abstract int GetYear(DateTime time);
-
- /// <summary>
- /// Checks whether a given day in the current era is a leap day.
- /// This method returns true if the date is a leap day, or false if not.
- /// </summary>
- public virtual bool IsLeapDay(int year, int month, int day)
- {
- return IsLeapDay(year, month, day, CurrentEra);
- }
-
- /// <summary>
- /// Checks whether a given day in the specified era is a leap day.
- /// This method returns true if the date is a leap day, or false if not.
- /// </summary>
- public abstract bool IsLeapDay(int year, int month, int day, int era);
-
- /// <summary>
- /// Checks whether a given month in the current era is a leap month.
- /// This method returns true if month is a leap month, or false if not.
- /// </summary>
- public virtual bool IsLeapMonth(int year, int month)
- {
- return IsLeapMonth(year, month, CurrentEra);
- }
-
- /// <summary>
- /// Checks whether a given month in the specified era is a leap month. This method returns true if
- /// month is a leap month, or false if not.
- /// </summary>
- public abstract bool IsLeapMonth(int year, int month, int era);
-
- /// <summary>
- /// Returns the leap month in a calendar year of the current era.
- /// This method returns 0 if this calendar does not have leap month,
- /// or this year is not a leap year.
- /// </summary>
- public virtual int GetLeapMonth(int year)
- {
- return GetLeapMonth(year, CurrentEra);
- }
-
- /// <summary>
- /// Returns the leap month in a calendar year of the specified era.
- /// This method returns 0 if this calendar does not have leap month,
- /// or this year is not a leap year.
- /// </summary>
- public virtual int GetLeapMonth(int year, int era)
- {
- if (!IsLeapYear(year, era))
- {
- return 0;
- }
-
- int monthsCount = GetMonthsInYear(year, era);
- for (int month = 1; month <= monthsCount; month++)
- {
- if (IsLeapMonth(year, month, era))
- {
- return month;
- }
- }
-
- return 0;
- }
-
- /// <summary>
- /// Checks whether a given year in the current era is a leap year.
- /// This method returns true if year is a leap year, or false if not.
- /// </summary>
- public virtual bool IsLeapYear(int year)
- {
- return IsLeapYear(year, CurrentEra);
- }
-
- /// <summary>
- /// Checks whether a given year in the specified era is a leap year.
- /// This method returns true if year is a leap year, or false if not.
- /// </summary>
- public abstract bool IsLeapYear(int year, int era);
-
- /// <summary>
- /// Returns the date and time converted to a DateTime value.
- /// Throws an exception if the n-tuple is invalid.
- /// </summary>
- public virtual DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond)
- {
- return ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra);
- }
-
- /// <summary>
- /// Returns the date and time converted to a DateTime value.
- /// Throws an exception if the n-tuple is invalid.
- /// </summary>
- public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
-
- internal virtual bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
- {
- result = DateTime.MinValue;
- try
- {
- result = ToDateTime(year, month, day, hour, minute, second, millisecond, era);
- return true;
- }
- catch (ArgumentException)
- {
- return false;
- }
- }
-
- internal virtual bool IsValidYear(int year, int era)
- {
- return year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime);
- }
-
- internal virtual bool IsValidMonth(int year, int month, int era)
- {
- return IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era);
- }
-
- internal virtual bool IsValidDay(int year, int month, int day, int era)
- {
- return IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era);
- }
-
- /// <summary>
- /// Returns and assigns the maximum value to represent a two digit year.
- /// This value is the upper boundary of a 100 year range that allows a
- /// two digit year to be properly translated to a four digit year.
- /// For example, if 2029 is the upper boundary, then a two digit value of
- /// 30 should be interpreted as 1930 while a two digit value of 29 should
- /// be interpreted as 2029. In this example, the 100 year range would be
- /// from 1930-2029. See ToFourDigitYear().
- /// </summary>
- public virtual int TwoDigitYearMax
- {
- get => _twoDigitYearMax;
- set
- {
- VerifyWritable();
- _twoDigitYearMax = value;
- }
- }
-
- /// <summary>
- /// Converts the year value to the appropriate century by using the
- /// TwoDigitYearMax property. For example, if the TwoDigitYearMax value is 2029,
- /// then a two digit value of 30 will get converted to 1930 while a two digit
- /// value of 29 will get converted to 2029.
- /// </summary>
- public virtual int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- if (year < 100)
- {
- return (TwoDigitYearMax / 100 - (year > TwoDigitYearMax % 100 ? 1 : 0)) * 100 + year;
- }
-
- // If the year value is above 100, just return the year value. Don't have to do
- // the TwoDigitYearMax comparison.
- return year;
- }
-
- /// <summary>
- /// Return the tick count corresponding to the given hour, minute, second.
- /// Will check the if the parameters are valid.
- /// </summary>
- internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
- {
- if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
- }
- if (millisecond < 0 || millisecond >= MillisPerSecond)
- {
- throw new ArgumentOutOfRangeException(
- nameof(millisecond),
- millisecond,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1));
- }
-
- return InternalGlobalizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
- }
-
- internal static int GetSystemTwoDigitYearSetting(CalendarId CalID, int defaultYearValue)
- {
- int twoDigitYearMax = CalendarData.GetTwoDigitYearMax(CalID);
- return twoDigitYearMax >= 0 ? twoDigitYearMax : defaultYearValue;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarAlgorithmType.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarAlgorithmType.cs
deleted file mode 100644
index 4ddc307abfa..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarAlgorithmType.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public enum CalendarAlgorithmType
- {
- Unknown = 0, // This is the default value to return in the Calendar base class.
- SolarCalendar = 1, // Solar-base calendar, such as GregorianCalendar, jaoaneseCalendar, JulianCalendar, etc.
- // Solar calendars are based on the solar year and seasons.
- LunarCalendar = 2, // Lunar-based calendar, such as Hijri and UmAlQuraCalendar.
- // Lunar calendars are based on the path of the moon. The seasons are not accurately represented.
- LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars.
- // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration,
- // so they align with the seasons as well as lunar events.
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
deleted file mode 100644
index d8ed0072f37..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
+++ /dev/null
@@ -1,460 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Security;
-using System.Text;
-using Internal.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- // needs to be kept in sync with CalendarDataType in System.Globalization.Native
- internal enum CalendarDataType
- {
- Uninitialized = 0,
- NativeName = 1,
- MonthDay = 2,
- ShortDates = 3,
- LongDates = 4,
- YearMonths = 5,
- DayNames = 6,
- AbbrevDayNames = 7,
- MonthNames = 8,
- AbbrevMonthNames = 9,
- SuperShortDayNames = 10,
- MonthGenitiveNames = 11,
- AbbrevMonthGenitiveNames = 12,
- EraNames = 13,
- AbbrevEraNames = 14,
- }
-
- internal partial class CalendarData
- {
- private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
- {
- bool result = true;
-
- // these can return null but are later replaced with String.Empty or other non-nullable value
- result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.NativeName, out this.sNativeName!);
- result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.MonthDay, out this.sMonthDay!);
-
- if (this.sMonthDay != null)
- {
- this.sMonthDay = NormalizeDatePattern(this.sMonthDay);
- }
-
- result &= EnumDatePatterns(localeName, calendarId, CalendarDataType.ShortDates, out this.saShortDates!);
- result &= EnumDatePatterns(localeName, calendarId, CalendarDataType.LongDates, out this.saLongDates!);
- result &= EnumDatePatterns(localeName, calendarId, CalendarDataType.YearMonths, out this.saYearMonths!);
- result &= EnumCalendarInfo(localeName, calendarId, CalendarDataType.DayNames, out this.saDayNames!);
- result &= EnumCalendarInfo(localeName, calendarId, CalendarDataType.AbbrevDayNames, out this.saAbbrevDayNames!);
- result &= EnumCalendarInfo(localeName, calendarId, CalendarDataType.SuperShortDayNames, out this.saSuperShortDayNames!);
-
- string? leapHebrewMonthName = null;
- result &= EnumMonthNames(localeName, calendarId, CalendarDataType.MonthNames, out this.saMonthNames!, ref leapHebrewMonthName);
- if (leapHebrewMonthName != null)
- {
- Debug.Assert(this.saMonthNames != null);
-
- // In Hebrew calendar, get the leap month name Adar II and override the non-leap month 7
- Debug.Assert(calendarId == CalendarId.HEBREW && saMonthNames.Length == 13);
- saLeapYearMonthNames = (string[]) saMonthNames.Clone();
- saLeapYearMonthNames[6] = leapHebrewMonthName;
-
- // The returned data from ICU has 6th month name as 'Adar I' and 7th month name as 'Adar'
- // We need to adjust that in the list used with non-leap year to have 6th month as 'Adar' and 7th month as 'Adar II'
- // note that when formatting non-leap year dates, 7th month shouldn't get used at all.
- saMonthNames[5] = saMonthNames[6];
- saMonthNames[6] = leapHebrewMonthName;
-
- }
- result &= EnumMonthNames(localeName, calendarId, CalendarDataType.AbbrevMonthNames, out this.saAbbrevMonthNames!, ref leapHebrewMonthName);
- result &= EnumMonthNames(localeName, calendarId, CalendarDataType.MonthGenitiveNames, out this.saMonthGenitiveNames!, ref leapHebrewMonthName);
- result &= EnumMonthNames(localeName, calendarId, CalendarDataType.AbbrevMonthGenitiveNames, out this.saAbbrevMonthGenitiveNames!, ref leapHebrewMonthName);
-
- result &= EnumEraNames(localeName, calendarId, CalendarDataType.EraNames, out this.saEraNames!);
- result &= EnumEraNames(localeName, calendarId, CalendarDataType.AbbrevEraNames, out this.saAbbrevEraNames!);
-
- return result;
- }
-
- internal static int GetTwoDigitYearMax(CalendarId calendarId)
- {
- // There is no user override for this value on Linux or in ICU.
- // So just return -1 to use the hard-coded defaults.
- return -1;
- }
-
- // Call native side to figure out which calendars are allowed
- internal static int GetCalendars(string localeName, bool useUserOverride, CalendarId[] calendars)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- // NOTE: there are no 'user overrides' on Linux
- int count = Interop.Globalization.GetCalendars(localeName, calendars, calendars.Length);
-
- // ensure there is at least 1 calendar returned
- if (count == 0 && calendars.Length > 0)
- {
- calendars[0] = CalendarId.GREGORIAN;
- count = 1;
- }
-
- return count;
- }
-
- private static bool SystemSupportsTaiwaneseCalendar()
- {
- return true;
- }
-
- // PAL Layer ends here
-
- private static unsafe bool GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string? calendarString)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- return Interop.CallStringMethod(
- (buffer, locale, id, type) =>
- {
- fixed (char* bufferPtr = buffer)
- {
- return Interop.Globalization.GetCalendarInfo(locale, id, type, bufferPtr, buffer.Length);
- }
- },
- localeName,
- calendarId,
- dataType,
- out calendarString);
- }
-
- private static bool EnumDatePatterns(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[]? datePatterns)
- {
- datePatterns = null;
-
- EnumCalendarsData callbackContext = default;
- callbackContext.Results = new List<string>();
- callbackContext.DisallowDuplicates = true;
- bool result = EnumCalendarInfo(localeName, calendarId, dataType, ref callbackContext);
- if (result)
- {
- List<string> datePatternsList = callbackContext.Results;
-
- for (int i = 0; i < datePatternsList.Count; i++)
- {
- datePatternsList[i] = NormalizeDatePattern(datePatternsList[i]);
- }
-
- if (dataType == CalendarDataType.ShortDates)
- FixDefaultShortDatePattern(datePatternsList);
-
- datePatterns = datePatternsList.ToArray();
- }
-
- return result;
- }
-
- // FixDefaultShortDatePattern will convert the default short date pattern from using 'yy' to using 'yyyy'
- // And will ensure the original pattern still exist in the list.
- // doing that will have the short date pattern format the year as 4-digit number and not just 2-digit number.
- // Example: June 5, 2018 will be formatted to something like 6/5/2018 instead of 6/5/18 fro en-US culture.
- private static void FixDefaultShortDatePattern(List<string> shortDatePatterns)
- {
- if (shortDatePatterns.Count == 0)
- return;
-
- string s = shortDatePatterns[0];
-
- // We are not expecting any pattern have length more than 100.
- // We have to do this check to prevent stack overflow as we allocate the buffer on the stack.
- if (s.Length > 100)
- return;
-
- Span<char> modifiedPattern = stackalloc char[s.Length + 2];
- int index = 0;
-
- while (index < s.Length)
- {
- if (s[index] == '\'')
- {
- do
- {
- modifiedPattern[index] = s[index];
- index++;
- } while (index < s.Length && s[index] != '\'');
-
- if (index >= s.Length)
- return;
- }
- else if (s[index] == 'y')
- {
- modifiedPattern[index] = 'y';
- break;
- }
-
- modifiedPattern[index] = s[index];
- index++;
- }
-
- if (index >= s.Length - 1 || s[index + 1] != 'y')
- {
- // not a 'yy' pattern
- return;
- }
-
- if (index + 2 < s.Length && s[index + 2] == 'y')
- {
- // we have 'yyy' then nothing to do
- return;
- }
-
- // we are sure now we have 'yy' pattern
-
- Debug.Assert(index + 3 < modifiedPattern.Length);
-
- modifiedPattern[index + 1] = 'y'; // second y
- modifiedPattern[index + 2] = 'y'; // third y
- modifiedPattern[index + 3] = 'y'; // fourth y
-
- index += 2;
-
- // Now, copy the rest of the pattern to the destination buffer
- while (index < s.Length)
- {
- modifiedPattern[index + 2] = s[index];
- index++;
- }
-
- shortDatePatterns[0] = modifiedPattern.ToString();
-
- for (int i = 1; i < shortDatePatterns.Count; i++)
- {
- if (shortDatePatterns[i] == shortDatePatterns[0])
- {
- // Found match in the list to the new constructed pattern, then replace it with the original modified pattern
- shortDatePatterns[i] = s;
- return;
- }
- }
-
- // if we come here means the newly constructed pattern not found on the list, then add the original pattern
- shortDatePatterns.Add(s);
- }
-
- /// <summary>
- /// The ICU date format characters are not exactly the same as the .NET date format characters.
- /// NormalizeDatePattern will take in an ICU date pattern and return the equivalent .NET date pattern.
- /// </summary>
- /// <remarks>
- /// see Date Field Symbol Table in http://userguide.icu-project.org/formatparse/datetime
- /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
- /// </remarks>
- private static string NormalizeDatePattern(string input)
- {
- StringBuilder destination = StringBuilderCache.Acquire(input.Length);
-
- int index = 0;
- while (index < input.Length)
- {
- switch (input[index])
- {
- case '\'':
- // single quotes escape characters, like 'de' in es-SP
- // so read verbatim until the next single quote
- destination.Append(input[index++]);
- while (index < input.Length)
- {
- char current = input[index++];
- destination.Append(current);
- if (current == '\'')
- {
- break;
- }
- }
- break;
- case 'E':
- case 'e':
- case 'c':
- // 'E' in ICU is the day of the week, which maps to 3 or 4 'd's in .NET
- // 'e' in ICU is the local day of the week, which has no representation in .NET, but
- // maps closest to 3 or 4 'd's in .NET
- // 'c' in ICU is the stand-alone day of the week, which has no representation in .NET, but
- // maps closest to 3 or 4 'd's in .NET
- NormalizeDayOfWeek(input, destination, ref index);
- break;
- case 'L':
- case 'M':
- // 'L' in ICU is the stand-alone name of the month,
- // which maps closest to 'M' in .NET since it doesn't support stand-alone month names in patterns
- // 'M' in both ICU and .NET is the month,
- // but ICU supports 5 'M's, which is the super short month name
- int occurrences = CountOccurrences(input, input[index], ref index);
- if (occurrences > 4)
- {
- // 5 'L's or 'M's in ICU is the super short name, which maps closest to MMM in .NET
- occurrences = 3;
- }
- destination.Append('M', occurrences);
- break;
- case 'G':
- // 'G' in ICU is the era, which maps to 'g' in .NET
- occurrences = CountOccurrences(input, 'G', ref index);
-
- // it doesn't matter how many 'G's, since .NET only supports 'g' or 'gg', and they
- // have the same meaning
- destination.Append('g');
- break;
- case 'y':
- // a single 'y' in ICU is the year with no padding or trimming.
- // a single 'y' in .NET is the year with 1 or 2 digits
- // so convert any single 'y' to 'yyyy'
- occurrences = CountOccurrences(input, 'y', ref index);
- if (occurrences == 1)
- {
- occurrences = 4;
- }
- destination.Append('y', occurrences);
- break;
- default:
- const string unsupportedDateFieldSymbols = "YuUrQqwWDFg";
- Debug.Assert(!unsupportedDateFieldSymbols.Contains(input[index]),
- $"Encountered an unexpected date field symbol '{input[index]}' from ICU which has no known corresponding .NET equivalent.");
-
- destination.Append(input[index++]);
- break;
- }
- }
-
- return StringBuilderCache.GetStringAndRelease(destination);
- }
-
- private static void NormalizeDayOfWeek(string input, StringBuilder destination, ref int index)
- {
- char dayChar = input[index];
- int occurrences = CountOccurrences(input, dayChar, ref index);
- occurrences = Math.Max(occurrences, 3);
- if (occurrences > 4)
- {
- // 5 and 6 E/e/c characters in ICU is the super short names, which maps closest to ddd in .NET
- occurrences = 3;
- }
-
- destination.Append('d', occurrences);
- }
-
- private static int CountOccurrences(string input, char value, ref int index)
- {
- int startIndex = index;
- while (index < input.Length && input[index] == value)
- {
- index++;
- }
-
- return index - startIndex;
- }
-
- private static bool EnumMonthNames(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[]? monthNames, ref string? leapHebrewMonthName)
- {
- monthNames = null;
-
- EnumCalendarsData callbackContext = default;
- callbackContext.Results = new List<string>();
- bool result = EnumCalendarInfo(localeName, calendarId, dataType, ref callbackContext);
- if (result)
- {
- // the month-name arrays are expected to have 13 elements. If ICU only returns 12, add an
- // extra empty string to fill the array.
- if (callbackContext.Results.Count == 12)
- {
- callbackContext.Results.Add(string.Empty);
- }
-
- if (callbackContext.Results.Count > 13)
- {
- Debug.Assert(calendarId == CalendarId.HEBREW && callbackContext.Results.Count == 14);
-
- if (calendarId == CalendarId.HEBREW)
- {
- leapHebrewMonthName = callbackContext.Results[13];
- }
- callbackContext.Results.RemoveRange(13, callbackContext.Results.Count - 13);
- }
-
- monthNames = callbackContext.Results.ToArray();
- }
-
- return result;
- }
-
- private static bool EnumEraNames(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[]? eraNames)
- {
- bool result = EnumCalendarInfo(localeName, calendarId, dataType, out eraNames);
-
- // .NET expects that only the Japanese calendars have more than 1 era.
- // So for other calendars, only return the latest era.
- if (calendarId != CalendarId.JAPAN && calendarId != CalendarId.JAPANESELUNISOLAR && eraNames?.Length > 0)
- {
- string[] latestEraName = new string[] { eraNames![eraNames.Length - 1] };
- eraNames = latestEraName;
- }
-
- return result;
- }
-
- internal static bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[]? calendarData)
- {
- calendarData = null;
-
- EnumCalendarsData callbackContext = default;
- callbackContext.Results = new List<string>();
- bool result = EnumCalendarInfo(localeName, calendarId, dataType, ref callbackContext);
- if (result)
- {
- calendarData = callbackContext.Results.ToArray();
- }
-
- return result;
- }
-
- private static unsafe bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, ref EnumCalendarsData callbackContext)
- {
- return Interop.Globalization.EnumCalendarInfo(EnumCalendarInfoCallback, localeName, calendarId, dataType, (IntPtr)Unsafe.AsPointer(ref callbackContext));
- }
-
- private static unsafe void EnumCalendarInfoCallback(string calendarString, IntPtr context)
- {
- try
- {
- ref EnumCalendarsData callbackContext = ref Unsafe.As<byte, EnumCalendarsData>(ref *(byte*)context);
-
- if (callbackContext.DisallowDuplicates)
- {
- foreach (string existingResult in callbackContext.Results)
- {
- if (string.Equals(calendarString, existingResult, StringComparison.Ordinal))
- {
- // the value is already in the results, so don't add it again
- return;
- }
- }
- }
-
- callbackContext.Results.Add(calendarString);
- }
- catch (Exception e)
- {
- Debug.Fail(e.ToString());
- // we ignore the managed exceptions here because EnumCalendarInfoCallback will get called from the native code.
- // If we don't ignore the exception here that can cause the runtime to fail fast.
- }
- }
-
- private struct EnumCalendarsData
- {
- public List<string> Results;
- public bool DisallowDuplicates;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
deleted file mode 100644
index 8031df90e0e..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
+++ /dev/null
@@ -1,448 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Collections.Generic;
-using Internal.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- internal partial class CalendarData
- {
- private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- bool ret = true;
-
- uint useOverrides = this.bUseUserOverrides ? 0 : CAL_NOUSEROVERRIDE;
-
- //
- // Windows doesn't support some calendars right now, so remap those.
- //
- switch (calendarId)
- {
- case CalendarId.JAPANESELUNISOLAR: // Data looks like Japanese
- calendarId = CalendarId.JAPAN;
- break;
- case CalendarId.JULIAN: // Data looks like gregorian US
- case CalendarId.CHINESELUNISOLAR: // Algorithmic, so actual data is irrelevent
- case CalendarId.SAKA: // reserved to match Office but not implemented in our code, so data is irrelevent
- case CalendarId.LUNAR_ETO_CHN: // reserved to match Office but not implemented in our code, so data is irrelevent
- case CalendarId.LUNAR_ETO_KOR: // reserved to match Office but not implemented in our code, so data is irrelevent
- case CalendarId.LUNAR_ETO_ROKUYOU: // reserved to match Office but not implemented in our code, so data is irrelevent
- case CalendarId.KOREANLUNISOLAR: // Algorithmic, so actual data is irrelevent
- case CalendarId.TAIWANLUNISOLAR: // Algorithmic, so actual data is irrelevent
- calendarId = CalendarId.GREGORIAN_US;
- break;
- }
-
- //
- // Special handling for some special calendar due to OS limitation.
- // This includes calendar like Taiwan calendar, UmAlQura calendar, etc.
- //
- CheckSpecialCalendar(ref calendarId, ref localeName);
-
- // Numbers
- ret &= CallGetCalendarInfoEx(localeName, calendarId, CAL_ITWODIGITYEARMAX | useOverrides, out this.iTwoDigitYearMax);
-
- // Strings
- ret &= CallGetCalendarInfoEx(localeName, calendarId, CAL_SCALNAME, out this.sNativeName);
- ret &= CallGetCalendarInfoEx(localeName, calendarId, CAL_SMONTHDAY | useOverrides, out this.sMonthDay);
-
- // String Arrays
- // Formats
- ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SSHORTDATE, LOCALE_SSHORTDATE | useOverrides, out this.saShortDates!);
- ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SLONGDATE, LOCALE_SLONGDATE | useOverrides, out this.saLongDates!);
-
- // Get the YearMonth pattern.
- ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SYEARMONTH, LOCALE_SYEARMONTH, out this.saYearMonths!);
-
- // Day & Month Names
- // These are all single calType entries, 1 per day, so we have to make 7 or 13 calls to collect all the names
-
- // Day
- // Note that we're off-by-one since managed starts on sunday and windows starts on monday
- ret &= GetCalendarDayInfo(localeName, calendarId, CAL_SDAYNAME7, out this.saDayNames);
- ret &= GetCalendarDayInfo(localeName, calendarId, CAL_SABBREVDAYNAME7, out this.saAbbrevDayNames);
-
- // Month names
- ret &= GetCalendarMonthInfo(localeName, calendarId, CAL_SMONTHNAME1, out this.saMonthNames);
- ret &= GetCalendarMonthInfo(localeName, calendarId, CAL_SABBREVMONTHNAME1, out this.saAbbrevMonthNames);
-
- //
- // The following LCTYPE are not supported in some platforms. If the call fails,
- // don't return a failure.
- //
- GetCalendarDayInfo(localeName, calendarId, CAL_SSHORTESTDAYNAME7, out this.saSuperShortDayNames);
-
- // Gregorian may have genitive month names
- if (calendarId == CalendarId.GREGORIAN)
- {
- GetCalendarMonthInfo(localeName, calendarId, CAL_SMONTHNAME1 | CAL_RETURN_GENITIVE_NAMES, out this.saMonthGenitiveNames);
- GetCalendarMonthInfo(localeName, calendarId, CAL_SABBREVMONTHNAME1 | CAL_RETURN_GENITIVE_NAMES, out this.saAbbrevMonthGenitiveNames);
- }
-
- // Calendar Parts Names
- // This doesn't get always get localized names for gregorian (not available in windows < 7)
- // so: eg: coreclr on win < 7 won't get these
- CallEnumCalendarInfo(localeName, calendarId, CAL_SERASTRING, 0, out this.saEraNames!);
- CallEnumCalendarInfo(localeName, calendarId, CAL_SABBREVERASTRING, 0, out this.saAbbrevEraNames!);
-
- //
- // Calendar Era Info
- // Note that calendar era data (offsets, etc) is hard coded for each calendar since this
- // data is implementation specific and not dynamic (except perhaps Japanese)
- //
-
- // Clean up the escaping of the formats
- this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates)!;
- this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates)!;
- this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths)!;
- this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay)!;
-
- return ret;
- }
-
- // Get native two digit year max
- internal static int GetTwoDigitYearMax(CalendarId calendarId) =>
- GlobalizationMode.Invariant ? Invariant.iTwoDigitYearMax :
- CallGetCalendarInfoEx(null, calendarId, CAL_ITWODIGITYEARMAX, out int twoDigitYearMax) ? twoDigitYearMax :
- -1;
-
- // Call native side to figure out which calendars are allowed
- internal static int GetCalendars(string localeName, bool useUserOverride, CalendarId[] calendars)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- EnumCalendarsData data = default;
- data.userOverride = 0;
- data.calendars = new List<int>();
-
- // First call GetLocaleInfo if necessary
- if (useUserOverride)
- {
- // They want user overrides, see if the user calendar matches the input calendar
- int userCalendar = CultureData.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE);
-
- // If we got a default, then use it as the first calendar
- if (userCalendar != 0)
- {
- data.userOverride = userCalendar;
- data.calendars.Add(userCalendar);
- }
- }
-
- unsafe
- {
- Interop.Kernel32.EnumCalendarInfoExEx(EnumCalendarsCallback, localeName, ENUM_ALL_CALENDARS, null, CAL_ICALINTVALUE, Unsafe.AsPointer(ref data));
- }
-
- // Copy to the output array
- for (int i = 0; i < Math.Min(calendars.Length, data.calendars.Count); i++)
- calendars[i] = (CalendarId)data.calendars[i];
-
- // Now we have a list of data, return the count
- return data.calendars.Count;
- }
-
- private static bool SystemSupportsTaiwaneseCalendar()
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- // Taiwanese calendar get listed as one of the optional zh-TW calendars only when having zh-TW UI
- return CallGetCalendarInfoEx("zh-TW", CalendarId.TAIWAN, CAL_SCALNAME, out string _);
- }
-
- // PAL Layer ends here
-
- private const uint CAL_RETURN_NUMBER = 0x20000000;
- private const uint CAL_RETURN_GENITIVE_NAMES = 0x10000000;
- private const uint CAL_NOUSEROVERRIDE = 0x80000000;
- private const uint CAL_SCALNAME = 0x00000002;
- private const uint CAL_SMONTHDAY = 0x00000038;
- private const uint CAL_SSHORTDATE = 0x00000005;
- private const uint CAL_SLONGDATE = 0x00000006;
- private const uint CAL_SYEARMONTH = 0x0000002f;
- private const uint CAL_SDAYNAME7 = 0x0000000d;
- private const uint CAL_SABBREVDAYNAME7 = 0x00000014;
- private const uint CAL_SMONTHNAME1 = 0x00000015;
- private const uint CAL_SABBREVMONTHNAME1 = 0x00000022;
- private const uint CAL_SSHORTESTDAYNAME7 = 0x00000037;
- private const uint CAL_SERASTRING = 0x00000004;
- private const uint CAL_SABBREVERASTRING = 0x00000039;
- private const uint CAL_ICALINTVALUE = 0x00000001;
- private const uint CAL_ITWODIGITYEARMAX = 0x00000030;
-
- private const uint ENUM_ALL_CALENDARS = 0xffffffff;
-
- private const uint LOCALE_SSHORTDATE = 0x0000001F;
- private const uint LOCALE_SLONGDATE = 0x00000020;
- private const uint LOCALE_SYEARMONTH = 0x00001006;
- private const uint LOCALE_ICALENDARTYPE = 0x00001009;
-
- ////////////////////////////////////////////////////////////////////////
- //
- // For calendars like Gregorain US/Taiwan/UmAlQura, they are not available
- // in all OS or all localized versions of OS.
- // If OS does not support these calendars, we will fallback by using the
- // appropriate fallback calendar and locale combination to retrieve data from OS.
- //
- // Parameters:
- // __deref_inout pCalendarInt:
- // Pointer to the calendar ID. This will be updated to new fallback calendar ID if needed.
- // __in_out pLocaleNameStackBuffer
- // Pointer to the StackSString object which holds the locale name to be checked.
- // This will be updated to new fallback locale name if needed.
- //
- ////////////////////////////////////////////////////////////////////////
- private static void CheckSpecialCalendar(ref CalendarId calendar, ref string localeName)
- {
- // Gregorian-US isn't always available in the OS, however it is the same for all locales
- switch (calendar)
- {
- case CalendarId.GREGORIAN_US:
- // See if this works
- if (!CallGetCalendarInfoEx(localeName, calendar, CAL_SCALNAME, out string _))
- {
- // Failed, set it to a locale (fa-IR) that's alway has Gregorian US available in the OS
- localeName = "fa-IR";
- }
- // See if that works
- if (!CallGetCalendarInfoEx(localeName, calendar, CAL_SCALNAME, out string _))
- {
- // Failed again, just use en-US with the gregorian calendar
- localeName = "en-US";
- calendar = CalendarId.GREGORIAN;
- }
- break;
- case CalendarId.TAIWAN:
- // Taiwan calendar data is not always in all language version of OS due to Geopolical reasons.
- // It is only available in zh-TW localized versions of Windows.
- // Let's check if OS supports it. If not, fallback to Greogrian localized for Taiwan calendar.
- if (!SystemSupportsTaiwaneseCalendar())
- {
- calendar = CalendarId.GREGORIAN;
- }
- break;
- }
- }
-
- private static bool CallGetCalendarInfoEx(string? localeName, CalendarId calendar, uint calType, out int data)
- {
- return Interop.Kernel32.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType | CAL_RETURN_NUMBER, IntPtr.Zero, 0, out data) != 0;
- }
-
- private static unsafe bool CallGetCalendarInfoEx(string localeName, CalendarId calendar, uint calType, out string data)
- {
- const int BUFFER_LENGTH = 80;
-
- // The maximum size for values returned from GetCalendarInfoEx is 80 characters.
- char* buffer = stackalloc char[BUFFER_LENGTH];
-
- int ret = Interop.Kernel32.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType, (IntPtr)buffer, BUFFER_LENGTH, IntPtr.Zero);
- if (ret > 0)
- {
- if (buffer[ret - 1] == '\0')
- {
- ret--; // don't include the null termination in the string
- }
- data = new string(buffer, 0, ret);
- return true;
- }
- data = "";
- return false;
- }
-
- // Context for EnumCalendarInfoExEx callback.
- private struct EnumData
- {
- public string? userOverride;
- public List<string>? strings;
- }
-
- // EnumCalendarInfoExEx callback itself.
- // [NativeCallable(CallingConvention = CallingConvention.StdCall)]
- private static unsafe Interop.BOOL EnumCalendarInfoCallback(char* lpCalendarInfoString, uint calendar, IntPtr pReserved, void* lParam)
- {
- ref EnumData context = ref Unsafe.As<byte, EnumData>(ref *(byte*)lParam);
- try
- {
- string calendarInfo = new string(lpCalendarInfoString);
-
- // If we had a user override, check to make sure this differs
- if (context.userOverride != calendarInfo)
- {
- Debug.Assert(context.strings != null);
- context.strings.Add(calendarInfo);
- }
-
- return Interop.BOOL.TRUE;
- }
- catch (Exception)
- {
- return Interop.BOOL.FALSE;
- }
- }
-
- private static unsafe bool CallEnumCalendarInfo(string localeName, CalendarId calendar, uint calType, uint lcType, out string[]? data)
- {
- EnumData context = default;
- context.userOverride = null;
- context.strings = new List<string>();
- // First call GetLocaleInfo if necessary
- if ((lcType != 0) && ((lcType & CAL_NOUSEROVERRIDE) == 0) &&
- // Get user locale, see if it matches localeName.
- // Note that they should match exactly, including letter case
- GetUserDefaultLocaleName() == localeName)
- {
- // They want user overrides, see if the user calendar matches the input calendar
- CalendarId userCalendar = (CalendarId)CultureData.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE);
-
- // If the calendars were the same, see if the locales were the same
- if (userCalendar == calendar)
- {
- // They matched, get the user override since locale & calendar match
- string? res = CultureData.GetLocaleInfoEx(localeName, lcType);
-
- // if it succeeded remember the override for the later callers
- if (res != null)
- {
- // Remember this was the override (so we can look for duplicates later in the enum function)
- context.userOverride = res;
-
- // Add to the result strings.
- context.strings.Add(res);
- }
- }
- }
-
- // Now call the enumeration API. Work is done by our callback function
- Interop.Kernel32.EnumCalendarInfoExEx(EnumCalendarInfoCallback, localeName, (uint)calendar, null, calType, Unsafe.AsPointer(ref context));
-
- // Now we have a list of data, fail if we didn't find anything.
- Debug.Assert(context.strings != null);
- if (context.strings.Count == 0)
- {
- data = null;
- return false;
- }
-
- string[] output = context.strings.ToArray();
-
- if (calType == CAL_SABBREVERASTRING || calType == CAL_SERASTRING)
- {
- // Eras are enumerated backwards. (oldest era name first, but
- // Japanese calendar has newest era first in array, and is only
- // calendar with multiple eras)
- Array.Reverse(output, 0, output.Length);
- }
-
- data = output;
-
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Get the native day names
- //
- // NOTE: There's a disparity between .NET & windows day orders, the input day should
- // start with Sunday
- //
- // Parameters:
- // OUT pOutputStrings The output string[] value.
- //
- ////////////////////////////////////////////////////////////////////////
- private static bool GetCalendarDayInfo(string localeName, CalendarId calendar, uint calType, out string[] outputStrings)
- {
- bool result = true;
-
- //
- // We'll need a new array of 7 items
- //
- string[] results = new string[7];
-
- // Get each one of them
- for (int i = 0; i < 7; i++, calType++)
- {
- result &= CallGetCalendarInfoEx(localeName, calendar, calType, out results[i]);
-
- // On the first iteration we need to go from CAL_SDAYNAME7 to CAL_SDAYNAME1, so subtract 7 before the ++ happens
- // This is because the framework starts on sunday and windows starts on monday when counting days
- if (i == 0)
- calType -= 7;
- }
-
- outputStrings = results;
-
- return result;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Get the native month names
- //
- // Parameters:
- // OUT pOutputStrings The output string[] value.
- //
- ////////////////////////////////////////////////////////////////////////
- private static bool GetCalendarMonthInfo(string localeName, CalendarId calendar, uint calType, out string[] outputStrings)
- {
- //
- // We'll need a new array of 13 items
- //
- string[] results = new string[13];
-
- // Get each one of them
- for (int i = 0; i < 13; i++, calType++)
- {
- if (!CallGetCalendarInfoEx(localeName, calendar, calType, out results[i]))
- results[i] = "";
- }
-
- outputStrings = results;
-
- return true;
- }
-
- //
- // struct to help our calendar data enumaration callback
- //
- private struct EnumCalendarsData
- {
- public int userOverride; // user override value (if found)
- public List<int> calendars; // list of calendars found so far
- }
-
- // [NativeCallable(CallingConvention = CallingConvention.StdCall)]
- private static unsafe Interop.BOOL EnumCalendarsCallback(char* lpCalendarInfoString, uint calendar, IntPtr reserved, void* lParam)
- {
- ref EnumCalendarsData context = ref Unsafe.As<byte, EnumCalendarsData>(ref *(byte*)lParam);
- try
- {
- // If we had a user override, check to make sure this differs
- if (context.userOverride != calendar)
- context.calendars.Add((int)calendar);
-
- return Interop.BOOL.TRUE;
- }
- catch (Exception)
- {
- return Interop.BOOL.FALSE;
- }
- }
-
- private static unsafe string GetUserDefaultLocaleName()
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- int result;
- char* localeName = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH];
- result = CultureData.GetLocaleInfoEx(Interop.Kernel32.LOCALE_NAME_USER_DEFAULT, Interop.Kernel32.LOCALE_SNAME, localeName, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH);
-
- return result <= 0 ? "" : new string(localeName, 0, result - 1); // exclude the null termination
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
deleted file mode 100644
index 997cfb406e4..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
+++ /dev/null
@@ -1,380 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- // List of calendar data
- // Note the we cache overrides.
- // Note that localized names (resource names) aren't available from here.
- //
- // NOTE: Calendars depend on the locale name that creates it. Only a few
- // properties are available without locales using CalendarData.GetCalendar(CalendarData)
- //
- internal partial class CalendarData
- {
- // Max calendars
- internal const int MAX_CALENDARS = 23;
-
- // Identity
- internal string sNativeName = null!; // Calendar Name for the locale
-
- // Formats
- internal string[] saShortDates = null!; // Short Data format, default first
- internal string[] saYearMonths = null!; // Year/Month Data format, default first
- internal string[] saLongDates = null!; // Long Data format, default first
- internal string sMonthDay = null!; // Month/Day format
-
- // Calendar Parts Names
- internal string[] saEraNames = null!; // Names of Eras
- internal string[] saAbbrevEraNames = null!; // Abbreviated Era Names
- internal string[] saAbbrevEnglishEraNames = null!; // Abbreviated Era Names in English
- internal string[] saDayNames = null!; // Day Names, null to use locale data, starts on Sunday
- internal string[] saAbbrevDayNames = null!; // Abbrev Day Names, null to use locale data, starts on Sunday
- internal string[] saSuperShortDayNames = null!; // Super short Day of week names
- internal string[] saMonthNames = null!; // Month Names (13)
- internal string[] saAbbrevMonthNames = null!; // Abbrev Month Names (13)
- internal string[] saMonthGenitiveNames = null!; // Genitive Month Names (13)
- internal string[] saAbbrevMonthGenitiveNames = null!; // Genitive Abbrev Month Names (13)
- internal string[] saLeapYearMonthNames = null!; // Multiple strings for the month names in a leap year.
-
- // Integers at end to make marshaller happier
- internal int iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
- internal int iCurrentEra = 0; // current era # (usually 1)
-
- // Use overrides?
- internal bool bUseUserOverrides; // True if we want user overrides.
-
- // Static invariant for the invariant locale
- internal static readonly CalendarData Invariant = CreateInvariant();
-
- // Private constructor
- private CalendarData()
- {
- }
-
- // Invariant factory
- private static CalendarData CreateInvariant()
- {
- // Set our default/gregorian US calendar data
- // Calendar IDs are 1-based, arrays are 0 based.
- CalendarData invariant = new CalendarData();
-
- // Set default data for calendar
- // Note that we don't load resources since this IS NOT supposed to change (by definition)
- invariant.sNativeName = "Gregorian Calendar"; // Calendar Name
-
- // Year
- invariant.iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
- invariant.iCurrentEra = 1; // Current era #
-
- // Formats
- invariant.saShortDates = new string[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
- invariant.saLongDates = new string[] { "dddd, dd MMMM yyyy" }; // long date format
- invariant.saYearMonths = new string[] { "yyyy MMMM" }; // year month format
- invariant.sMonthDay = "MMMM dd"; // Month day pattern
-
- // Calendar Parts Names
- invariant.saEraNames = new string[] { "A.D." }; // Era names
- invariant.saAbbrevEraNames = new string[] { "AD" }; // Abbreviated Era names
- invariant.saAbbrevEnglishEraNames = new string[] { "AD" }; // Abbreviated era names in English
- invariant.saDayNames = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; // day names
- invariant.saAbbrevDayNames = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
- invariant.saSuperShortDayNames = new string[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
- invariant.saMonthNames = new string[] { "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December", string.Empty }; // month names
- invariant.saAbbrevMonthNames = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", string.Empty }; // abbreviated month names
- invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant)
- invariant.saAbbrevMonthGenitiveNames = invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
- invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant)
-
- invariant.bUseUserOverrides = false;
-
- return invariant;
- }
-
- //
- // Get a bunch of data for a calendar
- //
- internal CalendarData(string localeName, CalendarId calendarId, bool bUseUserOverrides)
- {
- this.bUseUserOverrides = bUseUserOverrides;
-
- Debug.Assert(!GlobalizationMode.Invariant);
-
- if (!LoadCalendarDataFromSystem(localeName, calendarId))
- {
- // LoadCalendarDataFromSystem sometimes can fail on Linux if the installed ICU package is missing some resources.
- // The ICU package can miss some resources in some cases like if someone compile and build the ICU package manually or ICU has a regression.
-
- // Something failed, try invariant for missing parts
- // This is really not good, but we don't want the callers to crash.
- this.sNativeName ??= string.Empty; // Calendar Name for the locale.
-
- // Formats
- this.saShortDates ??= Invariant.saShortDates; // Short Data format, default first
- this.saYearMonths ??= Invariant.saYearMonths; // Year/Month Data format, default first
- this.saLongDates ??= Invariant.saLongDates; // Long Data format, default first
- this.sMonthDay ??= Invariant.sMonthDay; // Month/Day format
-
- // Calendar Parts Names
- this.saEraNames ??= Invariant.saEraNames; // Names of Eras
- this.saAbbrevEraNames ??= Invariant.saAbbrevEraNames; // Abbreviated Era Names
- this.saAbbrevEnglishEraNames ??= Invariant.saAbbrevEnglishEraNames; // Abbreviated Era Names in English
- this.saDayNames ??= Invariant.saDayNames; // Day Names, null to use locale data, starts on Sunday
- this.saAbbrevDayNames ??= Invariant.saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
- this.saSuperShortDayNames ??= Invariant.saSuperShortDayNames; // Super short Day of week names
- this.saMonthNames ??= Invariant.saMonthNames; // Month Names (13)
- this.saAbbrevMonthNames ??= Invariant.saAbbrevMonthNames; // Abbrev Month Names (13)
- // Genitive and Leap names can follow the fallback below
- }
-
- if (calendarId == CalendarId.TAIWAN)
- {
- if (SystemSupportsTaiwaneseCalendar())
- {
- // We got the month/day names from the OS (same as gregorian), but the native name is wrong
- this.sNativeName = "\x4e2d\x83ef\x6c11\x570b\x66c6";
- }
- else
- {
- this.sNativeName = string.Empty;
- }
- }
-
- // Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc)
- if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || string.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
- this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant)
- if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
- this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
- if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || string.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
- this.saLeapYearMonthNames = this.saMonthNames;
-
- InitializeEraNames(localeName, calendarId);
-
- InitializeAbbreviatedEraNames(localeName, calendarId);
-
- // Abbreviated English Era Names are only used for the Japanese calendar.
- if (calendarId == CalendarId.JAPAN)
- {
- this.saAbbrevEnglishEraNames = JapaneseCalendar.EnglishEraNames();
- }
- else
- {
- // For all others just use the an empty string (doesn't matter we'll never ask for it for other calendars)
- this.saAbbrevEnglishEraNames = new string[] { "" };
- }
-
- // Japanese is the only thing with > 1 era. Its current era # is how many ever
- // eras are in the array. (And the others all have 1 string in the array)
- this.iCurrentEra = this.saEraNames.Length;
- }
-
- private void InitializeEraNames(string localeName, CalendarId calendarId)
- {
- // Note that the saEraNames only include "A.D." We don't have localized names for other calendars available from windows
- switch (calendarId)
- {
- // For Localized Gregorian we really expect the data from the OS.
- case CalendarId.GREGORIAN:
- // Fallback for CoreCLR < Win7 or culture.dll missing
- if (this.saEraNames == null || this.saEraNames.Length == 0 || string.IsNullOrEmpty(this.saEraNames[0]))
- {
- this.saEraNames = new string[] { "A.D." };
- }
- break;
-
- // The rest of the calendars have constant data, so we'll just use that
- case CalendarId.GREGORIAN_US:
- case CalendarId.JULIAN:
- this.saEraNames = new string[] { "A.D." };
- break;
- case CalendarId.HEBREW:
- this.saEraNames = new string[] { "C.E." };
- break;
- case CalendarId.HIJRI:
- case CalendarId.UMALQURA:
- if (localeName == "dv-MV")
- {
- // Special case for Divehi
- this.saEraNames = new string[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
- }
- else
- {
- this.saEraNames = new string[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
- }
- break;
- case CalendarId.GREGORIAN_ARABIC:
- case CalendarId.GREGORIAN_XLIT_ENGLISH:
- case CalendarId.GREGORIAN_XLIT_FRENCH:
- // These are all the same:
- this.saEraNames = new string[] { "\x0645" };
- break;
-
- case CalendarId.GREGORIAN_ME_FRENCH:
- this.saEraNames = new string[] { "ap. J.-C." };
- break;
-
- case CalendarId.TAIWAN:
- if (SystemSupportsTaiwaneseCalendar())
- {
- this.saEraNames = new string[] { "\x4e2d\x83ef\x6c11\x570b" };
- }
- else
- {
- this.saEraNames = new string[] { string.Empty };
- }
- break;
-
- case CalendarId.KOREA:
- this.saEraNames = new string[] { "\xb2e8\xae30" };
- break;
-
- case CalendarId.THAI:
- this.saEraNames = new string[] { "\x0e1e\x002e\x0e28\x002e" };
- break;
-
- case CalendarId.JAPAN:
- case CalendarId.JAPANESELUNISOLAR:
- this.saEraNames = JapaneseCalendar.EraNames();
- break;
-
- case CalendarId.PERSIAN:
- if (this.saEraNames == null || this.saEraNames.Length == 0 || string.IsNullOrEmpty(this.saEraNames[0]))
- {
- this.saEraNames = new string[] { "\x0647\x002e\x0634" };
- }
- break;
-
- default:
- // Most calendars are just "A.D."
- this.saEraNames = Invariant.saEraNames;
- break;
- }
- }
-
- private void InitializeAbbreviatedEraNames(string localeName, CalendarId calendarId)
- {
- // Note that the saAbbrevEraNames only include "AD" We don't have localized names for other calendars available from windows
- switch (calendarId)
- {
- // For Localized Gregorian we really expect the data from the OS.
- case CalendarId.GREGORIAN:
- // Fallback for CoreCLR < Win7 or culture.dll missing
- if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevEraNames[0]))
- {
- this.saAbbrevEraNames = new string[] { "AD" };
- }
- break;
-
- // The rest of the calendars have constant data, so we'll just use that
- case CalendarId.GREGORIAN_US:
- case CalendarId.JULIAN:
- this.saAbbrevEraNames = new string[] { "AD" };
- break;
- case CalendarId.JAPAN:
- case CalendarId.JAPANESELUNISOLAR:
- this.saAbbrevEraNames = JapaneseCalendar.AbbrevEraNames();
- break;
- case CalendarId.HIJRI:
- case CalendarId.UMALQURA:
- if (localeName == "dv-MV")
- {
- // Special case for Divehi
- this.saAbbrevEraNames = new string[] { "\x0780\x002e" };
- }
- else
- {
- this.saAbbrevEraNames = new string[] { "\x0647\x0640" };
- }
- break;
- case CalendarId.TAIWAN:
- // Get era name and abbreviate it
- this.saAbbrevEraNames = new string[1];
- if (this.saEraNames[0].Length == 4)
- {
- this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2, 2);
- }
- else
- {
- this.saAbbrevEraNames[0] = this.saEraNames[0];
- }
- break;
-
- case CalendarId.PERSIAN:
- if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevEraNames[0]))
- {
- this.saAbbrevEraNames = this.saEraNames;
- }
- break;
-
- default:
- // Most calendars just use the full name
- this.saAbbrevEraNames = this.saEraNames;
- break;
- }
- }
-
- internal static CalendarData GetCalendarData(CalendarId calendarId)
- {
- //
- // Get a calendar.
- // Unfortunately we depend on the locale in the OS, so we need a locale
- // no matter what. So just get the appropriate calendar from the
- // appropriate locale here
- //
-
- // Get a culture name
- // TODO: Note that this doesn't handle the new calendars (lunisolar, etc)
- string culture = CalendarIdToCultureName(calendarId);
-
- // Return our calendar
- return CultureInfo.GetCultureInfo(culture)._cultureData.GetCalendar(calendarId);
- }
-
- private static string CalendarIdToCultureName(CalendarId calendarId)
- {
- switch (calendarId)
- {
- case CalendarId.GREGORIAN_US:
- return "fa-IR"; // "fa-IR" Iran
-
- case CalendarId.JAPAN:
- return "ja-JP"; // "ja-JP" Japan
-
- case CalendarId.TAIWAN:
- return "zh-TW"; // zh-TW Taiwan
-
- case CalendarId.KOREA:
- return "ko-KR"; // "ko-KR" Korea
-
- case CalendarId.HIJRI:
- case CalendarId.GREGORIAN_ARABIC:
- case CalendarId.UMALQURA:
- return "ar-SA"; // "ar-SA" Saudi Arabia
-
- case CalendarId.THAI:
- return "th-TH"; // "th-TH" Thailand
-
- case CalendarId.HEBREW:
- return "he-IL"; // "he-IL" Israel
-
- case CalendarId.GREGORIAN_ME_FRENCH:
- return "ar-DZ"; // "ar-DZ" Algeria
-
- case CalendarId.GREGORIAN_XLIT_ENGLISH:
- case CalendarId.GREGORIAN_XLIT_FRENCH:
- return "ar-IQ"; // "ar-IQ"; Iraq
-
- default:
- // Default to gregorian en-US
- break;
- }
-
- return "en-US";
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarWeekRule.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarWeekRule.cs
deleted file mode 100644
index 13567afba1a..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendarWeekRule.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public enum CalendarWeekRule
- {
- FirstDay = 0, // Week 1 begins on the first day of the year
-
- FirstFullWeek = 1, // Week 1 begins on first FirstDayOfWeek not before the first day of the year
-
- FirstFourDayWeek = 2 // Week 1 begins on first FirstDayOfWeek such that FirstDayOfWeek+3 is not before the first day of the year
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendricalCalculationsHelper.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CalendricalCalculationsHelper.cs
deleted file mode 100644
index 99caf6ba1d1..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CalendricalCalculationsHelper.cs
+++ /dev/null
@@ -1,412 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- internal static class CalendricalCalculationsHelper
- {
- private const double FullCircleOfArc = 360.0; // 360.0;
- private const int HalfCircleOfArc = 180;
- private const double TwelveHours = 0.5; // half a day
- private const double Noon2000Jan01 = 730120.5;
- internal const double MeanTropicalYearInDays = 365.242189;
- private const double MeanSpeedOfSun = MeanTropicalYearInDays / FullCircleOfArc;
- private const double LongitudeSpring = 0.0;
- private const double TwoDegreesAfterSpring = 2.0;
- private const int SecondsPerDay = 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds
-
- private const int DaysInUniformLengthCentury = 36525;
- private const int SecondsPerMinute = 60;
- private const int MinutesPerDegree = 60;
-
- private static readonly long s_startOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1));
- private static readonly long s_startOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1));
-
- private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 };
- private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 };
- private static readonly double[] s_coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 };
- private static readonly double[] s_coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 };
- private static readonly double[] s_lambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 };
- private static readonly double[] s_anomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 };
- private static readonly double[] s_eccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 };
- private static readonly double[] s_coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) };
- private static readonly double[] s_coefficientsA = new double[] { 124.90, -1934.134, 0.002063 };
- private static readonly double[] s_coefficientsB = new double[] { 201.11, 72001.5377, 0.00057 };
-
- private static double RadiansFromDegrees(double degree)
- {
- return degree * Math.PI / 180;
- }
-
- private static double SinOfDegree(double degree)
- {
- return Math.Sin(RadiansFromDegrees(degree));
- }
-
- private static double CosOfDegree(double degree)
- {
- return Math.Cos(RadiansFromDegrees(degree));
- }
- private static double TanOfDegree(double degree)
- {
- return Math.Tan(RadiansFromDegrees(degree));
- }
-
- public static double Angle(int degrees, int minutes, double seconds)
- {
- return ((seconds / SecondsPerMinute + minutes) / MinutesPerDegree) + degrees;
- }
-
- private static double Obliquity(double julianCenturies)
- {
- return PolynomialSum(s_coefficients, julianCenturies);
- }
-
- internal static long GetNumberOfDays(DateTime date)
- {
- return date.Ticks / GregorianCalendar.TicksPerDay;
- }
-
- private static int GetGregorianYear(double numberOfDays)
- {
- return new DateTime(Math.Min((long)(Math.Floor(numberOfDays) * GregorianCalendar.TicksPerDay), DateTime.MaxValue.Ticks)).Year;
- }
-
- private enum CorrectionAlgorithm
- {
- Default,
- Year1988to2019,
- Year1900to1987,
- Year1800to1899,
- Year1700to1799,
- Year1620to1699
- }
-
- private struct EphemerisCorrectionAlgorithmMap
- {
- public EphemerisCorrectionAlgorithmMap(int year, CorrectionAlgorithm algorithm)
- {
- _lowestYear = year;
- _algorithm = algorithm;
- }
-
- internal int _lowestYear;
- internal CorrectionAlgorithm _algorithm;
- }
-
- private static readonly EphemerisCorrectionAlgorithmMap[] s_ephemerisCorrectionTable = new EphemerisCorrectionAlgorithmMap[]
- {
- // lowest year that starts algorithm, algorithm to use
- new EphemerisCorrectionAlgorithmMap(2020, CorrectionAlgorithm.Default),
- new EphemerisCorrectionAlgorithmMap(1988, CorrectionAlgorithm.Year1988to2019),
- new EphemerisCorrectionAlgorithmMap(1900, CorrectionAlgorithm.Year1900to1987),
- new EphemerisCorrectionAlgorithmMap(1800, CorrectionAlgorithm.Year1800to1899),
- new EphemerisCorrectionAlgorithmMap(1700, CorrectionAlgorithm.Year1700to1799),
- new EphemerisCorrectionAlgorithmMap(1620, CorrectionAlgorithm.Year1620to1699),
- new EphemerisCorrectionAlgorithmMap(int.MinValue, CorrectionAlgorithm.Default) // default must be last
- };
-
- private static double Reminder(double divisor, double dividend)
- {
- double whole = Math.Floor(divisor / dividend);
- return divisor - (dividend * whole);
- }
-
- private static double NormalizeLongitude(double longitude)
- {
- longitude = Reminder(longitude, FullCircleOfArc);
- if (longitude < 0)
- {
- longitude += FullCircleOfArc;
- }
- return longitude;
- }
-
- public static double AsDayFraction(double longitude)
- {
- return longitude / FullCircleOfArc;
- }
-
- private static double PolynomialSum(double[] coefficients, double indeterminate)
- {
- double sum = coefficients[0];
- double indeterminateRaised = 1;
- for (int i = 1; i < coefficients.Length; i++)
- {
- indeterminateRaised *= indeterminate;
- sum += (coefficients[i] * indeterminateRaised);
- }
-
- return sum;
- }
-
- private static double CenturiesFrom1900(int gregorianYear)
- {
- long july1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 7, 1));
- return (double)(july1stOfYear - s_startOf1900Century) / DaysInUniformLengthCentury;
- }
-
- // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges
- private static double DefaultEphemerisCorrection(int gregorianYear)
- {
- Debug.Assert(gregorianYear < 1620 || 2020 <= gregorianYear);
- long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1));
- double daysSinceStartOf1810 = january1stOfYear - s_startOf1810;
- double x = TwelveHours + daysSinceStartOf1810;
- return ((Math.Pow(x, 2) / 41048480) - 15) / SecondsPerDay;
- }
-
- private static double EphemerisCorrection1988to2019(int gregorianYear)
- {
- Debug.Assert(1988 <= gregorianYear && gregorianYear <= 2019);
- return (double)(gregorianYear - 1933) / SecondsPerDay;
- }
-
- private static double EphemerisCorrection1900to1987(int gregorianYear)
- {
- Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987);
- double centuriesFrom1900 = CenturiesFrom1900(gregorianYear);
- return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900);
- }
-
- private static double EphemerisCorrection1800to1899(int gregorianYear)
- {
- Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899);
- double centuriesFrom1900 = CenturiesFrom1900(gregorianYear);
- return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900);
- }
-
- private static double EphemerisCorrection1700to1799(int gregorianYear)
- {
- Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799);
- double yearsSince1700 = gregorianYear - 1700;
- return PolynomialSum(s_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;
- }
-
- // ephemeris-correction: correction to account for the slowing down of the rotation of the earth
- private static double EphemerisCorrection(double time)
- {
- int year = GetGregorianYear(time);
- foreach (EphemerisCorrectionAlgorithmMap map in s_ephemerisCorrectionTable)
- {
- if (map._lowestYear <= year)
- {
- switch (map._algorithm)
- {
- case CorrectionAlgorithm.Default: return DefaultEphemerisCorrection(year);
- case CorrectionAlgorithm.Year1988to2019: return EphemerisCorrection1988to2019(year);
- case CorrectionAlgorithm.Year1900to1987: return EphemerisCorrection1900to1987(year);
- case CorrectionAlgorithm.Year1800to1899: return EphemerisCorrection1800to1899(year);
- case CorrectionAlgorithm.Year1700to1799: return EphemerisCorrection1700to1799(year);
- case CorrectionAlgorithm.Year1620to1699: return EphemerisCorrection1620to1699(year);
- }
-
- break; // break the loop and assert eventually
- }
- }
-
- Debug.Fail("Not expected to come here");
- return DefaultEphemerisCorrection(year);
- }
-
- public static double JulianCenturies(double moment)
- {
- double dynamicalMoment = moment + EphemerisCorrection(moment);
- return (dynamicalMoment - Noon2000Jan01) / DaysInUniformLengthCentury;
- }
-
- private static bool IsNegative(double value)
- {
- return Math.Sign(value) == -1;
- }
-
- private static double CopySign(double value, double sign)
- {
- return (IsNegative(value) == IsNegative(sign)) ? value : -value;
- }
-
- // equation-of-time; approximate the difference between apparent solar time and mean solar time
- // formal definition is EOT = GHA - GMHA
- // GHA is the Greenwich Hour Angle of the apparent (actual) Sun
- // GMHA is the Greenwich Mean Hour Angle of the mean (fictitious) Sun
- // http://www.esrl.noaa.gov/gmd/grad/solcalc/
- // http://en.wikipedia.org/wiki/Equation_of_time
- 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 epsilon = Obliquity(julianCenturies);
- double tanHalfEpsilon = TanOfDegree(epsilon / 2);
- double y = tanHalfEpsilon * tanHalfEpsilon;
-
- double dividend = ((y * SinOfDegree(2 * lambda))
- - (2 * eccentricity * SinOfDegree(anomaly))
- + (4 * eccentricity * y * SinOfDegree(anomaly) * CosOfDegree(2 * lambda))
- - (0.5 * Math.Pow(y, 2) * SinOfDegree(4 * lambda))
- - (1.25 * Math.Pow(eccentricity, 2) * SinOfDegree(2 * anomaly)));
- const double Divisor = 2 * Math.PI;
- double equation = dividend / Divisor;
-
- // approximation of equation of time is not valid for dates that are many millennia in the past or future
- // thus limited to a half day
- return CopySign(Math.Min(Math.Abs(equation), TwelveHours), equation);
- }
-
- private static double AsLocalTime(double apparentMidday, double longitude)
- {
- // slightly inaccurate since equation of time takes mean time not apparent time as its argument, but the difference is negligible
- double universalTime = apparentMidday - AsDayFraction(longitude);
- return apparentMidday - EquationOfTime(universalTime);
- }
-
- // midday
- public static double Midday(double date, double longitude)
- {
- return AsLocalTime(date + TwelveHours, longitude) - AsDayFraction(longitude);
- }
-
- private static double InitLongitude(double longitude)
- {
- return NormalizeLongitude(longitude + HalfCircleOfArc) - HalfCircleOfArc;
- }
-
- // midday-in-tehran
- public static double MiddayAtPersianObservationSite(double date)
- {
- return Midday(date, InitLongitude(52.5)); // 52.5 degrees east - longitude of UTC+3:30 which defines Iranian Standard Time
- }
-
- private static double PeriodicTerm(double julianCenturies, int x, double y, double z)
- {
- return x * SinOfDegree(y + z * julianCenturies);
- }
-
- private static double SumLongSequenceOfPeriodicTerms(double julianCenturies)
- {
- double sum = 0.0;
- sum += PeriodicTerm(julianCenturies, 403406, 270.54861, 0.9287892);
- sum += PeriodicTerm(julianCenturies, 195207, 340.19128, 35999.1376958);
- sum += PeriodicTerm(julianCenturies, 119433, 63.91854, 35999.4089666);
- sum += PeriodicTerm(julianCenturies, 112392, 331.2622, 35998.7287385);
- sum += PeriodicTerm(julianCenturies, 3891, 317.843, 71998.20261);
- sum += PeriodicTerm(julianCenturies, 2819, 86.631, 71998.4403);
- sum += PeriodicTerm(julianCenturies, 1721, 240.052, 36000.35726);
- sum += PeriodicTerm(julianCenturies, 660, 310.26, 71997.4812);
- sum += PeriodicTerm(julianCenturies, 350, 247.23, 32964.4678);
- sum += PeriodicTerm(julianCenturies, 334, 260.87, -19.441);
- sum += PeriodicTerm(julianCenturies, 314, 297.82, 445267.1117);
- sum += PeriodicTerm(julianCenturies, 268, 343.14, 45036.884);
- sum += PeriodicTerm(julianCenturies, 242, 166.79, 3.1008);
- sum += PeriodicTerm(julianCenturies, 234, 81.53, 22518.4434);
- sum += PeriodicTerm(julianCenturies, 158, 3.5, -19.9739);
- sum += PeriodicTerm(julianCenturies, 132, 132.75, 65928.9345);
- sum += PeriodicTerm(julianCenturies, 129, 182.95, 9038.0293);
- sum += PeriodicTerm(julianCenturies, 114, 162.03, 3034.7684);
- sum += PeriodicTerm(julianCenturies, 99, 29.8, 33718.148);
- sum += PeriodicTerm(julianCenturies, 93, 266.4, 3034.448);
- sum += PeriodicTerm(julianCenturies, 86, 249.2, -2280.773);
- sum += PeriodicTerm(julianCenturies, 78, 157.6, 29929.992);
- sum += PeriodicTerm(julianCenturies, 72, 257.8, 31556.493);
- sum += PeriodicTerm(julianCenturies, 68, 185.1, 149.588);
- sum += PeriodicTerm(julianCenturies, 64, 69.9, 9037.75);
- sum += PeriodicTerm(julianCenturies, 46, 8.0, 107997.405);
- sum += PeriodicTerm(julianCenturies, 38, 197.1, -4444.176);
- sum += PeriodicTerm(julianCenturies, 37, 250.4, 151.771);
- sum += PeriodicTerm(julianCenturies, 32, 65.3, 67555.316);
- sum += PeriodicTerm(julianCenturies, 29, 162.7, 31556.08);
- sum += PeriodicTerm(julianCenturies, 28, 341.5, -4561.54);
- sum += PeriodicTerm(julianCenturies, 27, 291.6, 107996.706);
- sum += PeriodicTerm(julianCenturies, 27, 98.5, 1221.655);
- sum += PeriodicTerm(julianCenturies, 25, 146.7, 62894.167);
- sum += PeriodicTerm(julianCenturies, 24, 110.0, 31437.369);
- sum += PeriodicTerm(julianCenturies, 21, 5.2, 14578.298);
- sum += PeriodicTerm(julianCenturies, 21, 342.6, -31931.757);
- sum += PeriodicTerm(julianCenturies, 20, 230.9, 34777.243);
- sum += PeriodicTerm(julianCenturies, 18, 256.1, 1221.999);
- sum += PeriodicTerm(julianCenturies, 17, 45.3, 62894.511);
- sum += PeriodicTerm(julianCenturies, 14, 242.9, -4442.039);
- sum += PeriodicTerm(julianCenturies, 13, 115.2, 107997.909);
- sum += PeriodicTerm(julianCenturies, 13, 151.8, 119.066);
- sum += PeriodicTerm(julianCenturies, 13, 285.3, 16859.071);
- sum += PeriodicTerm(julianCenturies, 12, 53.3, -4.578);
- sum += PeriodicTerm(julianCenturies, 10, 126.6, 26895.292);
- sum += PeriodicTerm(julianCenturies, 10, 205.7, -39.127);
- sum += PeriodicTerm(julianCenturies, 10, 85.9, 12297.536);
- sum += PeriodicTerm(julianCenturies, 10, 146.1, 90073.778);
- return sum;
- }
-
- private static double Aberration(double julianCenturies)
- {
- return (0.0000974 * CosOfDegree(177.63 + (35999.01848 * julianCenturies))) - 0.005575;
- }
-
- private static double Nutation(double julianCenturies)
- {
- double a = PolynomialSum(s_coefficientsA, julianCenturies);
- double b = PolynomialSum(s_coefficientsB, julianCenturies);
- return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b));
- }
-
- public static double Compute(double time)
- {
- double julianCenturies = JulianCenturies(time);
- double lambda = 282.7771834
- + (36000.76953744 * julianCenturies)
- + (0.000005729577951308232 * SumLongSequenceOfPeriodicTerms(julianCenturies));
-
- double longitude = lambda + Aberration(julianCenturies) + Nutation(julianCenturies);
- return InitLongitude(longitude);
- }
-
- public static double AsSeason(double longitude)
- {
- return (longitude < 0) ? (longitude + FullCircleOfArc) : longitude;
- }
-
- private static double EstimatePrior(double longitude, double time)
- {
- double timeSunLastAtLongitude = time - (MeanSpeedOfSun * AsSeason(InitLongitude(Compute(time) - longitude)));
- double longitudeErrorDelta = InitLongitude(Compute(timeSunLastAtLongitude) - longitude);
- return Math.Min(time, timeSunLastAtLongitude - (MeanSpeedOfSun * longitudeErrorDelta));
- }
-
- // persian-new-year-on-or-before
- // number of days is the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
- // 1/1/0001 is absolute date 1.
- internal static long PersianNewYearOnOrBefore(long numberOfDays)
- {
- double date = (double)numberOfDays;
-
- double approx = EstimatePrior(LongitudeSpring, MiddayAtPersianObservationSite(date));
- long lowerBoundNewYearDay = (long)Math.Floor(approx) - 1;
- long upperBoundNewYearDay = lowerBoundNewYearDay + 3; // estimate is generally within a day of the actual occurrence (at the limits, the error expands, since the calculations rely on the mean tropical year which changes...)
- long day = lowerBoundNewYearDay;
- for (; day != upperBoundNewYearDay; ++day)
- {
- double midday = MiddayAtPersianObservationSite((double)day);
- double l = Compute(midday);
- if ((LongitudeSpring <= l) && (l <= TwoDegreesAfterSpring))
- {
- break;
- }
- }
- Debug.Assert(day != upperBoundNewYearDay);
-
- return day - 1;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
deleted file mode 100644
index 59ccd9e30da..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
+++ /dev/null
@@ -1,321 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers.Binary;
-using System.Diagnostics;
-using System.Text;
-using Internal.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class implements a set of methods for retrieving character type
- /// information. Character type information is independent of culture
- /// and region.
- /// </summary>
- public static partial class CharUnicodeInfo
- {
- internal const char HIGH_SURROGATE_START = '\ud800';
- internal const char HIGH_SURROGATE_END = '\udbff';
- internal const char LOW_SURROGATE_START = '\udc00';
- internal const char LOW_SURROGATE_END = '\udfff';
- internal const int HIGH_SURROGATE_RANGE = 0x3FF;
-
- internal const int UNICODE_CATEGORY_OFFSET = 0;
- internal const int BIDI_CATEGORY_OFFSET = 1;
-
- // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
- internal const int UNICODE_PLANE01_START = 0x10000;
-
- /// <summary>
- /// Convert the BMP character or surrogate pointed by index to a UTF32 value.
- /// This is similar to char.ConvertToUTF32, but the difference is that
- /// it does not throw exceptions when invalid surrogate characters are passed in.
- ///
- /// WARNING: since it doesn't throw an exception it CAN return a value
- /// in the surrogate range D800-DFFF, which are not legal unicode values.
- /// </summary>
- internal static int InternalConvertToUtf32(string s, int index)
- {
- Debug.Assert(s != null, "s != null");
- Debug.Assert(index >= 0 && index < s.Length, "index < s.Length");
- if (index < s.Length - 1)
- {
- int temp1 = (int)s[index] - HIGH_SURROGATE_START;
- if ((uint)temp1 <= HIGH_SURROGATE_RANGE)
- {
- int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if ((uint)temp2 <= HIGH_SURROGATE_RANGE)
- {
- // Convert the surrogate to UTF32 and get the result.
- return (temp1 * 0x400) + temp2 + UNICODE_PLANE01_START;
- }
- }
- }
- return (int)s[index];
- }
-
- internal static int InternalConvertToUtf32(StringBuilder s, int index)
- {
- Debug.Assert(s != null, "s != null");
- Debug.Assert(index >= 0 && index < s.Length, "index < s.Length");
-
- int c = (int)s[index];
- if (index < s.Length - 1)
- {
- int temp1 = c - HIGH_SURROGATE_START;
- if ((uint)temp1 <= HIGH_SURROGATE_RANGE)
- {
- int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if ((uint)temp2 <= HIGH_SURROGATE_RANGE)
- {
- // Convert the surrogate to UTF32 and get the result.
- return (temp1 * 0x400) + temp2 + UNICODE_PLANE01_START;
- }
- }
- }
- return c;
- }
-
- /// <summary>
- /// Convert a character or a surrogate pair starting at index of string s
- /// to UTF32 value.
- /// WARNING: since it doesn't throw an exception it CAN return a value
- /// in the surrogate range D800-DFFF, which are not legal unicode values.
- /// </summary>
- internal static int InternalConvertToUtf32(string s, int index, out int charLength)
- {
- Debug.Assert(s != null, "s != null");
- Debug.Assert(s.Length > 0, "s.Length > 0");
- Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
- charLength = 1;
- if (index < s.Length - 1)
- {
- int temp1 = (int)s[index] - HIGH_SURROGATE_START;
- if ((uint)temp1 <= HIGH_SURROGATE_RANGE)
- {
- int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if ((uint)temp2 <= HIGH_SURROGATE_RANGE)
- {
- // Convert the surrogate to UTF32 and get the result.
- charLength++;
- return (temp1 * 0x400) + temp2 + UNICODE_PLANE01_START;
- }
- }
- }
- return (int)s[index];
- }
-
- /// <summary>
- /// This is called by the public char and string, index versions
- /// Note that for ch in the range D800-DFFF we just treat it as any
- /// other non-numeric character
- /// </summary>
- internal static double InternalGetNumericValue(int ch)
- {
- Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
- // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
- int index = ch >> 8;
- if ((uint)index < (uint)NumericLevel1Index.Length)
- {
- index = NumericLevel1Index[index];
- // Get the level 2 offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
- // Note that & has the lower precedence than addition, so don't forget the parathesis.
- index = NumericLevel2Index[(index << 4) + ((ch >> 4) & 0x000f)];
- index = NumericLevel3Index[(index << 4) + (ch & 0x000f)];
- ref byte value = ref Unsafe.AsRef(in NumericValues[index * 8]);
-
- if (BitConverter.IsLittleEndian)
- {
- return Unsafe.ReadUnaligned<double>(ref value);
- }
-
- return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(Unsafe.ReadUnaligned<long>(ref value)));
- }
- return -1;
- }
-
- internal static byte InternalGetDigitValues(int ch, int offset)
- {
- Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
- // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
- int index = ch >> 8;
- if ((uint)index < (uint)NumericLevel1Index.Length)
- {
- index = NumericLevel1Index[index];
- // Get the level 2 offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
- // Note that & has the lower precedence than addition, so don't forget the parathesis.
- index = NumericLevel2Index[(index << 4) + ((ch >> 4) & 0x000f)];
- index = NumericLevel3Index[(index << 4) + (ch & 0x000f)];
- return DigitValues[index * 2 + offset];
- }
- return 0xff;
- }
-
- /// <summary>
- /// Returns the numeric value associated with the character c.
- /// If the character is a fraction, the return value will not be an
- /// integer. If the character does not have a numeric value, the return
- /// value is -1.
- /// </summary>
- public static double GetNumericValue(char ch)
- {
- return InternalGetNumericValue(ch);
- }
-
- public static double GetNumericValue(string s, int index)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
- if (index < 0 || index >= s.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- }
-
- return InternalGetNumericValue(InternalConvertToUtf32(s, index));
- }
-
- public static int GetDecimalDigitValue(char ch)
- {
- return (sbyte)InternalGetDigitValues(ch, 0);
- }
-
- public static int GetDecimalDigitValue(string s, int index)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
- if (index < 0 || index >= s.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- }
-
- return (sbyte)InternalGetDigitValues(InternalConvertToUtf32(s, index), 0);
- }
-
- public static int GetDigitValue(char ch)
- {
- return (sbyte)InternalGetDigitValues(ch, 1);
- }
-
- public static int GetDigitValue(string s, int index)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
- if (index < 0 || index >= s.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- }
-
- return (sbyte)InternalGetDigitValues(InternalConvertToUtf32(s, index), 1);
- }
-
- public static UnicodeCategory GetUnicodeCategory(char ch)
- {
- return GetUnicodeCategory((int)ch);
- }
-
- public static UnicodeCategory GetUnicodeCategory(string s, int index)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
- if (((uint)index) >= ((uint)s.Length))
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
-
- return InternalGetUnicodeCategory(s, index);
- }
-
- public static UnicodeCategory GetUnicodeCategory(int codePoint)
- {
- return (UnicodeCategory)InternalGetCategoryValue(codePoint, UNICODE_CATEGORY_OFFSET);
- }
-
- /// <summary>
- /// Returns the Unicode Category property for the character c.
- /// Note that this API will return values for D800-DF00 surrogate halves.
- /// </summary>
- internal static byte InternalGetCategoryValue(int ch, int offset)
- {
- Debug.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
- // Get the level 2 item from the highest 11 bits of ch.
- int index = CategoryLevel1Index[ch >> 9];
- // Get the level 2 WORD offset from the next 5 bits of ch. This provides the base offset of the level 3 table.
- // Note that & has the lower precedence than addition, so don't forget the parathesis.
- index = Unsafe.ReadUnaligned<ushort>(ref Unsafe.AsRef(in CategoryLevel2Index[(index << 6) + ((ch >> 3) & 0b111110)]));
- if (!BitConverter.IsLittleEndian)
- {
- index = BinaryPrimitives.ReverseEndianness((ushort)index);
- }
-
- // Get the result from the 0 -3 bit of ch.
- index = CategoryLevel3Index[(index << 4) + (ch & 0x000f)];
- return CategoriesValue[index * 2 + offset];
- }
-
- /// <summary>
- /// Returns the Unicode Category property for the character c.
- /// </summary>
- internal static UnicodeCategory InternalGetUnicodeCategory(string value, int index)
- {
- Debug.Assert(value != null, "value can not be null");
- Debug.Assert(index < value.Length, "index < value.Length");
-
- return GetUnicodeCategory(InternalConvertToUtf32(value, index));
- }
-
- internal static BidiCategory GetBidiCategory(string s, int index)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
- if (((uint)index) >= ((uint)s.Length))
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
-
- return (BidiCategory)InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET);
- }
-
- internal static BidiCategory GetBidiCategory(StringBuilder s, int index)
- {
- Debug.Assert(s != null, "s can not be null");
- Debug.Assert(index >= 0 && index < s.Length, "invalid index");
-
- return (BidiCategory)InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET);
- }
-
- /// <summary>
- /// Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
- /// If the character is a valid surrogate pair, charLength will return 2.
- /// </summary>
- internal static UnicodeCategory InternalGetUnicodeCategory(string str, int index, out int charLength)
- {
- Debug.Assert(str != null, "str can not be null");
- Debug.Assert(str.Length > 0, "str.Length > 0");
- Debug.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length");
-
- return GetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength));
- }
-
- internal static bool IsCombiningCategory(UnicodeCategory uc)
- {
- Debug.Assert(uc >= 0, "uc >= 0");
- return
- uc == UnicodeCategory.NonSpacingMark ||
- uc == UnicodeCategory.SpacingCombiningMark ||
- uc == UnicodeCategory.EnclosingMark
- ;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfoData.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfoData.cs
deleted file mode 100644
index 522c33004a4..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfoData.cs
+++ /dev/null
@@ -1,1576 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public static partial class CharUnicodeInfo
- {
- // THE FOLLOWING DATA IS AUTO GENERATED BY GenUnicodeProp program UNDER THE TOOLS FOLDER
- // PLEASE DON'T MODIFY BY HAND
-
-
- // 11:5:4 index table of the Unicode category data.
- private static ReadOnlySpan<byte> CategoryLevel1Index => new byte[2176]
- {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1c,
- 0x1d, 0x1a, 0x1e, 0x1f, 0x20, 0x21, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x22, 0x23, 0x23, 0x23, 0x23,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x1a, 0x39, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1a, 0x1a, 0x3c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x1a, 0x3d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x1a, 0x3e, 0x3b, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x40, 0x1a, 0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x3b, 0x3b,
- 0x4b, 0x3b, 0x3b, 0x3b, 0x4c, 0x3b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x3b, 0x3b,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x55, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x56, 0x57, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x58, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
- 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x59, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1a, 0x5a, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x5b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x5c,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x5c
- };
-
- private static ReadOnlySpan<byte> CategoryLevel2Index => new byte[5952]
- {
- 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
- 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00,
- 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x13, 0x00,
- 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x10, 0x00, 0x1a, 0x00,
- 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
- 0x0e, 0x00, 0x1d, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00,
- 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x24, 0x00,
- 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x0e, 0x00, 0x28, 0x00, 0x29, 0x00, 0x10, 0x00, 0x2a, 0x00,
- 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x10, 0x00,
- 0x2b, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x2c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
- 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x2d, 0x00, 0x0c, 0x00, 0x2e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
- 0x2f, 0x00, 0x30, 0x00, 0x23, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
- 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x38, 0x00, 0x39, 0x00, 0x23, 0x00, 0x3a, 0x00, 0x3b, 0x00,
- 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00,
- 0x3f, 0x00, 0x40, 0x00, 0x38, 0x00, 0x23, 0x00, 0x41, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
- 0x38, 0x00, 0x38, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x33, 0x00, 0x45, 0x00, 0x46, 0x00,
- 0x33, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x33, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x38, 0x00, 0x4d, 0x00, 0x4c, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x23, 0x00,
- 0x50, 0x00, 0x51, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00,
- 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00,
- 0x5f, 0x00, 0x58, 0x00, 0x59, 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
- 0x65, 0x00, 0x66, 0x00, 0x59, 0x00, 0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x5d, 0x00, 0x6a, 0x00,
- 0x6b, 0x00, 0x58, 0x00, 0x59, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x5d, 0x00, 0x6f, 0x00,
- 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x63, 0x00, 0x76, 0x00,
- 0x77, 0x00, 0x78, 0x00, 0x59, 0x00, 0x79, 0x00, 0x7a, 0x00, 0x7b, 0x00, 0x5d, 0x00, 0x7c, 0x00,
- 0x7d, 0x00, 0x78, 0x00, 0x59, 0x00, 0x7e, 0x00, 0x7f, 0x00, 0x80, 0x00, 0x5d, 0x00, 0x81, 0x00,
- 0x82, 0x00, 0x78, 0x00, 0x51, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x5d, 0x00, 0x86, 0x00,
- 0x87, 0x00, 0x88, 0x00, 0x51, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x63, 0x00, 0x8c, 0x00,
- 0x8d, 0x00, 0x51, 0x00, 0x51, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x90, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x97, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9a, 0x00, 0x9b, 0x00, 0x51, 0x00, 0x9c, 0x00, 0x9d, 0x00,
- 0x9e, 0x00, 0x9f, 0x00, 0x23, 0x00, 0xa0, 0x00, 0xa1, 0x00, 0xa2, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0xa8, 0x00,
- 0xa9, 0x00, 0xaa, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xab, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0xac, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xad, 0x00, 0xae, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0xad, 0x00, 0x51, 0x00, 0x51, 0x00, 0xaf, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0xb0, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, 0x00,
- 0x51, 0x00, 0xb5, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xb6, 0x00,
- 0xb7, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xb8, 0x00, 0x51, 0x00,
- 0xb9, 0x00, 0xba, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xbb, 0x00, 0xbc, 0x00,
- 0xbd, 0x00, 0xbe, 0x00, 0x51, 0x00, 0xbf, 0x00, 0x51, 0x00, 0xc0, 0x00, 0xbd, 0x00, 0xc1, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00,
- 0xc7, 0x00, 0xc5, 0x00, 0x51, 0x00, 0x51, 0x00, 0xc8, 0x00, 0x51, 0x00, 0x51, 0x00, 0xc9, 0x00,
- 0xca, 0x00, 0x51, 0x00, 0xcb, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xcc, 0x00,
- 0x51, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xcf, 0x00, 0xd0, 0x00, 0x51, 0x00, 0xd1, 0x00, 0xd2, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0xd3, 0x00, 0x51, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0x51, 0x00, 0xd7, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xd8, 0x00, 0xd9, 0x00, 0xda, 0x00,
- 0xc5, 0x00, 0xc5, 0x00, 0xdb, 0x00, 0xdc, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xdd, 0x00, 0x51, 0x00, 0x51, 0x00, 0xde, 0x00, 0xdf, 0x00, 0xa5, 0x00, 0xe0, 0x00, 0xe1, 0x00,
- 0xe2, 0x00, 0x51, 0x00, 0xe3, 0x00, 0xe4, 0x00, 0x51, 0x00, 0x51, 0x00, 0xe5, 0x00, 0xe6, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0xe7, 0x00, 0xe8, 0x00, 0xe9, 0x00, 0xe4, 0x00, 0x51, 0x00, 0xea, 0x00,
- 0xeb, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xec, 0x00, 0xed, 0x00, 0xee, 0x00, 0xef, 0x00, 0xf0, 0x00,
- 0x0e, 0x00, 0x0e, 0x00, 0xf1, 0x00, 0xf2, 0x00, 0xf2, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00,
- 0x0e, 0x00, 0xf5, 0x00, 0xf2, 0x00, 0xf2, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0xf6, 0x00,
- 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
- 0x10, 0x00, 0xf7, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
- 0xf8, 0x00, 0xf9, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0xf9, 0x00, 0xfa, 0x00, 0xf8, 0x00, 0xfb, 0x00,
- 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfd, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x00, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x03, 0x01, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x01,
- 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x4c, 0x00, 0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01,
- 0x10, 0x01, 0x11, 0x01, 0x12, 0x01, 0x13, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x16, 0x01,
- 0x17, 0x01, 0x18, 0x01, 0x19, 0x01, 0xd6, 0x00, 0x1a, 0x01, 0x1b, 0x01, 0xd6, 0x00, 0x1c, 0x01,
- 0x1d, 0x01, 0x1e, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01,
- 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01,
- 0x1f, 0x01, 0xd6, 0x00, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x23, 0x01,
- 0xd6, 0x00, 0x24, 0x01, 0x1d, 0x01, 0x25, 0x01, 0xd6, 0x00, 0x26, 0x01, 0x27, 0x01, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0x28, 0x01, 0x4c, 0x00, 0x29, 0x01, 0x4c, 0x00, 0x15, 0x01, 0x15, 0x01,
- 0x2a, 0x01, 0x2b, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x2c, 0x01, 0x15, 0x01,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x2d, 0x01, 0x2e, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x2f, 0x01,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x30, 0x01, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0x31, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x32, 0x01, 0x33, 0x01,
- 0x15, 0x01, 0x34, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x35, 0x01, 0x1d, 0x01, 0x36, 0x01, 0x1d, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01,
- 0x37, 0x01, 0x38, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x39, 0x01, 0x1d, 0x01, 0x3a, 0x01,
- 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01,
- 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x1d, 0x01,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x1d, 0x01, 0x3b, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x3c, 0x01,
- 0xd6, 0x00, 0x3d, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x3e, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x3f, 0x01,
- 0x0c, 0x00, 0x0c, 0x00, 0x40, 0x01, 0x0e, 0x00, 0x0e, 0x00, 0x41, 0x01, 0x42, 0x01, 0x43, 0x01,
- 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x44, 0x01, 0x45, 0x01,
- 0x0e, 0x00, 0x0e, 0x00, 0x46, 0x01, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x47, 0x01, 0x48, 0x01,
- 0x51, 0x00, 0x49, 0x01, 0x4a, 0x01, 0x4a, 0x01, 0x4a, 0x01, 0x4a, 0x01, 0x23, 0x00, 0x23, 0x00,
- 0x4b, 0x01, 0x4c, 0x01, 0x4d, 0x01, 0x4e, 0x01, 0x4f, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xd6, 0x00, 0x50, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x51, 0x01,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x52, 0x01, 0x4c, 0x00, 0x53, 0x01,
- 0x54, 0x01, 0x55, 0x01, 0x56, 0x01, 0x57, 0x01, 0x8d, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x58, 0x01, 0xb7, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x59, 0x01,
- 0x5a, 0x01, 0x51, 0x00, 0x51, 0x00, 0x8d, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0xcd, 0x00, 0x5b, 0x01, 0x51, 0x00, 0x5c, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x51, 0x01, 0x51, 0x00,
- 0x22, 0x01, 0x5d, 0x01, 0x5e, 0x01, 0x22, 0x01, 0x5f, 0x01, 0x60, 0x01, 0x22, 0x01, 0x61, 0x01,
- 0x5e, 0x01, 0x22, 0x01, 0x22, 0x01, 0x62, 0x01, 0x63, 0x01, 0x22, 0x01, 0x22, 0x01, 0x64, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x65, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x66, 0x01, 0x22, 0x01, 0x67, 0x01,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xcc, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x68, 0x01, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x9c, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x28, 0x01, 0x51, 0x00, 0x51, 0x00, 0xea, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x69, 0x01, 0x51, 0x00, 0x6a, 0x01, 0x4c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x6b, 0x01, 0x6c, 0x01,
- 0x10, 0x00, 0x6d, 0x01, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x6e, 0x01, 0x6f, 0x01,
- 0x22, 0x00, 0x70, 0x01, 0x71, 0x01, 0x72, 0x01, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x73, 0x01,
- 0x74, 0x01, 0x75, 0x01, 0x76, 0x01, 0x77, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x78, 0x01,
- 0x79, 0x01, 0x51, 0x00, 0x7a, 0x01, 0x7b, 0x01, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x7c, 0x01,
- 0x7d, 0x01, 0x51, 0x00, 0x51, 0x00, 0x7e, 0x01, 0x7f, 0x01, 0xc5, 0x00, 0x23, 0x00, 0x80, 0x01,
- 0xe4, 0x00, 0x51, 0x00, 0x81, 0x01, 0x51, 0x00, 0x82, 0x01, 0x83, 0x01, 0x51, 0x00, 0x9c, 0x00,
- 0x50, 0x00, 0x51, 0x00, 0x51, 0x00, 0x84, 0x01, 0x85, 0x01, 0x86, 0x01, 0x87, 0x01, 0x88, 0x01,
- 0x51, 0x00, 0x51, 0x00, 0x89, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x51, 0x00, 0x8d, 0x01,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x8e, 0x01, 0x8f, 0x01, 0x90, 0x01, 0x91, 0x01, 0x92, 0x01,
- 0x93, 0x01, 0x94, 0x01, 0x4a, 0x01, 0x0e, 0x00, 0x0e, 0x00, 0x95, 0x01, 0x96, 0x01, 0x0e, 0x00,
- 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x51, 0x00, 0x51, 0x00, 0x97, 0x01, 0xc5, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x98, 0x01, 0x51, 0x00, 0x99, 0x01, 0x51, 0x00, 0x51, 0x00, 0xd3, 0x00,
- 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01,
- 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01,
- 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01,
- 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01, 0x9a, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xd1, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xd4, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x9c, 0x01, 0x9d, 0x01, 0x9e, 0x01, 0x9f, 0x01, 0xa0, 0x01, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
- 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0xa1, 0x01, 0xa2, 0x01, 0xa3, 0x01, 0x38, 0x00, 0x38, 0x00,
- 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
- 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
- 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0xa4, 0x01, 0x4c, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
- 0x38, 0x00, 0xa5, 0x01, 0x38, 0x00, 0x38, 0x00, 0xa6, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0xa7, 0x01,
- 0x23, 0x00, 0xa8, 0x01, 0x23, 0x00, 0xa9, 0x01, 0xaa, 0x01, 0xab, 0x01, 0xac, 0x01, 0xad, 0x01,
- 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0xae, 0x01,
- 0xaf, 0x01, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0xb0, 0x01, 0xb1, 0x01, 0xb2, 0x01,
- 0x51, 0x00, 0xb3, 0x01, 0x51, 0x00, 0xcd, 0x00, 0xb4, 0x01, 0xb5, 0x01, 0xb6, 0x01, 0xb7, 0x01,
- 0xb8, 0x01, 0x51, 0x00, 0xb1, 0x00, 0xb9, 0x01, 0xd1, 0x00, 0xd1, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x5c, 0x01,
- 0xba, 0x01, 0xbb, 0x01, 0xbb, 0x01, 0xbc, 0x01, 0xbd, 0x01, 0xbd, 0x01, 0xbd, 0x01, 0xbe, 0x01,
- 0xbf, 0x01, 0x53, 0x01, 0xc0, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x22, 0x01, 0x22, 0x01, 0xc1, 0x01,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x9c, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x69, 0x00, 0xc2, 0x01, 0xc3, 0x01,
- 0x51, 0x00, 0x51, 0x00, 0xc4, 0x01, 0x51, 0x00, 0xc5, 0x01, 0x51, 0x00, 0x51, 0x00, 0xc6, 0x01,
- 0x51, 0x00, 0xc7, 0x01, 0x51, 0x00, 0x51, 0x00, 0xc8, 0x01, 0xc9, 0x01, 0x4c, 0x00, 0x4c, 0x00,
- 0x0c, 0x00, 0x0c, 0x00, 0xca, 0x01, 0x0e, 0x00, 0x0e, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0xd1, 0x00, 0xc5, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xcb, 0x01, 0x0e, 0x00, 0xcc, 0x01,
- 0x51, 0x00, 0x51, 0x00, 0xcd, 0x01, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xce, 0x01, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x49, 0x01, 0x51, 0x00, 0xcc, 0x00, 0xcd, 0x01, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xcf, 0x01, 0x33, 0x00, 0x33, 0x00, 0xd0, 0x01, 0x33, 0x00, 0xd1, 0x01, 0x33, 0x00, 0xd2, 0x01,
- 0x33, 0x00, 0xd3, 0x01, 0xd4, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x33, 0x00, 0xd5, 0x01,
- 0x33, 0x00, 0xd6, 0x01, 0x33, 0x00, 0xd7, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0xd8, 0x01, 0xd9, 0x01, 0xda, 0x01, 0xd9, 0x01, 0xd9, 0x01,
- 0xdb, 0x01, 0xdc, 0x01, 0x33, 0x00, 0xdd, 0x01, 0xde, 0x01, 0xdf, 0x01, 0x33, 0x00, 0xe0, 0x01,
- 0x33, 0x00, 0xe1, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0xe2, 0x01, 0x33, 0x00, 0xe3, 0x01, 0xe4, 0x01,
- 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0xe5, 0x01, 0x33, 0x00, 0xe6, 0x01, 0x33, 0x00, 0xe7, 0x01,
- 0x33, 0x00, 0xe8, 0x01, 0xe9, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0xea, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xeb, 0x01, 0xeb, 0x01, 0xeb, 0x01, 0xec, 0x01, 0xed, 0x01, 0xed, 0x01, 0xed, 0x01, 0xee, 0x01,
- 0x38, 0x00, 0x38, 0x00, 0xef, 0x01, 0xf0, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0xf1, 0x01, 0xf2, 0x01,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x33, 0x00, 0xe1, 0x01, 0xf3, 0x01, 0x38, 0x00, 0x42, 0x00, 0xf4, 0x01, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xf5, 0x01, 0x51, 0x00, 0x51, 0x00, 0xf6, 0x01, 0xf7, 0x01, 0xf8, 0x01, 0xf9, 0x01, 0xfa, 0x01,
- 0xe2, 0x00, 0x51, 0x00, 0x51, 0x00, 0xfb, 0x01, 0xfc, 0x01, 0x51, 0x00, 0xc9, 0x00, 0xc5, 0x00,
- 0xfd, 0x01, 0x51, 0x00, 0xfe, 0x01, 0xff, 0x01, 0x00, 0x02, 0x51, 0x00, 0x51, 0x00, 0x01, 0x02,
- 0xe2, 0x00, 0x51, 0x00, 0x51, 0x00, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02,
- 0x51, 0x00, 0x66, 0x00, 0x07, 0x02, 0x08, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x09, 0x02, 0x0a, 0x02, 0x0b, 0x02, 0x51, 0x00, 0x51, 0x00, 0x0c, 0x02, 0x0d, 0x02, 0xc5, 0x00,
- 0x0e, 0x02, 0x58, 0x00, 0x59, 0x00, 0x0f, 0x02, 0x10, 0x02, 0x11, 0x02, 0x12, 0x02, 0x13, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x14, 0x02, 0x15, 0x02, 0x16, 0x02, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x17, 0x02, 0x18, 0x02, 0xc5, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x19, 0x02, 0x1a, 0x02, 0x1b, 0x02, 0x1c, 0x02, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x1d, 0x02, 0x1e, 0x02, 0xc5, 0x00, 0x1f, 0x02, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x20, 0x02, 0x21, 0x02, 0xc5, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0xb2, 0x00, 0x22, 0x02, 0x23, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x07, 0x02, 0x24, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x99, 0x00, 0x25, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x26, 0x02, 0x51, 0x00, 0x51, 0x00, 0x27, 0x02, 0x28, 0x02, 0x29, 0x02, 0x51, 0x00, 0x51, 0x00,
- 0x2a, 0x02, 0x2b, 0x02, 0x2c, 0x02, 0x4c, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xc9, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x59, 0x00, 0x51, 0x00, 0x19, 0x02, 0x2d, 0x02, 0x2e, 0x02, 0x99, 0x00, 0xb4, 0x00, 0x2f, 0x02,
- 0x51, 0x00, 0x30, 0x02, 0x31, 0x02, 0x32, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x33, 0x02, 0x51, 0x00, 0x51, 0x00, 0x34, 0x02, 0x35, 0x02, 0xc5, 0x00, 0x36, 0x02, 0x51, 0x00,
- 0x37, 0x02, 0x38, 0x02, 0xc5, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x51, 0x00, 0x39, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0xd4, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x16, 0x01, 0x3a, 0x02, 0x3b, 0x02,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x98, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x49, 0x01, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xc9, 0x00, 0x51, 0x00, 0xcd, 0x00, 0x86, 0x01, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x51, 0x00, 0xd1, 0x00, 0x3c, 0x02,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x3d, 0x02, 0x3e, 0x02, 0x3f, 0x02, 0x40, 0x02, 0x41, 0x02,
- 0x51, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00,
- 0xbb, 0x01, 0x42, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xd2, 0x00, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02,
- 0xfa, 0x01, 0x46, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x47, 0x02, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x48, 0x02,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x49, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0xcd, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xd3, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x5c, 0x01, 0x9c, 0x00,
- 0xc9, 0x00, 0x4a, 0x02, 0x4b, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x4c, 0x02,
- 0x22, 0x01, 0x22, 0x01, 0x4d, 0x02, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x4e, 0x02, 0x4f, 0x02,
- 0x50, 0x02, 0x22, 0x01, 0x51, 0x02, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x52, 0x02, 0x4c, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x53, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0xbb, 0x01, 0x54, 0x02,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x28, 0x01, 0xbb, 0x01, 0x55, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x0c, 0x00, 0x56, 0x02, 0x0e, 0x00, 0x57, 0x02, 0x58, 0x02, 0x59, 0x02, 0xf8, 0x00, 0x0c, 0x00,
- 0x5a, 0x02, 0x5b, 0x02, 0x5c, 0x02, 0x5d, 0x02, 0x5e, 0x02, 0x0c, 0x00, 0x56, 0x02, 0x0e, 0x00,
- 0x5f, 0x02, 0x60, 0x02, 0x0e, 0x00, 0x61, 0x02, 0x62, 0x02, 0x63, 0x02, 0x64, 0x02, 0x0c, 0x00,
- 0x65, 0x02, 0x0e, 0x00, 0x0c, 0x00, 0x56, 0x02, 0x0e, 0x00, 0x57, 0x02, 0x58, 0x02, 0x0e, 0x00,
- 0xf8, 0x00, 0x0c, 0x00, 0x5a, 0x02, 0x64, 0x02, 0x0c, 0x00, 0x65, 0x02, 0x0e, 0x00, 0x0c, 0x00,
- 0x56, 0x02, 0x0e, 0x00, 0x66, 0x02, 0x0c, 0x00, 0x67, 0x02, 0x68, 0x02, 0x69, 0x02, 0x6a, 0x02,
- 0x0e, 0x00, 0x6b, 0x02, 0x0c, 0x00, 0x6c, 0x02, 0x6d, 0x02, 0x6e, 0x02, 0x6f, 0x02, 0x0e, 0x00,
- 0x70, 0x02, 0x0c, 0x00, 0x71, 0x02, 0x0e, 0x00, 0x72, 0x02, 0x73, 0x02, 0x73, 0x02, 0x73, 0x02,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01,
- 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x74, 0x02, 0x23, 0x00, 0x23, 0x00, 0x75, 0x02, 0x76, 0x02,
- 0x77, 0x02, 0x78, 0x02, 0x30, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x79, 0x02, 0x7a, 0x02, 0x7b, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00,
- 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x7c, 0x02, 0x7d, 0x02, 0x4c, 0x00, 0x4c, 0x00,
- 0xeb, 0x01, 0xeb, 0x01, 0x7e, 0x02, 0xed, 0x01, 0x7f, 0x02, 0x80, 0x02, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x81, 0x02,
- 0x82, 0x02, 0x82, 0x02, 0x83, 0x02, 0x84, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x85, 0x02, 0x38, 0x00, 0x86, 0x02, 0x87, 0x02, 0x88, 0x02, 0x89, 0x02, 0x8a, 0x02, 0x8b, 0x02,
- 0x8c, 0x02, 0x8d, 0x02, 0x8e, 0x02, 0x8d, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x8f, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0x53, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0x51, 0x01, 0x3f, 0x01, 0x90, 0x02, 0x90, 0x02, 0x90, 0x02, 0xd6, 0x00, 0x52, 0x01,
- 0x91, 0x02, 0x22, 0x01, 0x67, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x92, 0x02, 0x22, 0x01,
- 0x22, 0x01, 0x22, 0x01, 0x93, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x94, 0x02, 0x22, 0x01,
- 0x95, 0x02, 0x22, 0x01, 0x22, 0x01, 0x96, 0x02, 0x52, 0x02, 0x97, 0x02, 0x52, 0x01, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x98, 0x02,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x99, 0x02, 0x9a, 0x02, 0xb5, 0x00,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x51, 0x01,
- 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x9b, 0x02, 0x4c, 0x00, 0x4c, 0x00,
- 0x53, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x9c, 0x02, 0xb5, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0x9c, 0x02, 0xd6, 0x00, 0x9d, 0x02, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x53, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0x3f, 0x01, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x9e, 0x02,
- 0xd6, 0x00, 0xd6, 0x00, 0x9f, 0x02, 0xb5, 0x00, 0x9f, 0x02, 0xd6, 0x00, 0xd6, 0x00, 0xd6, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x9d, 0x02, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x49, 0x01, 0x4c, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0xd2, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0xd1, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x48, 0x02, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00,
- 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x51, 0x00, 0x69, 0x00, 0x4c, 0x00,
- 0x51, 0x00, 0xd1, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0xa0, 0x02, 0x4c, 0x00, 0xa1, 0x02, 0xa1, 0x02, 0xa1, 0x02, 0xa1, 0x02, 0xa1, 0x02, 0xa1, 0x02,
- 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00,
- 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00,
- 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, 0x4c, 0x00,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01,
- 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0x9b, 0x01, 0xa2, 0x02
- };
-
- private static ReadOnlySpan<byte> CategoryLevel3Index => new byte[10800]
- {
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x02, 0x04, 0x03, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x02,
- 0x05, 0x06, 0x06, 0x07, 0x08, 0x07, 0x06, 0x06, 0x09, 0x0a, 0x06, 0x0b, 0x0c, 0x0d, 0x0c, 0x0c,
- 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0c, 0x06, 0x0f, 0x0f, 0x0f, 0x06,
- 0x06, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x09, 0x06, 0x0a, 0x11, 0x12,
- 0x11, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x09, 0x0f, 0x0a, 0x0f, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x14, 0x06, 0x08, 0x08, 0x08, 0x08, 0x15, 0x06, 0x11, 0x15, 0x16, 0x17, 0x0f, 0x18, 0x15, 0x11,
- 0x19, 0x1a, 0x1b, 0x1b, 0x11, 0x13, 0x06, 0x06, 0x11, 0x1b, 0x16, 0x1c, 0x1d, 0x1d, 0x1d, 0x06,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x0f, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10,
- 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x13,
- 0x13, 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x13, 0x10, 0x10, 0x10, 0x13, 0x13, 0x10, 0x10,
- 0x10, 0x10, 0x13, 0x10, 0x10, 0x13, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x10, 0x10, 0x13, 0x10,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x13, 0x10, 0x13, 0x13, 0x10, 0x13, 0x10, 0x10,
- 0x13, 0x10, 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x13, 0x13, 0x16, 0x10, 0x13, 0x13, 0x13,
- 0x16, 0x16, 0x16, 0x16, 0x10, 0x1e, 0x13, 0x10, 0x1e, 0x13, 0x10, 0x1e, 0x13, 0x10, 0x13, 0x10,
- 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x13, 0x10, 0x13,
- 0x13, 0x10, 0x1e, 0x13, 0x10, 0x13, 0x10, 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x10, 0x13, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x13, 0x10, 0x10, 0x13,
- 0x13, 0x10, 0x13, 0x10, 0x10, 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x16, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
- 0x1f, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x1f, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x20, 0x11, 0x1f, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x10, 0x13, 0x10, 0x13, 0x20, 0x11, 0x10, 0x13, 0x00, 0x00, 0x1f, 0x13, 0x13, 0x13, 0x06, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x10, 0x06, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,
- 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10,
- 0x13, 0x13, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x10, 0x13, 0x0f, 0x10, 0x13, 0x10, 0x10, 0x13, 0x13, 0x10, 0x10, 0x10,
- 0x10, 0x13, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x23, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x13,
- 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x24, 0x25, 0x00, 0x00, 0x15, 0x15, 0x08,
- 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x26, 0x21,
- 0x27, 0x21, 0x21, 0x27, 0x21, 0x21, 0x27, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x28,
- 0x28, 0x28, 0x28, 0x27, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x0f, 0x0f, 0x2a, 0x07, 0x07, 0x2b, 0x0c, 0x2c, 0x15, 0x15,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x2c, 0x2d, 0x00, 0x2c, 0x2c,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2f, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x07, 0x31, 0x31, 0x2c, 0x2e, 0x2e,
- 0x21, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2c, 0x2e, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x29, 0x15, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x2f, 0x2f, 0x21, 0x21, 0x15, 0x21, 0x21, 0x21, 0x21, 0x2e, 0x2e,
- 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x2e, 0x2e, 0x2e, 0x32, 0x32, 0x2e,
- 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x2d,
- 0x2e, 0x21, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x34, 0x34, 0x15, 0x06, 0x06, 0x06, 0x34, 0x00, 0x00, 0x21, 0x35, 0x35,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x21, 0x21, 0x21, 0x21, 0x34, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x34, 0x21, 0x21, 0x21, 0x34, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00,
- 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x00,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x21, 0x21, 0x21, 0x00, 0x00, 0x27, 0x00,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x29, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x36, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x36, 0x21, 0x16, 0x36, 0x36,
- 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x36, 0x36, 0x21, 0x36, 0x36,
- 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x21, 0x21, 0x24, 0x24, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
- 0x24, 0x1f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x21, 0x36, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16,
- 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x21, 0x16, 0x36, 0x36,
- 0x36, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x36, 0x36, 0x21, 0x16, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x00, 0x16,
- 0x16, 0x16, 0x21, 0x21, 0x00, 0x00, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
- 0x16, 0x16, 0x08, 0x08, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x22, 0x08, 0x16, 0x24, 0x21, 0x00,
- 0x00, 0x21, 0x21, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x16,
- 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x00, 0x00, 0x21, 0x00, 0x36, 0x36,
- 0x36, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x21, 0x21, 0x00, 0x00, 0x21, 0x21, 0x21, 0x00, 0x00,
- 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
- 0x21, 0x21, 0x16, 0x16, 0x16, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x21, 0x21, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16,
- 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x21, 0x16, 0x36, 0x36,
- 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x36, 0x00, 0x36, 0x36, 0x21, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x00, 0x21, 0x36, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16,
- 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x21, 0x16, 0x36, 0x21,
- 0x36, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x36, 0x36, 0x21, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x36, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x00, 0x16,
- 0x22, 0x16, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x21, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x16, 0x16,
- 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x16, 0x16, 0x00, 0x16, 0x00, 0x16, 0x16,
- 0x00, 0x00, 0x00, 0x16, 0x16, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36,
- 0x21, 0x36, 0x36, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x00, 0x36, 0x36, 0x36, 0x21, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x38, 0x38, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x08, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x36, 0x36, 0x36, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16,
- 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x16, 0x21, 0x21,
- 0x21, 0x36, 0x36, 0x36, 0x36, 0x00, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x21, 0x00, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x22,
- 0x16, 0x21, 0x36, 0x36, 0x24, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x21, 0x16, 0x36, 0x39,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x39, 0x36, 0x36, 0x00, 0x36, 0x36, 0x21, 0x21, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00,
- 0x00, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x36, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x16, 0x36, 0x36,
- 0x36, 0x21, 0x21, 0x21, 0x21, 0x00, 0x36, 0x36, 0x36, 0x00, 0x36, 0x36, 0x36, 0x21, 0x16, 0x22,
- 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x36, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x16,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x22, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x00, 0x00, 0x36, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x36,
- 0x36, 0x36, 0x21, 0x21, 0x21, 0x00, 0x21, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x00, 0x00, 0x36, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x21, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x1f, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x16, 0x16, 0x00, 0x16, 0x00, 0x00, 0x16, 0x16, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x00, 0x16, 0x16, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16,
- 0x16, 0x21, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x16, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x1f, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x22, 0x22, 0x22, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x38, 0x38, 0x38, 0x38, 0x22, 0x21, 0x22, 0x21, 0x22, 0x21, 0x09, 0x0a, 0x09, 0x0a, 0x36, 0x36,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00,
- 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x22, 0x22,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x21, 0x21, 0x21,
- 0x21, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x21, 0x36, 0x36, 0x21, 0x21, 0x16,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21,
- 0x21, 0x16, 0x36, 0x36, 0x36, 0x16, 0x16, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x16, 0x16,
- 0x16, 0x21, 0x21, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x21, 0x36, 0x36, 0x21, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x16, 0x36,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x21, 0x22, 0x22,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x24, 0x1f, 0x13, 0x13, 0x13,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00,
- 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00,
- 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x21, 0x21, 0x21,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00,
- 0x25, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x24, 0x24, 0x16,
- 0x05, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x09, 0x0a, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x24, 0x24, 0x24, 0x3a, 0x3a,
- 0x3a, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16,
- 0x16, 0x16, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x21, 0x21, 0x21, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x1f, 0x24, 0x24, 0x24, 0x08, 0x16, 0x21, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x25, 0x06, 0x06, 0x06, 0x06, 0x21, 0x21, 0x21, 0x18, 0x00,
- 0x16, 0x16, 0x16, 0x1f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00,
- 0x21, 0x21, 0x21, 0x36, 0x36, 0x36, 0x36, 0x21, 0x21, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
- 0x36, 0x36, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x06, 0x06, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x00, 0x00, 0x00, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x36, 0x36, 0x21, 0x00, 0x00, 0x24, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x21, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00,
- 0x21, 0x36, 0x21, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x21,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x00,
- 0x21, 0x21, 0x21, 0x21, 0x36, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x21, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x21, 0x36, 0x36, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x36, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x36, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x21, 0x21, 0x36, 0x21, 0x21, 0x21, 0x16, 0x16,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x36, 0x21, 0x21, 0x36, 0x36, 0x36, 0x21, 0x36, 0x21,
- 0x21, 0x21, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x21, 0x21, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x24,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x24, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x21, 0x16, 0x16,
- 0x16, 0x16, 0x36, 0x36, 0x21, 0x16, 0x16, 0x36, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1f, 0x1f, 0x1f, 0x1f,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1f, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x13, 0x11,
- 0x11, 0x11, 0x13, 0x13, 0x13, 0x00, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x11, 0x11,
- 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x00, 0x11, 0x11, 0x11,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11,
- 0x00, 0x00, 0x13, 0x13, 0x13, 0x00, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x11, 0x00,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x18, 0x18, 0x18, 0x3b, 0x3c,
- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x06, 0x06, 0x17, 0x1c, 0x09, 0x17, 0x17, 0x1c, 0x09, 0x17,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x14,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x17, 0x1c, 0x06, 0x06, 0x06, 0x06, 0x12,
- 0x12, 0x06, 0x06, 0x06, 0x44, 0x09, 0x0a, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x0f, 0x06, 0x12, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x45, 0x46, 0x47, 0x48, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x1b, 0x1f, 0x00, 0x00, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x0b, 0x0b, 0x0f, 0x09, 0x0a, 0x1f,
- 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x0b, 0x0b, 0x0f, 0x09, 0x0a, 0x00,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x23, 0x23,
- 0x23, 0x21, 0x23, 0x23, 0x23, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x10, 0x15, 0x15, 0x15, 0x15, 0x10, 0x15, 0x15, 0x13, 0x10, 0x10, 0x10, 0x13, 0x13,
- 0x10, 0x10, 0x10, 0x13, 0x15, 0x10, 0x15, 0x15, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x10, 0x15, 0x10, 0x15, 0x10, 0x15, 0x10, 0x10, 0x10, 0x10, 0x19, 0x13,
- 0x10, 0x10, 0x10, 0x10, 0x13, 0x16, 0x16, 0x16, 0x16, 0x13, 0x15, 0x15, 0x13, 0x13, 0x10, 0x10,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x13, 0x13, 0x13, 0x13, 0x15, 0x0f, 0x15, 0x15, 0x13, 0x22,
- 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
- 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
- 0x3a, 0x3a, 0x3a, 0x10, 0x13, 0x3a, 0x3a, 0x3a, 0x3a, 0x1d, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x15, 0x15, 0x15, 0x15,
- 0x0f, 0x15, 0x15, 0x0f, 0x15, 0x15, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f,
- 0x15, 0x15, 0x0f, 0x15, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0b, 0x1a, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x15, 0x15, 0x15,
- 0x0f, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x09, 0x0a, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x0f, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x22, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
- 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x0f, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x22, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a,
- 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
- 0x1d, 0x1d, 0x1d, 0x1d, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x0a, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a,
- 0x0f, 0x0f, 0x0f, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09,
- 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x0a, 0x09, 0x0a, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x0a, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x15, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00,
- 0x10, 0x13, 0x10, 0x10, 0x10, 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x10,
- 0x10, 0x13, 0x10, 0x13, 0x13, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1f, 0x1f, 0x10, 0x10,
- 0x10, 0x13, 0x10, 0x13, 0x13, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x13, 0x10, 0x13, 0x21,
- 0x21, 0x21, 0x10, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1d, 0x06, 0x06,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00,
- 0x06, 0x06, 0x17, 0x1c, 0x17, 0x1c, 0x06, 0x06, 0x06, 0x17, 0x1c, 0x06, 0x17, 0x1c, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x25, 0x06, 0x06, 0x25, 0x06, 0x17, 0x1c, 0x06, 0x06,
- 0x17, 0x1c, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x06, 0x06, 0x06, 0x06, 0x06, 0x20,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x25, 0x25, 0x06, 0x06, 0x06, 0x06,
- 0x25, 0x06, 0x09, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x06, 0x06, 0x06, 0x15, 0x1f, 0x16, 0x3a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a,
- 0x09, 0x0a, 0x15, 0x15, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x25, 0x09, 0x0a, 0x0a,
- 0x15, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36,
- 0x25, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x15, 0x15, 0x3a, 0x3a, 0x3a, 0x1f, 0x16, 0x06, 0x15, 0x15,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x21, 0x21, 0x11, 0x11, 0x1f, 0x1f, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x06, 0x1f, 0x1f, 0x1f, 0x16,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x22, 0x22, 0x38, 0x38, 0x38, 0x38, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x15, 0x00,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x15, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x15, 0x15, 0x22,
- 0x22, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x15, 0x15, 0x15,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x15, 0x15, 0x15, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x15,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x1f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x1f, 0x06, 0x06, 0x06,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x16, 0x21,
- 0x23, 0x23, 0x23, 0x06, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x06, 0x20,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x1f, 0x1f, 0x21, 0x21,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
- 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x11, 0x11, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x1f, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x13,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x20, 0x49, 0x49, 0x10, 0x13, 0x10, 0x13, 0x16,
- 0x10, 0x13, 0x10, 0x13, 0x13, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13,
- 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x10, 0x13, 0x10, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x1f, 0x1f, 0x13, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x21, 0x16, 0x16, 0x16, 0x21, 0x16, 0x16, 0x16, 0x16, 0x21, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x36, 0x36, 0x21, 0x21, 0x36, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x22, 0x22, 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x36, 0x36, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
- 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x24, 0x24, 0x24, 0x16, 0x24, 0x16, 0x16, 0x21,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
- 0x16, 0x16, 0x16, 0x21, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x21, 0x36, 0x36, 0x36,
- 0x36, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x1f,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x1f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36,
- 0x36, 0x21, 0x21, 0x36, 0x36, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x36, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
- 0x1f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x22, 0x22, 0x22, 0x16, 0x36, 0x21, 0x36, 0x16, 0x16,
- 0x21, 0x16, 0x21, 0x21, 0x21, 0x16, 0x16, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21,
- 0x16, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x1f, 0x24, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x21, 0x21, 0x36, 0x36,
- 0x24, 0x24, 0x16, 0x1f, 0x1f, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00,
- 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x49, 0x1f, 0x1f, 0x1f, 0x1f,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x36, 0x36, 0x21, 0x36, 0x36, 0x21, 0x36, 0x36, 0x24, 0x36, 0x21, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
- 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x21, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x0b, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x28, 0x00,
- 0x28, 0x28, 0x00, 0x28, 0x28, 0x00, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x2e, 0x2e, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
- 0x4c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x0a, 0x09,
- 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2b, 0x15, 0x00, 0x00,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x09, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0x25, 0x25, 0x12, 0x12, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x09,
- 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x06, 0x06, 0x09, 0x0a, 0x06, 0x06, 0x06, 0x06, 0x12, 0x12, 0x12,
- 0x0c, 0x06, 0x0c, 0x00, 0x06, 0x0c, 0x06, 0x06, 0x25, 0x09, 0x0a, 0x09, 0x0a, 0x09, 0x0a, 0x07,
- 0x06, 0x06, 0x0b, 0x0d, 0x0f, 0x0f, 0x0f, 0x00, 0x06, 0x08, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x18,
- 0x00, 0x06, 0x06, 0x07, 0x08, 0x07, 0x06, 0x06, 0x09, 0x0a, 0x06, 0x0b, 0x0c, 0x0d, 0x0c, 0x0c,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x09, 0x0f, 0x0a, 0x0f, 0x09,
- 0x0a, 0x06, 0x09, 0x0a, 0x06, 0x06, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x1f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x1f, 0x1f,
- 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00,
- 0x08, 0x08, 0x0f, 0x11, 0x15, 0x08, 0x08, 0x00, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x15, 0x15, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x4d, 0x4d, 0x15, 0x15, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x00, 0x16,
- 0x24, 0x06, 0x24, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
- 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x1d, 0x1d, 0x1d, 0x1d, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1d, 0x1d, 0x15, 0x22, 0x22, 0x00,
- 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x00, 0x00,
- 0x21, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
- 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16,
- 0x16, 0x3a, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x24,
- 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x24, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x28, 0x00, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x28, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x27, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x50, 0x50, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x00, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x00, 0x00, 0x00, 0x06,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x28, 0x28,
- 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21,
- 0x28, 0x28, 0x28, 0x28, 0x00, 0x28, 0x28, 0x28, 0x00, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x21,
- 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4f, 0x4f, 0x27,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x50, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x27, 0x27, 0x27, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
- 0x51, 0x51, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
- 0x52, 0x52, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
- 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x00,
- 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x54, 0x54, 0x54, 0x54, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x36, 0x21, 0x36, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00,
- 0x00, 0x00, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
- 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21,
- 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x21, 0x21, 0x24, 0x24, 0x3b, 0x24, 0x24,
- 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
- 0x24, 0x24, 0x24, 0x24, 0x16, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x21, 0x24, 0x24, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36,
- 0x36, 0x16, 0x16, 0x16, 0x16, 0x24, 0x24, 0x24, 0x24, 0x21, 0x21, 0x21, 0x21, 0x24, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x16, 0x24, 0x16, 0x24, 0x24, 0x24,
- 0x00, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x36, 0x21,
- 0x21, 0x21, 0x36, 0x36, 0x21, 0x36, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x21, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21,
- 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x36, 0x36, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16,
- 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x21, 0x21, 0x16, 0x36, 0x36,
- 0x21, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x36, 0x36, 0x36, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x36, 0x36, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x36, 0x36, 0x21, 0x21, 0x21, 0x36, 0x21, 0x16, 0x16, 0x16, 0x16, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x24, 0x00, 0x24, 0x21, 0x00,
- 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x36, 0x36, 0x36, 0x36, 0x21,
- 0x21, 0x36, 0x21, 0x21, 0x16, 0x16, 0x24, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x36,
- 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x21, 0x21, 0x36, 0x21,
- 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x00, 0x00,
- 0x36, 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x21, 0x36, 0x21,
- 0x21, 0x24, 0x24, 0x24, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x21, 0x36, 0x21, 0x36, 0x36,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x36, 0x36, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x24, 0x24, 0x24, 0x22,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
- 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x39, 0x39, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x16, 0x21, 0x21, 0x21, 0x21, 0x24,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x36, 0x21, 0x21, 0x21, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x16, 0x16, 0x16, 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x21, 0x21, 0x24, 0x24, 0x24, 0x16, 0x24, 0x24,
- 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x36, 0x39,
- 0x16, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x24, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x36, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x36, 0x21, 0x21, 0x36, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x21, 0x00, 0x21, 0x21, 0x00, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x16, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x16, 0x16, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00,
- 0x21, 0x21, 0x00, 0x36, 0x36, 0x21, 0x36, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x21, 0x21, 0x36, 0x36, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x00,
- 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, 0x24, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00, 0x38, 0x38, 0x38, 0x38, 0x38,
- 0x38, 0x38, 0x00, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00,
- 0x21, 0x21, 0x21, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
- 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x22, 0x21, 0x21, 0x24,
- 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x36, 0x36, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x21, 0x21, 0x21, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x10, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x00, 0x10, 0x10,
- 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x13, 0x00, 0x13, 0x00, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x55, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x0f, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x55, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x0f, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x55, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x0f,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x55,
- 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x0f, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x55, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
- 0x13, 0x13, 0x13, 0x0f, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x13, 0x00, 0x00, 0x0e, 0x0e,
- 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21,
- 0x21, 0x21, 0x00, 0x21, 0x21, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
- 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x51, 0x51, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
- 0x52, 0x52, 0x52, 0x52, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x27, 0x27,
- 0x00, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
- 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
- 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x32, 0x54, 0x54, 0x54,
- 0x2b, 0x54, 0x54, 0x54, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x00, 0x2e, 0x2e, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x2e, 0x2e,
- 0x00, 0x2e, 0x2e, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e,
- 0x00, 0x2e, 0x2e, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x00,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
- 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
- 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1d, 0x1d, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
- 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00,
- 0x15, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x15, 0x15, 0x15, 0x15,
- 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x00, 0x00
- };
-
- private static ReadOnlySpan<byte> CategoriesValue => new byte[172]
- {
- 0x1d, 0x00, 0x0e, 0x0e, 0x0e, 0x10, 0x0e, 0x0f, 0x0e, 0x11, 0x0b, 0x11, 0x18, 0x12, 0x18, 0x0a,
- 0x1a, 0x0a, 0x14, 0x12, 0x15, 0x12, 0x19, 0x09, 0x18, 0x0c, 0x13, 0x09, 0x08, 0x08, 0x19, 0x12,
- 0x00, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x01, 0x00, 0x0b, 0x0c, 0x1c, 0x12, 0x04, 0x00, 0x16, 0x12,
- 0x0f, 0x0e, 0x1c, 0x0a, 0x19, 0x0a, 0x0a, 0x08, 0x17, 0x12, 0x0a, 0x12, 0x02, 0x00, 0x03, 0x00,
- 0x03, 0x12, 0x05, 0x0d, 0x1c, 0x00, 0x07, 0x0d, 0x18, 0x00, 0x13, 0x12, 0x13, 0x03, 0x18, 0x03,
- 0x04, 0x03, 0x0f, 0x0b, 0x19, 0x04, 0x1a, 0x04, 0x18, 0x04, 0x0f, 0x04, 0x04, 0x04, 0x03, 0x04,
- 0x08, 0x0b, 0x18, 0x0b, 0x1c, 0x04, 0x08, 0x03, 0x03, 0x03, 0x1a, 0x03, 0x06, 0x00, 0x08, 0x00,
- 0x0a, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0f, 0x00, 0x0f, 0x03, 0x0c, 0x11, 0x0d, 0x0f, 0x0f, 0x01,
- 0x0f, 0x05, 0x0f, 0x07, 0x0f, 0x02, 0x0f, 0x06, 0x19, 0x0c, 0x0f, 0x13, 0x0f, 0x14, 0x0f, 0x15,
- 0x0f, 0x16, 0x1b, 0x00, 0x10, 0x00, 0x11, 0x00, 0x1b, 0x04, 0x0f, 0x12, 0x09, 0x12, 0x0a, 0x03,
- 0x1c, 0x03, 0x00, 0x03, 0x01, 0x03, 0x0a, 0x0b, 0x0a, 0x04, 0x19, 0x00
- };
-
- // 12:4:4 index table of the Unicode numeric data.
- private static ReadOnlySpan<byte> NumericLevel1Index => new byte[761]
- {
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x0b, 0x01, 0x01, 0x0c, 0x01, 0x01, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x01, 0x01, 0x01,
- 0x14, 0x15, 0x01, 0x01, 0x16, 0x01, 0x01, 0x17, 0x01, 0x01, 0x01, 0x01, 0x18, 0x01, 0x01, 0x01,
- 0x19, 0x1a, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1c, 0x01, 0x1d, 0x1e, 0x1f, 0x20, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x21, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f,
- 0x01, 0x22, 0x23, 0x24, 0x25, 0x01, 0x01, 0x01, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
- 0x2e, 0x2f, 0x20, 0x01, 0x09, 0x01, 0x30, 0x31, 0x32, 0x01, 0x01, 0x01, 0x33, 0x34, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x35, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x36, 0x37, 0x01, 0x01, 0x38, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x39, 0x3a, 0x01, 0x01, 0x01, 0x3b, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3c, 0x1f, 0x01, 0x01, 0x3d, 0x01, 0x01, 0x01,
- 0x01, 0x3e, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3f
- };
-
- private static ReadOnlySpan<byte> NumericLevel2Index => new byte[1024]
- {
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x18, 0x19, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x1c,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
- 0x21, 0x00, 0x22, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x25, 0x00, 0x26, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00,
- 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2e, 0x00, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x3a,
- 0x00, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41,
- 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x50, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39, 0x55,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x58,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x66,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x69, 0x6a, 0x6b,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x6c, 0x6d, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00,
- 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private static ReadOnlySpan<byte> NumericLevel3Index => new byte[1824]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x0f, 0x10, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x13, 0x0e, 0x10, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x15, 0x16, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x19, 0x1a, 0x1b, 0x19, 0x1a, 0x1b, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x00,
- 0x15, 0x16, 0x17, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0f, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x16, 0x3a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x3c,
- 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x44, 0x00, 0x00, 0x00, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x44, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x45, 0x46, 0x20, 0x47, 0x48, 0x22, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x12, 0x4e, 0x4f, 0x50, 0x19,
- 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x15, 0x51, 0x52, 0x35, 0x16, 0x53, 0x17,
- 0x17, 0x54, 0x3a, 0x00, 0x00, 0x40, 0x35, 0x55, 0x56, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15, 0x51, 0x52, 0x57, 0x58, 0x59, 0x14,
- 0x3b, 0x3c, 0x3d, 0x32, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15, 0x51, 0x52,
- 0x57, 0x58, 0x59, 0x14, 0x3b, 0x3c, 0x3d, 0x32, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x15, 0x51, 0x52, 0x57, 0x58, 0x59, 0x14, 0x3b, 0x3c, 0x3d, 0x32, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x51, 0x52, 0x57, 0x58, 0x59,
- 0x14, 0x3b, 0x3c, 0x3d, 0x32, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15, 0x44,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15,
- 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e,
- 0x2f, 0x30, 0x31, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x00, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x33, 0x63, 0x64, 0x65, 0x66, 0x67,
- 0x00, 0x68, 0x69, 0x6a, 0x6b, 0x34, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x35,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x18,
- 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
- 0x15, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x16, 0x75, 0x76, 0x77, 0x53, 0x78, 0x79,
- 0x7a, 0x7b, 0x17, 0x7c, 0x7d, 0x7e, 0x54, 0x7f, 0x80, 0x81, 0x82, 0x3a, 0x83, 0x84, 0x85, 0x55,
- 0x86, 0x87, 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x0f, 0x19, 0x3f, 0x35, 0x53, 0x54, 0x55, 0x3f, 0x15, 0x35, 0x16, 0x53, 0x17, 0x54, 0x3f,
- 0x15, 0x35, 0x16, 0x53, 0x17, 0x3a, 0x55, 0x15, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f,
- 0x15, 0x15, 0x15, 0x15, 0x15, 0x33, 0x35, 0x35, 0x35, 0x35, 0x16, 0x76, 0x53, 0x53, 0x53, 0x53,
- 0x53, 0x17, 0x54, 0x3f, 0x35, 0x0f, 0x0f, 0x48, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36,
- 0x37, 0x38, 0x39, 0x16, 0x75, 0x76, 0x77, 0x53, 0x78, 0x79, 0x7a, 0x7b, 0x00, 0x00, 0x00, 0x00,
- 0x19, 0x3f, 0x15, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x19, 0x1a, 0x15, 0x32, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x15, 0x32, 0x16, 0x17, 0x3a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x15, 0x32,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x3e, 0x3f, 0x15, 0x32, 0x16,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x3f, 0x15, 0x32, 0x16,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x15, 0x32, 0x16, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x0f, 0x00, 0x00,
- 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- 0x00, 0x00, 0x16, 0x75, 0x76, 0x77, 0x53, 0x78, 0x79, 0x7a, 0x7b, 0x17, 0x7c, 0x7d, 0x7e, 0x54,
- 0x7f, 0x80, 0x81, 0x82, 0x3a, 0x83, 0x84, 0x85, 0x55, 0x86, 0x87, 0x88, 0x89, 0x56, 0x8b, 0x8c,
- 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c,
- 0x0d, 0x0b, 0x0c, 0x2c, 0x15, 0x32, 0x16, 0x17, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x35, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x15, 0x32,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x15, 0x32, 0x16, 0x17,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x3e, 0x15, 0x32, 0x16,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x3f, 0x15, 0x35, 0x16, 0x17,
- 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- 0x38, 0x39, 0x16, 0x75, 0x76, 0x77, 0x53, 0x78, 0x79, 0x7a, 0x7b, 0x0f, 0x0e, 0x47, 0x48, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b,
- 0x3e, 0x3f, 0x15, 0x32, 0x33, 0x16, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x19, 0x15, 0x32, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x15, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x16, 0x17, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x37, 0x38, 0x39, 0x16, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x15, 0x32, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36,
- 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40,
- 0x41, 0x42, 0x43, 0x15, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x16, 0x00, 0x00, 0x00,
- 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x3e,
- 0x3f, 0x40, 0x41, 0x42, 0x43, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x19, 0x1a,
- 0x1b, 0x3e, 0x3f, 0x1a, 0x1b, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x19, 0x1a, 0x1b, 0x1b,
- 0x3e, 0x3f, 0x9d, 0x9e, 0x19, 0x1a, 0x1b, 0x1b, 0x3e, 0x3f, 0x1b, 0x1b, 0x3e, 0x3e, 0x3e, 0x3e,
- 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x19,
- 0x1a, 0x1b, 0x3e, 0x3e, 0x3f, 0x3f, 0x1a, 0x1b, 0x19, 0x1a, 0x47, 0x48, 0x4d, 0x47, 0x48, 0x12,
- 0x0e, 0x4c, 0x0e, 0x0e, 0x0f, 0x47, 0x48, 0x34, 0x35, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00, 0x15, 0x16, 0x3a, 0x9f, 0xa0,
- 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x15, 0x51, 0x52, 0x57, 0x58, 0x59,
- 0x14, 0x3b, 0x3c, 0x3d, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x14, 0x3b, 0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x39, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04,
- 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- 0x37, 0x38, 0x39, 0x16, 0x75, 0x76, 0x77, 0x53, 0x78, 0x79, 0x7a, 0x7b, 0x17, 0x7c, 0x7d, 0x7e,
- 0x54, 0x7f, 0x80, 0x81, 0x82, 0x3a, 0x83, 0x84, 0x85, 0x55, 0x86, 0x87, 0x88, 0x89, 0x56, 0x8b,
- 0x56, 0xa3, 0xa4, 0x19, 0x1a, 0x1b, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x00, 0x0e, 0x0f, 0x10,
- 0x00, 0x19, 0x1a, 0x3a, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x44, 0x44, 0x0d, 0x0b, 0x0c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x18, 0x18, 0x00, 0x00, 0x00,
- 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- // Every item contains the value for numeric value.
- private static ReadOnlySpan<byte> NumericValues => new byte[1320]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40,
- 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x79, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3f,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xa3, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xa9, 0x3f,
- 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xb9, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xc3, 0x3f,
- 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xc9, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xbf,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x51, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x56, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xc3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0xc2, 0x3f,
- 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0xbc, 0x3f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xe5, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xd9, 0x3f,
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xe3, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe9, 0x3f,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xc5, 0x3f, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7f, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xb3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe8, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xf8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x42, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x45, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x46, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x47, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x82, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8c, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xa7, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xaf, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xb7, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbf, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xd3, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xed, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf1, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf5, 0x40,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xed, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, 0x12, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x18, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, 0x22, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0xc0, 0x5c, 0x25, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x28, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x77, 0x2b, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xb5, 0x3f,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xc5, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x3f,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xda, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xe2, 0x3f,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xe5, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x3f,
- 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x0a, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x1a, 0x41, 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x2e, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0x84, 0xd7, 0x97, 0x41, 0x00, 0x00, 0x00, 0x20, 0x5f, 0xa0, 0x02, 0x42,
- 0x00, 0x00, 0x00, 0xa2, 0x94, 0x1a, 0x6d, 0x42, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x12, 0x63, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0xd0, 0x12, 0x73, 0x41
- };
-
- private static ReadOnlySpan<byte> DigitValues => new byte[330]
- {
- 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
- 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0xff, 0x02, 0xff, 0x03, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0xff, 0x05, 0xff, 0x06, 0xff, 0x07,
- 0xff, 0x08, 0xff, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
deleted file mode 100644
index 01c6133d404..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
+++ /dev/null
@@ -1,302 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1901/02/19 2101/01/28
- /// ChineseLunisolar 1901/01/01 2100/12/29
- /// </remarks>
-
- public class ChineseLunisolarCalendar : EastAsianLunisolarCalendar
- {
- public const int ChineseEra = 1;
-
- private const int MinLunisolarYear = 1901;
- private const int MaxLunisolarYear = 2100;
-
- private static readonly DateTime s_minDate = new DateTime(1901, 2, 19);
- private static readonly DateTime s_maxDate = new DateTime((new DateTime(2101, 1, 28, 23, 59, 59, 999)).Ticks + 9999);
-
- public override DateTime MinSupportedDateTime => s_minDate;
-
- public override DateTime MaxSupportedDateTime => s_maxDate;
-
- protected override int DaysInYearBeforeMinSupportedYear =>
- // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations [1]
- // [1] Reingold, Edward M, and Nachum Dershowitz. Calendrical Tabulations, 1900 - 2200.Cambridge: Cambridge Univ. Press, 2002.Print.
- 384;
-
- // Data for years 1901-1905 and 1907-2100 matches output of Calendrical Calculations [2] and published calendar tables [3].
- // For 1906, month 4 of the Chinese year starts on 24 Apr 1906 and has 29 days. This is historially accurate
- // but different to the values in [1] and output from [2]. This is due to a change in the astronomical methods used
- // by the Chinese to calculate the calendar from 1913 onwards (see warnings in [1]).
- // [2] Reingold, Edward M, and Nachum Dershowitz. Calendrical Calculations: The Ultimate Edition. Cambridge [etc.: Cambridge University Press, 2018. Print.
- // [3] Wang, Jianmin. Xin Bian Wan Nian Li: (1840-2050) Chong Bian Ben. Beijing: Ke xue pu ji chu ban she, 1990. Print.
- private static readonly int[,] s_yinfo =
- {
-/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
-1901 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1902 */ { 00, 02, 08, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1903 */ { 05, 01, 29, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1904 */ { 00, 02, 16, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1905 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1906 */ { 04, 01, 25, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1907 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1908 */ { 00, 02, 02, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
-1909 */ { 02, 01, 22, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1910 */ { 00, 02, 10, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1911 */ { 06, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1912 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1913 */ { 00, 02, 06, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1914 */ { 05, 01, 26, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1915 */ { 00, 02, 14, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1916 */ { 00, 02, 03, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
-1917 */ { 02, 01, 23, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */ { 00, 02, 11, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1919 */ { 07, 02, 01, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1920 */ { 00, 02, 20, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1921 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1922 */ { 05, 01, 28, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */ { 00, 02, 16, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1924 */ { 00, 02, 05, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1925 */ { 04, 01, 24, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1926 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1927 */ { 00, 02, 02, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
-1928 */ { 02, 01, 23, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1929 */ { 00, 02, 10, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1930 */ { 06, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1932 */ { 00, 02, 06, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-1933 */ { 05, 01, 26, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */ { 00, 02, 14, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
-1935 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1936 */ { 03, 01, 24, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1937 */ { 00, 02, 11, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1938 */ { 07, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */ { 00, 02, 19, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
-1940 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1941 */ { 06, 01, 27, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */ { 00, 02, 15, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1943 */ { 00, 02, 05, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1944 */ { 04, 01, 25, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1945 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1946 */ { 00, 02, 02, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-1947 */ { 02, 01, 22, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1949 */ { 07, 01, 29, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1950 */ { 00, 02, 17, 0b0110110010100000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 354
-1951 */ { 00, 02, 06, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1952 */ { 05, 01, 27, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1953 */ { 00, 02, 14, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
-1954 */ { 00, 02, 03, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-1955 */ { 03, 01, 24, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1957 */ { 08, 01, 31, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1958 */ { 00, 02, 18, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
-1959 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1965 */ { 00, 02, 02, 0b0101001001100000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 353
-1966 */ { 03, 01, 21, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1968 */ { 07, 01, 30, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1970 */ { 00, 02, 06, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */ { 00, 02, 15, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
-1973 */ { 00, 02, 03, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1976 */ { 08, 01, 31, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1978 */ { 00, 02, 07, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
-1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1982 */ { 04, 01, 25, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1987 */ { 06, 01, 29, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
-1988 */ { 00, 02, 17, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1989 */ { 00, 02, 06, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
-1990 */ { 05, 01, 27, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-1995 */ { 08, 01, 31, 0b0110101100101000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1996 */ { 00, 02, 19, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
-1997 */ { 00, 02, 07, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1998 */ { 05, 01, 28, 0b1001001101101000 }, /* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
-1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-2001 */ { 04, 01, 24, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */ { 00, 02, 09, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-2012 */ { 04, 01, 23, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2013 */ { 00, 02, 10, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
-2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-2017 */ { 06, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-2019 */ { 00, 02, 05, 0b1010100100110000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 354
-2020 */ { 04, 01, 25, 0b0111010010101000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-2023 */ { 02, 01, 22, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */ { 00, 02, 17, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
-2027 */ { 00, 02, 06, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-2028 */ { 05, 01, 26, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2029 */ { 00, 02, 13, 0b1101010100110000 }, /* 30 30 29 30 29 30 29 30 29 29 30 30 355
-2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-2031 */ { 03, 01, 23, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */ { 00, 02, 19, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
-2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-2036 */ { 06, 01, 28, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
-2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */ { 00, 02, 12, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
-2041 */ { 00, 02, 01, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-2046 */ { 00, 02, 06, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */ { 00, 02, 14, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
-2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
-2050 */ { 03, 01, 23, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-2051 */ { 00, 02, 11, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-2052 */ { 08, 02, 01, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-2053 */ { 00, 02, 19, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-2054 */ { 00, 02, 08, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-2055 */ { 06, 01, 28, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-2056 */ { 00, 02, 15, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-2057 */ { 00, 02, 04, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-2058 */ { 04, 01, 24, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-2059 */ { 00, 02, 12, 0b1010101011100000 }, /* 30 29 30 29 30 29 30 29 30 30 30 29 355
-2060 */ { 00, 02, 02, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-2061 */ { 03, 01, 21, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-2062 */ { 00, 02, 09, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-2063 */ { 07, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2064 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-2065 */ { 00, 02, 05, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-2066 */ { 05, 01, 26, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2067 */ { 00, 02, 14, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-2068 */ { 00, 02, 03, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
-2069 */ { 04, 01, 23, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-2070 */ { 00, 02, 11, 0b0101001011010000 }, /* 29 30 29 30 29 29 30 29 30 30 29 30 354
-2071 */ { 08, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-2072 */ { 00, 02, 19, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-2073 */ { 00, 02, 07, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-2074 */ { 06, 01, 27, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2075 */ { 00, 02, 15, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-2076 */ { 00, 02, 05, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
-2077 */ { 04, 01, 24, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-2078 */ { 00, 02, 12, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-2079 */ { 00, 02, 02, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-2080 */ { 03, 01, 22, 0b1010100100111000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
-2081 */ { 00, 02, 09, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
-2082 */ { 07, 01, 29, 0b0111001010011000 }, /* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
-2083 */ { 00, 02, 17, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-2084 */ { 00, 02, 06, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-2085 */ { 05, 01, 26, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2086 */ { 00, 02, 14, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-2087 */ { 00, 02, 03, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-2088 */ { 04, 01, 24, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-2089 */ { 00, 02, 10, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
-2090 */ { 08, 01, 30, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2091 */ { 00, 02, 18, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
-2092 */ { 00, 02, 07, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
-2093 */ { 06, 01, 27, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2094 */ { 00, 02, 15, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-2095 */ { 00, 02, 05, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-2096 */ { 04, 01, 25, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-2097 */ { 00, 02, 12, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
-2098 */ { 00, 02, 01, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
-2099 */ { 02, 01, 21, 0b1101100100101000 }, /* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
-2100 */ { 00, 02, 09, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
- */ };
-
- internal override int MinCalendarYear => MinLunisolarYear;
-
- internal override int MaxCalendarYear => MaxLunisolarYear;
-
- internal override DateTime MinDate => s_minDate;
-
- internal override DateTime MaxDate => s_maxDate;
-
- internal override EraInfo[]? CalEraInfo => null;
-
- internal override int GetYearInfo(int lunarYear, int index)
- {
- if (lunarYear < MinLunisolarYear || lunarYear > MaxLunisolarYear)
- {
- throw new ArgumentOutOfRangeException("year", lunarYear, SR.Format(SR.ArgumentOutOfRange_Range, MinLunisolarYear, MaxLunisolarYear));
- }
-
- return s_yinfo[lunarYear - MinLunisolarYear, index];
- }
-
- internal override int GetYear(int year, DateTime time)
- {
- return year;
- }
-
- internal override int GetGregorianYear(int year, int era)
- {
- if (era != CurrentEra && era != ChineseEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < MinLunisolarYear || year > MaxLunisolarYear)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.Format(SR.ArgumentOutOfRange_Range, MinLunisolarYear, MaxLunisolarYear));
- }
-
- return year;
- }
-
- public ChineseLunisolarCalendar()
- {
- }
-
- public override int GetEra(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return ChineseEra;
- }
-
- internal override CalendarId ID => CalendarId.CHINESELUNISOLAR;
-
- internal override CalendarId BaseCalendarID =>
- // Use CAL_GREGORIAN just to get CurrentEraValue as 1 since we do not have data under the ID CAL_ChineseLunisolar yet
- CalendarId.GREGORIAN;
-
- public override int[] Eras => new int[] { ChineseEra };
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
deleted file mode 100644
index 92a962b5273..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
+++ /dev/null
@@ -1,249 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace System.Globalization
-{
- public partial class CompareInfo
- {
- internal static unsafe int InvariantIndexOf(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- Debug.Assert(source != null);
- Debug.Assert(value != null);
- Debug.Assert(startIndex >= 0 && startIndex < source.Length);
-
- fixed (char* pSource = source) fixed (char* pValue = value)
- {
- char* pSrc = &pSource[startIndex];
- int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, fromBeginning: true);
- if (index >= 0)
- {
- return index + startIndex;
- }
- return -1;
- }
- }
-
- internal static unsafe int InvariantIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning = true)
- {
- Debug.Assert(source.Length != 0);
- Debug.Assert(value.Length != 0);
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pValue = &MemoryMarshal.GetReference(value))
- {
- return InvariantFindString(pSource, source.Length, pValue, value.Length, ignoreCase, fromBeginning);
- }
- }
-
- internal static unsafe int InvariantLastIndexOf(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- Debug.Assert(source != null);
- Debug.Assert(value != null);
- Debug.Assert(startIndex >= 0 && startIndex < source.Length);
-
- fixed (char* pSource = source) fixed (char* pValue = value)
- {
- char* pSrc = &pSource[startIndex - count + 1];
- int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, fromBeginning: false);
- if (index >= 0)
- {
- return index + startIndex - count + 1;
- }
- return -1;
- }
- }
-
- private static unsafe int InvariantFindString(char* source, int sourceCount, char* value, int valueCount, bool ignoreCase, bool fromBeginning)
- {
- int ctrSource = 0; // index value into source
- int ctrValue = 0; // index value into value
- char sourceChar; // Character for case lookup in source
- char valueChar; // Character for case lookup in value
- int lastSourceStart;
-
- Debug.Assert(source != null);
- Debug.Assert(value != null);
- Debug.Assert(sourceCount >= 0);
- Debug.Assert(valueCount >= 0);
-
- if (valueCount == 0)
- {
- return fromBeginning ? 0 : sourceCount - 1;
- }
-
- if (sourceCount < valueCount)
- {
- return -1;
- }
-
- if (fromBeginning)
- {
- lastSourceStart = sourceCount - valueCount;
- if (ignoreCase)
- {
- char firstValueChar = InvariantToUpper(value[0]);
- for (ctrSource = 0; ctrSource <= lastSourceStart; ctrSource++)
- {
- sourceChar = InvariantToUpper(source[ctrSource]);
- if (sourceChar != firstValueChar)
- {
- continue;
- }
-
- for (ctrValue = 1; ctrValue < valueCount; ctrValue++)
- {
- sourceChar = InvariantToUpper(source[ctrSource + ctrValue]);
- valueChar = InvariantToUpper(value[ctrValue]);
-
- if (sourceChar != valueChar)
- {
- break;
- }
- }
-
- if (ctrValue == valueCount)
- {
- return ctrSource;
- }
- }
- }
- else
- {
- char firstValueChar = value[0];
- for (ctrSource = 0; ctrSource <= lastSourceStart; ctrSource++)
- {
- sourceChar = source[ctrSource];
- if (sourceChar != firstValueChar)
- {
- continue;
- }
-
- for (ctrValue = 1; ctrValue < valueCount; ctrValue++)
- {
- sourceChar = source[ctrSource + ctrValue];
- valueChar = value[ctrValue];
-
- if (sourceChar != valueChar)
- {
- break;
- }
- }
-
- if (ctrValue == valueCount)
- {
- return ctrSource;
- }
- }
- }
- }
- else
- {
- lastSourceStart = sourceCount - valueCount;
- if (ignoreCase)
- {
- char firstValueChar = InvariantToUpper(value[0]);
- for (ctrSource = lastSourceStart; ctrSource >= 0; ctrSource--)
- {
- sourceChar = InvariantToUpper(source[ctrSource]);
- if (sourceChar != firstValueChar)
- {
- continue;
- }
- for (ctrValue = 1; ctrValue < valueCount; ctrValue++)
- {
- sourceChar = InvariantToUpper(source[ctrSource + ctrValue]);
- valueChar = InvariantToUpper(value[ctrValue]);
-
- if (sourceChar != valueChar)
- {
- break;
- }
- }
-
- if (ctrValue == valueCount)
- {
- return ctrSource;
- }
- }
- }
- else
- {
- char firstValueChar = value[0];
- for (ctrSource = lastSourceStart; ctrSource >= 0; ctrSource--)
- {
- sourceChar = source[ctrSource];
- if (sourceChar != firstValueChar)
- {
- continue;
- }
-
- for (ctrValue = 1; ctrValue < valueCount; ctrValue++)
- {
- sourceChar = source[ctrSource + ctrValue];
- valueChar = value[ctrValue];
-
- if (sourceChar != valueChar)
- {
- break;
- }
- }
-
- if (ctrValue == valueCount)
- {
- return ctrSource;
- }
- }
- }
- }
-
- return -1;
- }
-
- private static char InvariantToUpper(char c)
- {
- return (uint)(c - 'a') <= (uint)('z' - 'a') ? (char)(c - 0x20) : c;
- }
-
- private unsafe SortKey InvariantCreateSortKey(string source, CompareOptions options)
- {
- if (source == null) { throw new ArgumentNullException(nameof(source)); }
-
- if ((options & ValidSortkeyCtorMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- byte[] keyData;
- if (source.Length == 0)
- {
- keyData = Array.Empty<byte>();
- }
- else
- {
- // In the invariant mode, all string comparisons are done as ordinal so when generating the sort keys we generate it according to this fact
- keyData = new byte[source.Length * sizeof(char)];
-
- fixed (char* pChar = source) fixed (byte* pByte = keyData)
- {
- if ((options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0)
- {
- short* pShort = (short*)pByte;
- for (int i = 0; i < source.Length; i++)
- {
- pShort[i] = (short)InvariantToUpper(source[i]);
- }
- }
- else
- {
- Buffer.MemoryCopy(pChar, pByte, keyData.Length, keyData.Length);
- }
- }
- }
- return new SortKey(Name, source, options, keyData);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
deleted file mode 100644
index f77c3913cae..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
+++ /dev/null
@@ -1,1148 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Threading;
-
-using Internal.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- public partial class CompareInfo
- {
- [NonSerialized]
- private IntPtr _sortHandle;
-
- [NonSerialized]
- private bool _isAsciiEqualityOrdinal;
-
- private void InitSort(CultureInfo culture)
- {
- _sortName = culture.SortName;
-
- if (GlobalizationMode.Invariant)
- {
- _isAsciiEqualityOrdinal = true;
- }
- else
- {
- // Inline the following condition to avoid potential implementation cycles within globalization
- //
- // _isAsciiEqualityOrdinal = _sortName == "" || _sortName == "en" || _sortName.StartsWith("en-", StringComparison.Ordinal);
- //
- _isAsciiEqualityOrdinal = _sortName.Length == 0 ||
- (_sortName.Length >= 2 && _sortName[0] == 'e' && _sortName[1] == 'n' && (_sortName.Length == 2 || _sortName[2] == '-'));
-
- _sortHandle = SortHandleCache.GetCachedSortHandle(_sortName);
- }
- }
-
- internal static unsafe int IndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source != null);
- Debug.Assert(value != null);
-
- if (value.Length == 0)
- {
- return startIndex;
- }
-
- if (count < value.Length)
- {
- return -1;
- }
-
- if (ignoreCase)
- {
- fixed (char* pSource = source)
- {
- int index = Interop.Globalization.IndexOfOrdinalIgnoreCase(value, value.Length, pSource + startIndex, count, findLast: false);
- return index != -1 ?
- startIndex + index :
- -1;
- }
- }
-
- int endIndex = startIndex + (count - value.Length);
- for (int i = startIndex; i <= endIndex; i++)
- {
- int valueIndex, sourceIndex;
-
- for (valueIndex = 0, sourceIndex = i;
- valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
- valueIndex++, sourceIndex++) ;
-
- if (valueIndex == value.Length)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- internal static unsafe int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (source.Length < value.Length)
- {
- return -1;
- }
-
- if (ignoreCase)
- {
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pValue = &MemoryMarshal.GetReference(value))
- {
- return Interop.Globalization.IndexOfOrdinalIgnoreCase(pValue, value.Length, pSource, source.Length, findLast: !fromBeginning);
- }
- }
-
- int startIndex, endIndex, jump;
- if (fromBeginning)
- {
- // Left to right, from zero to last possible index in the source string.
- // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
- startIndex = 0;
- endIndex = source.Length - value.Length + 1;
- jump = 1;
- }
- else
- {
- // Right to left, from first possible index in the source string to zero.
- // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
- startIndex = source.Length - value.Length;
- endIndex = -1;
- jump = -1;
- }
-
- for (int i = startIndex; i != endIndex; i += jump)
- {
- int valueIndex, sourceIndex;
-
- for (valueIndex = 0, sourceIndex = i;
- valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
- valueIndex++, sourceIndex++)
- ;
-
- if (valueIndex == value.Length)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- internal static unsafe int LastIndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source != null);
- Debug.Assert(value != null);
-
- if (value.Length == 0)
- {
- return startIndex;
- }
-
- if (count < value.Length)
- {
- return -1;
- }
-
- // startIndex is the index into source where we start search backwards from.
- // leftStartIndex is the index into source of the start of the string that is
- // count characters away from startIndex.
- int leftStartIndex = startIndex - count + 1;
-
- if (ignoreCase)
- {
- fixed (char* pSource = source)
- {
- int lastIndex = Interop.Globalization.IndexOfOrdinalIgnoreCase(value, value.Length, pSource + leftStartIndex, count, findLast: true);
- return lastIndex != -1 ?
- leftStartIndex + lastIndex :
- -1;
- }
- }
-
- for (int i = startIndex - value.Length + 1; i >= leftStartIndex; i--)
- {
- int valueIndex, sourceIndex;
-
- for (valueIndex = 0, sourceIndex = i;
- valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
- valueIndex++, sourceIndex++) ;
-
- if (valueIndex == value.Length) {
- return i;
- }
- }
-
- return -1;
- }
-
- private static unsafe int CompareStringOrdinalIgnoreCase(ref char string1, int count1, ref char string2, int count2)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- fixed (char* char1 = &string1)
- fixed (char* char2 = &string2)
- {
- return Interop.Globalization.CompareStringOrdinalIgnoreCase(char1, count1, char2, count2);
- }
- }
-
- // TODO https://github.com/dotnet/coreclr/issues/13827:
- // This method shouldn't be necessary, as we should be able to just use the overload
- // that takes two spans. But due to this issue, that's adding significant overhead.
- private unsafe int CompareString(ReadOnlySpan<char> string1, string string2, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(string2 != null);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
- fixed (char* pString2 = &string2.GetRawStringData())
- {
- return Interop.Globalization.CompareString(_sortHandle, pString1, string1.Length, pString2, string2.Length, options);
- }
- }
-
- private unsafe int CompareString(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
- fixed (char* pString2 = &MemoryMarshal.GetReference(string2))
- {
- return Interop.Globalization.CompareString(_sortHandle, pString1, string1.Length, pString2, string2.Length, options);
- }
- }
-
- internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!string.IsNullOrEmpty(source));
- Debug.Assert(target != null);
- Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
- Debug.Assert((options & CompareOptions.Ordinal) == 0);
-
- int index;
-
- if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- index = IndexOfOrdinalIgnoreCaseHelper(source.AsSpan(startIndex, count), target.AsSpan(), options, matchLengthPtr, fromBeginning: true);
- else
- index = IndexOfOrdinalHelper(source.AsSpan(startIndex, count), target.AsSpan(), options, matchLengthPtr, fromBeginning: true);
- }
- else
- {
- fixed (char* pSource = source)
- fixed (char* pTarget = target)
- {
- index = Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource + startIndex, count, options, matchLengthPtr);
- }
- }
-
- return index != -1 ? index + startIndex : -1;
- }
-
- // For now, this method is only called from Span APIs with either options == CompareOptions.None or CompareOptions.IgnoreCase
- internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(source.Length != 0);
- Debug.Assert(target.Length != 0);
-
- if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- return IndexOfOrdinalIgnoreCaseHelper(source, target, options, matchLengthPtr, fromBeginning);
- else
- return IndexOfOrdinalHelper(source, target, options, matchLengthPtr, fromBeginning);
- }
- else
- {
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pTarget = &MemoryMarshal.GetReference(target))
- {
- if (fromBeginning)
- return Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options, matchLengthPtr);
- else
- return Interop.Globalization.LastIndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options);
- }
- }
- }
-
- /// <summary>
- /// Duplicate of IndexOfOrdinalHelper that also handles ignore case. Can't converge both methods
- /// as the JIT wouldn't be able to optimize the ignoreCase path away.
- /// </summary>
- /// <returns></returns>
- private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!target.IsEmpty);
- Debug.Assert(_isAsciiEqualityOrdinal);
-
- fixed (char* ap = &MemoryMarshal.GetReference(source))
- fixed (char* bp = &MemoryMarshal.GetReference(target))
- {
- char* a = ap;
- char* b = bp;
-
- for (int j = 0; j < target.Length; j++)
- {
- char targetChar = *(b + j);
- if (targetChar >= 0x80 || HighCharTable[targetChar])
- goto InteropCall;
- }
-
- if (target.Length > source.Length)
- {
- for (int k = 0; k < source.Length; k++)
- {
- char targetChar = *(a + k);
- if (targetChar >= 0x80 || HighCharTable[targetChar])
- goto InteropCall;
- }
- return -1;
- }
-
- int startIndex, endIndex, jump;
- if (fromBeginning)
- {
- // Left to right, from zero to last possible index in the source string.
- // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
- startIndex = 0;
- endIndex = source.Length - target.Length + 1;
- jump = 1;
- }
- else
- {
- // Right to left, from first possible index in the source string to zero.
- // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
- startIndex = source.Length - target.Length;
- endIndex = -1;
- jump = -1;
- }
-
- for (int i = startIndex; i != endIndex; i += jump)
- {
- int targetIndex = 0;
- int sourceIndex = i;
-
- for (; targetIndex < target.Length; targetIndex++, sourceIndex++)
- {
- char valueChar = *(a + sourceIndex);
- char targetChar = *(b + targetIndex);
-
- if (valueChar >= 0x80 || HighCharTable[valueChar])
- goto InteropCall;
-
- if (valueChar == targetChar)
- {
- continue;
- }
-
- // uppercase both chars - notice that we need just one compare per char
- if ((uint)(valueChar - 'a') <= ('z' - 'a'))
- valueChar = (char)(valueChar - 0x20);
- if ((uint)(targetChar - 'a') <= ('z' - 'a'))
- targetChar = (char)(targetChar - 0x20);
-
- if (valueChar == targetChar)
- {
- continue;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
- if (sourceIndex < source.Length - 1 && *(a + sourceIndex + 1) >= 0x80)
- goto InteropCall;
- goto Next;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
- if (sourceIndex < source.Length && *(a + sourceIndex) >= 0x80)
- goto InteropCall;
- if (matchLengthPtr != null)
- *matchLengthPtr = target.Length;
- return i;
-
- Next: ;
- }
-
- return -1;
-
- InteropCall:
- if (fromBeginning)
- return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
- else
- return Interop.Globalization.LastIndexOf(_sortHandle, b, target.Length, a, source.Length, options);
- }
- }
-
- private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!target.IsEmpty);
- Debug.Assert(_isAsciiEqualityOrdinal);
-
- fixed (char* ap = &MemoryMarshal.GetReference(source))
- fixed (char* bp = &MemoryMarshal.GetReference(target))
- {
- char* a = ap;
- char* b = bp;
-
- for (int j = 0; j < target.Length; j++)
- {
- char targetChar = *(b + j);
- if (targetChar >= 0x80 || HighCharTable[targetChar])
- goto InteropCall;
- }
-
- if (target.Length > source.Length)
- {
- for (int k = 0; k < source.Length; k++)
- {
- char targetChar = *(a + k);
- if (targetChar >= 0x80 || HighCharTable[targetChar])
- goto InteropCall;
- }
- return -1;
- }
-
- int startIndex, endIndex, jump;
- if (fromBeginning)
- {
- // Left to right, from zero to last possible index in the source string.
- // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
- startIndex = 0;
- endIndex = source.Length - target.Length + 1;
- jump = 1;
- }
- else
- {
- // Right to left, from first possible index in the source string to zero.
- // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
- startIndex = source.Length - target.Length;
- endIndex = -1;
- jump = -1;
- }
-
- for (int i = startIndex; i != endIndex; i += jump)
- {
- int targetIndex = 0;
- int sourceIndex = i;
-
- for (; targetIndex < target.Length; targetIndex++, sourceIndex++)
- {
- char valueChar = *(a + sourceIndex);
- char targetChar = *(b + targetIndex);
-
- if (valueChar >= 0x80 || HighCharTable[valueChar])
- goto InteropCall;
-
- if (valueChar == targetChar)
- {
- continue;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
- if (sourceIndex < source.Length - 1 && *(a + sourceIndex + 1) >= 0x80)
- goto InteropCall;
- goto Next;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
- if (sourceIndex < source.Length && *(a + sourceIndex) >= 0x80)
- goto InteropCall;
- if (matchLengthPtr != null)
- *matchLengthPtr = target.Length;
- return i;
-
- Next: ;
- }
-
- return -1;
-
- InteropCall:
- if (fromBeginning)
- return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
- else
- return Interop.Globalization.LastIndexOf(_sortHandle, b, target.Length, a, source.Length, options);
- }
- }
-
- private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!string.IsNullOrEmpty(source));
- Debug.Assert(target != null);
- Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
-
- if (target.Length == 0)
- {
- return startIndex;
- }
-
- if (options == CompareOptions.Ordinal)
- {
- return LastIndexOfOrdinalCore(source, target, startIndex, count, ignoreCase: false);
- }
-
- // startIndex is the index into source where we start search backwards from. leftStartIndex is the index into source
- // of the start of the string that is count characters away from startIndex.
- int leftStartIndex = (startIndex - count + 1);
-
- int lastIndex;
-
- if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- lastIndex = IndexOfOrdinalIgnoreCaseHelper(source.AsSpan(leftStartIndex, count), target.AsSpan(), options, matchLengthPtr: null, fromBeginning: false);
- else
- lastIndex = IndexOfOrdinalHelper(source.AsSpan(leftStartIndex, count), target.AsSpan(), options, matchLengthPtr: null, fromBeginning: false);
- }
- else
- {
- fixed (char* pSource = source)
- fixed (char* pTarget = target)
- {
- lastIndex = Interop.Globalization.LastIndexOf(_sortHandle, pTarget, target.Length, pSource + (startIndex - count + 1), count, options);
- }
- }
-
- return lastIndex != -1 ? lastIndex + leftStartIndex : -1;
- }
-
- private unsafe bool StartsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!prefix.IsEmpty);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- return StartsWithOrdinalIgnoreCaseHelper(source, prefix, options);
- else
- return StartsWithOrdinalHelper(source, prefix, options);
- }
- else
- {
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pPrefix = &MemoryMarshal.GetReference(prefix))
- {
- return Interop.Globalization.StartsWith(_sortHandle, pPrefix, prefix.Length, pSource, source.Length, options);
- }
- }
- }
-
- private unsafe bool StartsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!prefix.IsEmpty);
- Debug.Assert(_isAsciiEqualityOrdinal);
-
- int length = Math.Min(source.Length, prefix.Length);
-
- fixed (char* ap = &MemoryMarshal.GetReference(source))
- fixed (char* bp = &MemoryMarshal.GetReference(prefix))
- {
- char* a = ap;
- char* b = bp;
-
- while (length != 0)
- {
- int charA = *a;
- int charB = *b;
-
- if (charA >= 0x80 || charB >= 0x80 || HighCharTable[charA] || HighCharTable[charB])
- goto InteropCall;
-
- if (charA == charB)
- {
- a++; b++;
- length--;
- continue;
- }
-
- // uppercase both chars - notice that we need just one compare per char
- if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
- if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
-
- if (charA == charB)
- {
- a++; b++;
- length--;
- continue;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
- if (a < ap + source.Length - 1 && *(a + 1) >= 0x80)
- goto InteropCall;
- if (b < bp + prefix.Length - 1 && *(b + 1) >= 0x80)
- goto InteropCall;
- return false;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
-
- if (source.Length < prefix.Length)
- {
- if (*b >= 0x80)
- goto InteropCall;
- return false;
- }
-
- if (source.Length > prefix.Length)
- {
- if (*a >= 0x80)
- goto InteropCall;
- }
- return true;
-
- InteropCall:
- return Interop.Globalization.StartsWith(_sortHandle, bp, prefix.Length, ap, source.Length, options);
- }
- }
-
- private unsafe bool StartsWithOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!prefix.IsEmpty);
- Debug.Assert(_isAsciiEqualityOrdinal);
-
- int length = Math.Min(source.Length, prefix.Length);
-
- fixed (char* ap = &MemoryMarshal.GetReference(source))
- fixed (char* bp = &MemoryMarshal.GetReference(prefix))
- {
- char* a = ap;
- char* b = bp;
-
- while (length != 0)
- {
- int charA = *a;
- int charB = *b;
-
- if (charA >= 0x80 || charB >= 0x80 || HighCharTable[charA] || HighCharTable[charB])
- goto InteropCall;
-
- if (charA == charB)
- {
- a++; b++;
- length--;
- continue;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
- if (a < ap + source.Length - 1 && *(a + 1) >= 0x80)
- goto InteropCall;
- if (b < bp + prefix.Length - 1 && *(b + 1) >= 0x80)
- goto InteropCall;
- return false;
- }
-
- // The match may be affected by special character. Verify that the following character is regular ASCII.
-
- if (source.Length < prefix.Length)
- {
- if (*b >= 0x80)
- goto InteropCall;
- return false;
- }
-
- if (source.Length > prefix.Length)
- {
- if (*a >= 0x80)
- goto InteropCall;
- }
- return true;
-
- InteropCall:
- return Interop.Globalization.StartsWith(_sortHandle, bp, prefix.Length, ap, source.Length, options);
- }
- }
-
- private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!suffix.IsEmpty);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- return EndsWithOrdinalIgnoreCaseHelper(source, suffix, options);
- else
- return EndsWithOrdinalHelper(source, suffix, options);
- }
- else
- {
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pSuffix = &MemoryMarshal.GetReference(suffix))
- {
- return Interop.Globalization.EndsWith(_sortHandle, pSuffix, suffix.Length, pSource, source.Length, options);
- }
- }
- }
-
- private unsafe bool EndsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!suffix.IsEmpty);
- Debug.Assert(_isAsciiEqualityOrdinal);
-
- int length = Math.Min(source.Length, suffix.Length);
-
- fixed (char* ap = &MemoryMarshal.GetReference(source))
- fixed (char* bp = &MemoryMarshal.GetReference(suffix))
- {
- char* a = ap + source.Length - 1;
- char* b = bp + suffix.Length - 1;
-
- while (length != 0)
- {
- int charA = *a;
- int charB = *b;
-
- if (charA >= 0x80 || charB >= 0x80 || HighCharTable[charA] || HighCharTable[charB])
- goto InteropCall;
-
- if (charA == charB)
- {
- a--; b--;
- length--;
- continue;
- }
-
- // uppercase both chars - notice that we need just one compare per char
- if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
- if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
-
- if (charA == charB)
- {
- a--; b--;
- length--;
- continue;
- }
-
- return false;
- }
-
- return (source.Length >= suffix.Length);
-
- InteropCall:
- return Interop.Globalization.EndsWith(_sortHandle, bp, suffix.Length, ap, source.Length, options);
- }
- }
-
- private unsafe bool EndsWithOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!suffix.IsEmpty);
- Debug.Assert(_isAsciiEqualityOrdinal);
-
- int length = Math.Min(source.Length, suffix.Length);
-
- fixed (char* ap = &MemoryMarshal.GetReference(source))
- fixed (char* bp = &MemoryMarshal.GetReference(suffix))
- {
- char* a = ap + source.Length - 1;
- char* b = bp + suffix.Length - 1;
-
- while (length != 0)
- {
- int charA = *a;
- int charB = *b;
-
- if (charA >= 0x80 || charB >= 0x80 || HighCharTable[charA] || HighCharTable[charB])
- goto InteropCall;
-
- if (charA == charB)
- {
- a--; b--;
- length--;
- continue;
- }
-
- return false;
- }
-
- return (source.Length >= suffix.Length);
-
- InteropCall:
- return Interop.Globalization.EndsWith(_sortHandle, bp, suffix.Length, ap, source.Length, options);
- }
- }
-
- private unsafe SortKey CreateSortKey(string source, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- if (source==null) { throw new ArgumentNullException(nameof(source)); }
-
- if ((options & ValidSortkeyCtorMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- byte [] keyData;
- if (source.Length == 0)
- {
- keyData = Array.Empty<byte>();
- }
- else
- {
- fixed (char* pSource = source)
- {
- int sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, pSource, source.Length, null, 0, options);
- keyData = new byte[sortKeyLength];
-
- fixed (byte* pSortKey = keyData)
- {
- if (Interop.Globalization.GetSortKey(_sortHandle, pSource, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
- }
- }
- }
-
- return new SortKey(Name, source, options, keyData);
- }
-
- private static unsafe bool IsSortable(char *text, int length)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- int index = 0;
- UnicodeCategory uc;
-
- while (index < length)
- {
- if (char.IsHighSurrogate(text[index]))
- {
- if (index == length - 1 || !char.IsLowSurrogate(text[index+1]))
- return false; // unpaired surrogate
-
- uc = CharUnicodeInfo.GetUnicodeCategory(char.ConvertToUtf32(text[index], text[index+1]));
- if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned)
- return false;
-
- index += 2;
- continue;
- }
-
- if (char.IsLowSurrogate(text[index]))
- {
- return false; // unpaired surrogate
- }
-
- uc = CharUnicodeInfo.GetUnicodeCategory(text[index]);
- if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned)
- {
- return false;
- }
-
- index++;
- }
-
- return true;
- }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
-
- internal unsafe int GetHashCodeOfStringCore(ReadOnlySpan<char> source, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- if (source.Length == 0)
- {
- return 0;
- }
-
- // according to ICU User Guide the performance of ucol_getSortKey is worse when it is called with null output buffer
- // the solution is to try to fill the sort key in a temporary buffer of size equal 4 x string length
- // 1MB is the biggest array that can be rented from ArrayPool.Shared without memory allocation
- int sortKeyLength = (source.Length > 1024 * 1024 / 4) ? 0 : 4 * source.Length;
-
- byte[]? borrowedArray = null;
- Span<byte> sortKey = sortKeyLength <= 1024
- ? stackalloc byte[1024]
- : (borrowedArray = ArrayPool<byte>.Shared.Rent(sortKeyLength));
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- {
- fixed (byte* pSortKey = &MemoryMarshal.GetReference(sortKey))
- {
- sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, pSource, source.Length, pSortKey, sortKey.Length, options);
- }
-
- if (sortKeyLength > sortKey.Length) // slow path for big strings
- {
- if (borrowedArray != null)
- {
- ArrayPool<byte>.Shared.Return(borrowedArray);
- }
-
- sortKey = (borrowedArray = ArrayPool<byte>.Shared.Rent(sortKeyLength));
-
- fixed (byte* pSortKey = &MemoryMarshal.GetReference(sortKey))
- {
- sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, pSource, source.Length, pSortKey, sortKey.Length, options);
- }
- }
- }
-
- if (sortKeyLength == 0 || sortKeyLength > sortKey.Length) // internal error (0) or a bug (2nd call failed) in ucol_getSortKey
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
-
- int hash = Marvin.ComputeHash32(sortKey.Slice(0, sortKeyLength), Marvin.DefaultSeed);
-
- if (borrowedArray != null)
- {
- ArrayPool<byte>.Shared.Return(borrowedArray);
- }
-
- return hash;
- }
-
- private static CompareOptions GetOrdinalCompareOptions(CompareOptions options)
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- {
- return CompareOptions.OrdinalIgnoreCase;
- }
- else
- {
- return CompareOptions.Ordinal;
- }
- }
-
- private static bool CanUseAsciiOrdinalForOptions(CompareOptions options)
- {
- // Unlike the other Ignore options, IgnoreSymbols impacts ASCII characters (e.g. ').
- return (options & CompareOptions.IgnoreSymbols) == 0;
- }
-
- private SortVersion GetSortVersion()
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- int sortVersion = Interop.Globalization.GetSortVersion(_sortHandle);
- return new SortVersion(sortVersion, LCID, new Guid(sortVersion, 0, 0, 0, 0, 0, 0,
- (byte) (LCID >> 24),
- (byte) ((LCID & 0x00FF0000) >> 16),
- (byte) ((LCID & 0x0000FF00) >> 8),
- (byte) (LCID & 0xFF)));
- }
-
- private static class SortHandleCache
- {
- // in most scenarios there is a limited number of cultures with limited number of sort options
- // so caching the sort handles and not freeing them is OK, see https://github.com/dotnet/coreclr/pull/25117 for more
- private static readonly Dictionary<string, IntPtr> s_sortNameToSortHandleCache = new Dictionary<string, IntPtr>();
-
- internal static IntPtr GetCachedSortHandle(string sortName)
- {
- lock (s_sortNameToSortHandleCache)
- {
- if (!s_sortNameToSortHandleCache.TryGetValue(sortName, out IntPtr result))
- {
- Interop.Globalization.ResultCode resultCode = Interop.Globalization.GetSortHandle(sortName, out result);
-
- if (resultCode == Interop.Globalization.ResultCode.OutOfMemory)
- throw new OutOfMemoryException();
- else if (resultCode != Interop.Globalization.ResultCode.Success)
- throw new ExternalException(SR.Arg_ExternalException);
-
- try
- {
- s_sortNameToSortHandleCache.Add(sortName, result);
- }
- catch
- {
- Interop.Globalization.CloseSortHandle(result);
-
- throw;
- }
- }
-
- return result;
- }
- }
- }
-
- private static ReadOnlySpan<bool> HighCharTable => new bool[0x80]
- {
- true, /* 0x0, 0x0 */
- true, /* 0x1, .*/
- true, /* 0x2, .*/
- true, /* 0x3, .*/
- true, /* 0x4, .*/
- true, /* 0x5, .*/
- true, /* 0x6, .*/
- true, /* 0x7, .*/
- true, /* 0x8, .*/
- false, /* 0x9, */
- true, /* 0xA, */
- false, /* 0xB, .*/
- false, /* 0xC, .*/
- true, /* 0xD, */
- true, /* 0xE, .*/
- true, /* 0xF, .*/
- true, /* 0x10, .*/
- true, /* 0x11, .*/
- true, /* 0x12, .*/
- true, /* 0x13, .*/
- true, /* 0x14, .*/
- true, /* 0x15, .*/
- true, /* 0x16, .*/
- true, /* 0x17, .*/
- true, /* 0x18, .*/
- true, /* 0x19, .*/
- true, /* 0x1A, */
- true, /* 0x1B, .*/
- true, /* 0x1C, .*/
- true, /* 0x1D, .*/
- true, /* 0x1E, .*/
- true, /* 0x1F, .*/
- false, /*0x20, */
- false, /*0x21, !*/
- false, /*0x22, "*/
- false, /*0x23, #*/
- false, /*0x24, $*/
- false, /*0x25, %*/
- false, /*0x26, &*/
- true, /*0x27, '*/
- false, /*0x28, (*/
- false, /*0x29, )*/
- false, /*0x2A **/
- false, /*0x2B, +*/
- false, /*0x2C, ,*/
- true, /*0x2D, -*/
- false, /*0x2E, .*/
- false, /*0x2F, /*/
- false, /*0x30, 0*/
- false, /*0x31, 1*/
- false, /*0x32, 2*/
- false, /*0x33, 3*/
- false, /*0x34, 4*/
- false, /*0x35, 5*/
- false, /*0x36, 6*/
- false, /*0x37, 7*/
- false, /*0x38, 8*/
- false, /*0x39, 9*/
- false, /*0x3A, :*/
- false, /*0x3B, ;*/
- false, /*0x3C, <*/
- false, /*0x3D, =*/
- false, /*0x3E, >*/
- false, /*0x3F, ?*/
- false, /*0x40, @*/
- false, /*0x41, A*/
- false, /*0x42, B*/
- false, /*0x43, C*/
- false, /*0x44, D*/
- false, /*0x45, E*/
- false, /*0x46, F*/
- false, /*0x47, G*/
- false, /*0x48, H*/
- false, /*0x49, I*/
- false, /*0x4A, J*/
- false, /*0x4B, K*/
- false, /*0x4C, L*/
- false, /*0x4D, M*/
- false, /*0x4E, N*/
- false, /*0x4F, O*/
- false, /*0x50, P*/
- false, /*0x51, Q*/
- false, /*0x52, R*/
- false, /*0x53, S*/
- false, /*0x54, T*/
- false, /*0x55, U*/
- false, /*0x56, V*/
- false, /*0x57, W*/
- false, /*0x58, X*/
- false, /*0x59, Y*/
- false, /*0x5A, Z*/
- false, /*0x5B, [*/
- false, /*0x5C, \*/
- false, /*0x5D, ]*/
- false, /*0x5E, ^*/
- false, /*0x5F, _*/
- false, /*0x60, `*/
- false, /*0x61, a*/
- false, /*0x62, b*/
- false, /*0x63, c*/
- false, /*0x64, d*/
- false, /*0x65, e*/
- false, /*0x66, f*/
- false, /*0x67, g*/
- false, /*0x68, h*/
- false, /*0x69, i*/
- false, /*0x6A, j*/
- false, /*0x6B, k*/
- false, /*0x6C, l*/
- false, /*0x6D, m*/
- false, /*0x6E, n*/
- false, /*0x6F, o*/
- false, /*0x70, p*/
- false, /*0x71, q*/
- false, /*0x72, r*/
- false, /*0x73, s*/
- false, /*0x74, t*/
- false, /*0x75, u*/
- false, /*0x76, v*/
- false, /*0x77, w*/
- false, /*0x78, x*/
- false, /*0x79, y*/
- false, /*0x7A, z*/
- false, /*0x7B, {*/
- false, /*0x7C, |*/
- false, /*0x7D, }*/
- false, /*0x7E, ~*/
- true, /*0x7F, */
- };
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs
deleted file mode 100644
index 595f64221b1..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs
+++ /dev/null
@@ -1,606 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace System.Globalization
-{
- public partial class CompareInfo
- {
- internal static unsafe IntPtr GetSortHandle(string cultureName)
- {
- if (GlobalizationMode.Invariant)
- {
- return IntPtr.Zero;
- }
-
- IntPtr handle;
- int ret = Interop.Kernel32.LCMapStringEx(cultureName, Interop.Kernel32.LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero);
- if (ret > 0)
- {
- // Even if we can get the sort handle, it is not guaranteed to work when Windows compatibility shim is applied
- // e.g. Windows 7 compatibility mode. We need to ensure it is working before using it.
- // otherwise the whole framework app will not start.
- int hashValue = 0;
- char a = 'a';
- ret = Interop.Kernel32.LCMapStringEx(null, Interop.Kernel32.LCMAP_HASH, &a, 1, &hashValue, sizeof(int), null, null, handle);
- if (ret > 1)
- {
- return handle;
- }
- }
-
- return IntPtr.Zero;
- }
-
- private void InitSort(CultureInfo culture)
- {
- _sortName = culture.SortName;
- _sortHandle = GetSortHandle(_sortName);
- }
-
- private static unsafe int FindStringOrdinal(
- uint dwFindStringOrdinalFlags,
- string stringSource,
- int offset,
- int cchSource,
- string value,
- int cchValue,
- bool bIgnoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(stringSource != null);
- Debug.Assert(value != null);
-
- fixed (char* pSource = stringSource)
- fixed (char* pValue = value)
- {
- int ret = Interop.Kernel32.FindStringOrdinal(
- dwFindStringOrdinalFlags,
- pSource + offset,
- cchSource,
- pValue,
- cchValue,
- bIgnoreCase ? 1 : 0);
- return ret < 0 ? ret : ret + offset;
- }
- }
-
- private static unsafe int FindStringOrdinal(
- uint dwFindStringOrdinalFlags,
- ReadOnlySpan<char> source,
- ReadOnlySpan<char> value,
- bool bIgnoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!value.IsEmpty);
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pValue = &MemoryMarshal.GetReference(value))
- {
- int ret = Interop.Kernel32.FindStringOrdinal(
- dwFindStringOrdinalFlags,
- pSource,
- source.Length,
- pValue,
- value.Length,
- bIgnoreCase ? 1 : 0);
- return ret;
- }
- }
-
- internal static int IndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source != null);
- Debug.Assert(value != null);
-
- return FindStringOrdinal(FIND_FROMSTART, source, startIndex, count, value, value.Length, ignoreCase);
- }
-
- internal static int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source.Length != 0);
- Debug.Assert(value.Length != 0);
-
- uint positionFlag = fromBeginning ? (uint)FIND_FROMSTART : FIND_FROMEND;
- return FindStringOrdinal(positionFlag, source, value, ignoreCase);
- }
-
- internal static int LastIndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source != null);
- Debug.Assert(value != null);
-
- return FindStringOrdinal(FIND_FROMEND, source, startIndex - count + 1, count, value, value.Length, ignoreCase);
- }
-
- private unsafe int GetHashCodeOfStringCore(ReadOnlySpan<char> source, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- if (source.Length == 0)
- {
- return 0;
- }
-
- uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
-
- fixed (char* pSource = source)
- {
- int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- flags,
- pSource, source.Length /* in chars */,
- null, 0,
- null, null, _sortHandle);
- if (sortKeyLength == 0)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
-
- // Note in calls to LCMapStringEx below, the input buffer is specified in wchars (and wchar count),
- // but the output buffer is specified in bytes (and byte count). This is because when generating
- // sort keys, LCMapStringEx treats the output buffer as containing opaque binary data.
- // See https://docs.microsoft.com/en-us/windows/desktop/api/winnls/nf-winnls-lcmapstringex.
-
- byte[]? borrowedArr = null;
- Span<byte> span = sortKeyLength <= 512 ?
- stackalloc byte[512] :
- (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
-
- fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
- {
- if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- flags,
- pSource, source.Length /* in chars */,
- pSortKey, sortKeyLength,
- null, null, _sortHandle) != sortKeyLength)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
- }
-
- int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
-
- // Return the borrowed array if necessary.
- if (borrowedArr != null)
- {
- ArrayPool<byte>.Shared.Return(borrowedArr);
- }
-
- return hash;
- }
- }
-
- private static unsafe int CompareStringOrdinalIgnoreCase(ref char string1, int count1, ref char string2, int count2)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- fixed (char* char1 = &string1)
- fixed (char* char2 = &string2)
- {
- // Use the OS to compare and then convert the result to expected value by subtracting 2
- return Interop.Kernel32.CompareStringOrdinal(char1, count1, char2, count2, true) - 2;
- }
- }
-
- // TODO https://github.com/dotnet/coreclr/issues/13827:
- // This method shouldn't be necessary, as we should be able to just use the overload
- // that takes two spans. But due to this issue, that's adding significant overhead.
- private unsafe int CompareString(ReadOnlySpan<char> string1, string string2, CompareOptions options)
- {
- Debug.Assert(string2 != null);
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- string? localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
-
- fixed (char* pLocaleName = localeName)
- fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
- fixed (char* pString2 = &string2.GetRawStringData())
- {
- Debug.Assert(pString1 != null);
- int result = Interop.Kernel32.CompareStringEx(
- pLocaleName,
- (uint)GetNativeCompareFlags(options),
- pString1,
- string1.Length,
- pString2,
- string2.Length,
- null,
- null,
- _sortHandle);
-
- if (result == 0)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
-
- // Map CompareStringEx return value to -1, 0, 1.
- return result - 2;
- }
- }
-
- private unsafe int CompareString(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- string? localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
-
- fixed (char* pLocaleName = localeName)
- fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
- fixed (char* pString2 = &MemoryMarshal.GetReference(string2))
- {
- Debug.Assert(pString1 != null);
- Debug.Assert(pString2 != null);
- int result = Interop.Kernel32.CompareStringEx(
- pLocaleName,
- (uint)GetNativeCompareFlags(options),
- pString1,
- string1.Length,
- pString2,
- string2.Length,
- null,
- null,
- _sortHandle);
-
- if (result == 0)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
-
- // Map CompareStringEx return value to -1, 0, 1.
- return result - 2;
- }
- }
-
- private unsafe int FindString(
- uint dwFindNLSStringFlags,
- ReadOnlySpan<char> lpStringSource,
- ReadOnlySpan<char> lpStringValue,
- int* pcchFound)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(!lpStringSource.IsEmpty);
- Debug.Assert(!lpStringValue.IsEmpty);
-
- string? localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
-
- fixed (char* pLocaleName = localeName)
- fixed (char* pSource = &MemoryMarshal.GetReference(lpStringSource))
- fixed (char* pValue = &MemoryMarshal.GetReference(lpStringValue))
- {
- return Interop.Kernel32.FindNLSStringEx(
- pLocaleName,
- dwFindNLSStringFlags,
- pSource,
- lpStringSource.Length,
- pValue,
- lpStringValue.Length,
- pcchFound,
- null,
- null,
- _sortHandle);
- }
- }
-
- private unsafe int FindString(
- uint dwFindNLSStringFlags,
- string lpStringSource,
- int startSource,
- int cchSource,
- string lpStringValue,
- int startValue,
- int cchValue,
- int* pcchFound)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(lpStringSource != null);
- Debug.Assert(lpStringValue != null);
-
- string? localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
-
- fixed (char* pLocaleName = localeName)
- fixed (char* pSource = lpStringSource)
- fixed (char* pValue = lpStringValue)
- {
- char* pS = pSource + startSource;
- char* pV = pValue + startValue;
-
- return Interop.Kernel32.FindNLSStringEx(
- pLocaleName,
- dwFindNLSStringFlags,
- pS,
- cchSource,
- pV,
- cchValue,
- pcchFound,
- null,
- null,
- _sortHandle);
- }
- }
-
- internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source != null);
- Debug.Assert(target != null);
- Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
- Debug.Assert((options & CompareOptions.Ordinal) == 0);
-
- int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, startIndex, count,
- target, 0, target.Length, matchLengthPtr);
- if (retValue >= 0)
- {
- return retValue + startIndex;
- }
-
- return -1;
- }
-
- internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(source.Length != 0);
- Debug.Assert(target.Length != 0);
- Debug.Assert(options == CompareOptions.None || options == CompareOptions.IgnoreCase);
-
- uint positionFlag = fromBeginning ? (uint)FIND_FROMSTART : FIND_FROMEND;
- return FindString(positionFlag | (uint)GetNativeCompareFlags(options), source, target, matchLengthPtr);
- }
-
- private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!string.IsNullOrEmpty(source));
- Debug.Assert(target != null);
- Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
-
- if (target.Length == 0)
- return startIndex;
-
- if ((options & CompareOptions.Ordinal) != 0)
- {
- return FastLastIndexOfString(source, target, startIndex, count, target.Length);
- }
- else
- {
- int retValue = FindString(FIND_FROMEND | (uint)GetNativeCompareFlags(options), source, startIndex - count + 1,
- count, target, 0, target.Length, null);
-
- if (retValue >= 0)
- {
- return retValue + startIndex - (count - 1);
- }
- }
-
- return -1;
- }
-
- private unsafe bool StartsWith(string source, string prefix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!string.IsNullOrEmpty(source));
- Debug.Assert(!string.IsNullOrEmpty(prefix));
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length,
- prefix, 0, prefix.Length, null) >= 0;
- }
-
- private unsafe bool StartsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!prefix.IsEmpty);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, prefix, null) >= 0;
- }
-
- private unsafe bool EndsWith(string source, string suffix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!string.IsNullOrEmpty(source));
- Debug.Assert(!string.IsNullOrEmpty(suffix));
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length,
- suffix, 0, suffix.Length, null) >= 0;
- }
-
- private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!suffix.IsEmpty);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, suffix, null) >= 0;
- }
-
- // PAL ends here
- [NonSerialized]
- private IntPtr _sortHandle;
-
- private const uint LCMAP_SORTKEY = 0x00000400;
-
- private const int FIND_STARTSWITH = 0x00100000;
- private const int FIND_ENDSWITH = 0x00200000;
- private const int FIND_FROMSTART = 0x00400000;
- private const int FIND_FROMEND = 0x00800000;
-
- // TODO: Instead of this method could we just have upstack code call LastIndexOfOrdinal with ignoreCase = false?
- private static unsafe int FastLastIndexOfString(string source, string target, int startIndex, int sourceCount, int targetCount)
- {
- int retValue = -1;
-
- int sourceStartIndex = startIndex - sourceCount + 1;
-
- fixed (char* pSource = source, spTarget = target)
- {
- char* spSubSource = pSource + sourceStartIndex;
-
- int endPattern = sourceCount - targetCount;
- if (endPattern < 0)
- return -1;
-
- Debug.Assert(target.Length >= 1);
- char patternChar0 = spTarget[0];
- for (int ctrSrc = endPattern; ctrSrc >= 0; ctrSrc--)
- {
- if (spSubSource[ctrSrc] != patternChar0)
- continue;
-
- int ctrPat;
- for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
- {
- if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
- break;
- }
- if (ctrPat == targetCount)
- {
- retValue = ctrSrc;
- break;
- }
- }
-
- if (retValue >= 0)
- {
- retValue += startIndex - sourceCount + 1;
- }
- }
-
- return retValue;
- }
-
- private unsafe SortKey CreateSortKey(string source, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- if (source == null) { throw new ArgumentNullException(nameof(source)); }
-
- if ((options & ValidSortkeyCtorMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- byte[] keyData;
- if (source.Length == 0)
- {
- keyData = Array.Empty<byte>();
- }
- else
- {
- uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
-
- fixed (char* pSource = source)
- {
- int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- flags,
- pSource, source.Length,
- null, 0,
- null, null, _sortHandle);
- if (sortKeyLength == 0)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
-
- keyData = new byte[sortKeyLength];
-
- fixed (byte* pBytes = keyData)
- {
- if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- flags,
- pSource, source.Length,
- pBytes, keyData.Length,
- null, null, _sortHandle) != sortKeyLength)
- {
- throw new ArgumentException(SR.Arg_ExternalException);
- }
- }
- }
- }
-
- return new SortKey(Name, source, options, keyData);
- }
-
- private static unsafe bool IsSortable(char* text, int length)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(text != null);
-
- return Interop.Kernel32.IsNLSDefinedString(Interop.Kernel32.COMPARE_STRING, 0, IntPtr.Zero, text, length);
- }
-
- private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal
- private const int NORM_IGNORECASE = 0x00000001; // Ignores case. (use LINGUISTIC_IGNORECASE instead)
- private const int NORM_IGNOREKANATYPE = 0x00010000; // Does not differentiate between Hiragana and Katakana characters. Corresponding Hiragana and Katakana will compare as equal.
- private const int NORM_IGNORENONSPACE = 0x00000002; // Ignores nonspacing. This flag also removes Japanese accent characters. (use LINGUISTIC_IGNOREDIACRITIC instead)
- private const int NORM_IGNORESYMBOLS = 0x00000004; // Ignores symbols.
- private const int NORM_IGNOREWIDTH = 0x00020000; // Does not differentiate between a single-byte character and the same character as a double-byte character.
- private const int NORM_LINGUISTIC_CASING = 0x08000000; // use linguistic rules for casing
- private const int SORT_STRINGSORT = 0x00001000; // Treats punctuation the same as symbols.
-
- private static int GetNativeCompareFlags(CompareOptions options)
- {
- // Use "linguistic casing" by default (load the culture's casing exception tables)
- int nativeCompareFlags = NORM_LINGUISTIC_CASING;
-
- if ((options & CompareOptions.IgnoreCase) != 0) { nativeCompareFlags |= NORM_IGNORECASE; }
- if ((options & CompareOptions.IgnoreKanaType) != 0) { nativeCompareFlags |= NORM_IGNOREKANATYPE; }
- if ((options & CompareOptions.IgnoreNonSpace) != 0) { nativeCompareFlags |= NORM_IGNORENONSPACE; }
- if ((options & CompareOptions.IgnoreSymbols) != 0) { nativeCompareFlags |= NORM_IGNORESYMBOLS; }
- if ((options & CompareOptions.IgnoreWidth) != 0) { nativeCompareFlags |= NORM_IGNOREWIDTH; }
- if ((options & CompareOptions.StringSort) != 0) { nativeCompareFlags |= SORT_STRINGSORT; }
-
- // TODO: Can we try for GetNativeCompareFlags to never
- // take Ordinal or OrdinalIgnoreCase. This value is not part of Win32, we just handle it special
- // in some places.
- // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag
- if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; }
-
- Debug.Assert(((options & ~(CompareOptions.IgnoreCase |
- CompareOptions.IgnoreKanaType |
- CompareOptions.IgnoreNonSpace |
- CompareOptions.IgnoreSymbols |
- CompareOptions.IgnoreWidth |
- CompareOptions.StringSort)) == 0) ||
- (options == CompareOptions.Ordinal), "[CompareInfo.GetNativeCompareFlags]Expected all flags to be handled");
-
- return nativeCompareFlags;
- }
-
- private unsafe SortVersion GetSortVersion()
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Interop.Kernel32.NlsVersionInfoEx nlsVersion = default;
- nlsVersion.dwNLSVersionInfoSize = sizeof(Interop.Kernel32.NlsVersionInfoEx);
- Interop.Kernel32.GetNLSVersionEx(Interop.Kernel32.COMPARE_STRING, _sortName, &nlsVersion);
- return new SortVersion(
- nlsVersion.dwNLSVersion,
- nlsVersion.dwEffectiveId == 0 ? LCID : nlsVersion.dwEffectiveId,
- nlsVersion.guidCustomVersion);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
deleted file mode 100644
index 3b8350f34ea..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
+++ /dev/null
@@ -1,1503 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-using System.Text.Unicode;
-using Internal.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class implements a set of methods for comparing strings.
- /// </summary>
- [Serializable]
- [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public partial class CompareInfo : IDeserializationCallback
- {
- // Mask used to check if IndexOf()/LastIndexOf()/IsPrefix()/IsPostfix() has the right flags.
- private const CompareOptions ValidIndexMaskOffFlags =
- ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
- CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType);
-
- // Mask used to check if Compare() has the right flags.
- private const CompareOptions ValidCompareMaskOffFlags =
- ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
- CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort);
-
- // Mask used to check if GetHashCodeOfString() has the right flags.
- private const CompareOptions ValidHashCodeOfStringMaskOffFlags =
- ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
- CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType);
-
- // Mask used to check if we have the right flags.
- private const CompareOptions ValidSortkeyCtorMaskOffFlags =
- ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
- CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort);
-
- // Cache the invariant CompareInfo
- internal static readonly CompareInfo Invariant = CultureInfo.InvariantCulture.CompareInfo;
-
- // CompareInfos have an interesting identity. They are attached to the locale that created them,
- // ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US.
- // The interesting part is that since haw-US doesn't have its own sort, it has to point at another
- // locale, which is what SCOMPAREINFO does.
- [OptionalField(VersionAdded = 2)]
- private string m_name; // The name used to construct this CompareInfo. Do not rename (binary serialization)
-
- [NonSerialized]
- private string _sortName = null!; // The name that defines our behavior
-
- [OptionalField(VersionAdded = 3)]
- private SortVersion? m_SortVersion; // Do not rename (binary serialization)
-
- private int culture; // Do not rename (binary serialization). The fields sole purpose is to support Desktop serialization.
-
- internal CompareInfo(CultureInfo culture)
- {
- m_name = culture._name;
- InitSort(culture);
- }
-
- /// <summary>
- /// Get the CompareInfo constructed from the data table in the specified
- /// assembly for the specified culture.
- /// Warning: The assembly versioning mechanism is dead!
- /// </summary>
- public static CompareInfo GetCompareInfo(int culture, Assembly assembly)
- {
- // Parameter checking.
- if (assembly == null)
- {
- throw new ArgumentNullException(nameof(assembly));
- }
- if (assembly != typeof(object).Module.Assembly)
- {
- throw new ArgumentException(SR.Argument_OnlyMscorlib, nameof(assembly));
- }
-
- return GetCompareInfo(culture);
- }
-
- /// <summary>
- /// Get the CompareInfo constructed from the data table in the specified
- /// assembly for the specified culture.
- /// The purpose of this method is to provide version for CompareInfo tables.
- /// </summary>
- public static CompareInfo GetCompareInfo(string name, Assembly assembly)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
- if (assembly == null)
- {
- throw new ArgumentNullException(nameof(assembly));
- }
- if (assembly != typeof(object).Module.Assembly)
- {
- throw new ArgumentException(SR.Argument_OnlyMscorlib, nameof(assembly));
- }
-
- return GetCompareInfo(name);
- }
-
- /// <summary>
- /// Get the CompareInfo for the specified culture.
- /// This method is provided for ease of integration with NLS-based software.
- /// </summary>
- public static CompareInfo GetCompareInfo(int culture)
- {
- if (CultureData.IsCustomCultureId(culture))
- {
- throw new ArgumentException(SR.Argument_CustomCultureCannotBePassedByNumber, nameof(culture));
- }
-
- return CultureInfo.GetCultureInfo(culture).CompareInfo;
- }
-
- /// <summary>
- /// Get the CompareInfo for the specified culture.
- /// </summary>
- public static CompareInfo GetCompareInfo(string name)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- return CultureInfo.GetCultureInfo(name).CompareInfo;
- }
-
- public static unsafe bool IsSortable(char ch)
- {
- if (GlobalizationMode.Invariant)
- {
- return true;
- }
-
- char* pChar = &ch;
- return IsSortable(pChar, 1);
- }
-
- public static unsafe bool IsSortable(string text)
- {
- if (text == null)
- {
- throw new ArgumentNullException(nameof(text));
- }
-
- if (text.Length == 0)
- {
- return false;
- }
-
- if (GlobalizationMode.Invariant)
- {
- return true;
- }
-
- fixed (char* pChar = text)
- {
- return IsSortable(pChar, text.Length);
- }
- }
-
- [OnDeserializing]
- private void OnDeserializing(StreamingContext ctx)
- {
- // this becomes null for a brief moment before deserialization
- // after serialization is finished it is never null.
- m_name = null!;
- }
-
- void IDeserializationCallback.OnDeserialization(object? sender)
- {
- OnDeserialized();
- }
-
- [OnDeserialized]
- private void OnDeserialized(StreamingContext ctx)
- {
- OnDeserialized();
- }
-
- private void OnDeserialized()
- {
- // If we didn't have a name, use the LCID
- if (m_name == null)
- {
- // From whidbey, didn't have a name
- m_name = CultureInfo.GetCultureInfo(culture)._name;
- }
- else
- {
- InitSort(CultureInfo.GetCultureInfo(m_name));
- }
- }
-
- [OnSerializing]
- private void OnSerializing(StreamingContext ctx)
- {
- // This is merely for serialization compatibility with Whidbey/Orcas, it can go away when we don't want that compat any more.
- culture = CultureInfo.GetCultureInfo(Name).LCID; // This is the lcid of the constructing culture (still have to dereference to get target sort)
- Debug.Assert(m_name != null, "CompareInfo.OnSerializing - expected m_name to be set already");
- }
-
- /// <summary>
- /// Returns the name of the culture (well actually, of the sort).
- /// Very important for providing a non-LCID way of identifying
- /// what the sort is.
- ///
- /// Note that this name isn't dereferenced in case the CompareInfo is a different locale
- /// which is consistent with the behaviors of earlier versions. (so if you ask for a sort
- /// and the locale's changed behavior, then you'll get changed behavior, which is like
- /// what happens for a version update)
- /// </summary>
- public virtual string Name
- {
- get
- {
- Debug.Assert(m_name != null, "CompareInfo.Name Expected _name to be set");
- if (m_name == "zh-CHT" || m_name == "zh-CHS")
- {
- return m_name;
- }
-
- return _sortName;
- }
- }
-
- /// <summary>
- /// Compares the two strings with the given options. Returns 0 if the
- /// two strings are equal, a number less than 0 if string1 is less
- /// than string2, and a number greater than 0 if string1 is greater
- /// than string2.
- /// </summary>
- public virtual int Compare(string? string1, string? string2)
- {
- return Compare(string1, string2, CompareOptions.None);
- }
-
- public virtual int Compare(string? string1, string? string2, CompareOptions options)
- {
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return string.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
- }
-
- // Verify the options before we do any real comparison.
- if ((options & CompareOptions.Ordinal) != 0)
- {
- if (options != CompareOptions.Ordinal)
- {
- throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
- }
-
- return string.CompareOrdinal(string1, string2);
- }
-
- if ((options & ValidCompareMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- // Our paradigm is that null sorts less than any other string and
- // that two nulls sort as equal.
- if (string1 == null)
- {
- if (string2 == null)
- {
- return 0;
- }
- return -1; // null < non-null
- }
- if (string2 == null)
- {
- return 1; // non-null > null
- }
-
- if (GlobalizationMode.Invariant)
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- {
- return CompareOrdinalIgnoreCase(string1, string2);
- }
-
- return string.CompareOrdinal(string1, string2);
- }
-
- return CompareString(string1.AsSpan(), string2.AsSpan(), options);
- }
-
- // TODO https://github.com/dotnet/coreclr/issues/13827:
- // This method shouldn't be necessary, as we should be able to just use the overload
- // that takes two spans. But due to this issue, that's adding significant overhead.
- internal int Compare(ReadOnlySpan<char> string1, string? string2, CompareOptions options)
- {
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return CompareOrdinalIgnoreCase(string1, string2.AsSpan());
- }
-
- // Verify the options before we do any real comparison.
- if ((options & CompareOptions.Ordinal) != 0)
- {
- if (options != CompareOptions.Ordinal)
- {
- throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
- }
-
- return string.CompareOrdinal(string1, string2.AsSpan());
- }
-
- if ((options & ValidCompareMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- // null sorts less than any other string.
- if (string2 == null)
- {
- return 1;
- }
-
- if (GlobalizationMode.Invariant)
- {
- return (options & CompareOptions.IgnoreCase) != 0 ?
- CompareOrdinalIgnoreCase(string1, string2.AsSpan()) :
- string.CompareOrdinal(string1, string2.AsSpan());
- }
-
- return CompareString(string1, string2, options);
- }
-
- internal int CompareOptionNone(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
- {
- // Check for empty span or span from a null string
- if (string1.Length == 0 || string2.Length == 0)
- {
- return string1.Length - string2.Length;
- }
-
- return GlobalizationMode.Invariant ?
- string.CompareOrdinal(string1, string2) :
- CompareString(string1, string2, CompareOptions.None);
- }
-
- internal int CompareOptionIgnoreCase(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
- {
- // Check for empty span or span from a null string
- if (string1.Length == 0 || string2.Length == 0)
- {
- return string1.Length - string2.Length;
- }
-
- return GlobalizationMode.Invariant ?
- CompareOrdinalIgnoreCase(string1, string2) :
- CompareString(string1, string2, CompareOptions.IgnoreCase);
- }
-
- /// <summary>
- /// Compares the specified regions of the two strings with the given
- /// options.
- /// Returns 0 if the two strings are equal, a number less than 0 if
- /// string1 is less than string2, and a number greater than 0 if
- /// string1 is greater than string2.
- /// </summary>
- public virtual int Compare(string? string1, int offset1, int length1, string? string2, int offset2, int length2)
- {
- return Compare(string1, offset1, length1, string2, offset2, length2, 0);
- }
-
- public virtual int Compare(string? string1, int offset1, string? string2, int offset2, CompareOptions options)
- {
- return Compare(string1, offset1, string1 == null ? 0 : string1.Length - offset1,
- string2, offset2, string2 == null ? 0 : string2.Length - offset2, options);
- }
-
- public virtual int Compare(string? string1, int offset1, string? string2, int offset2)
- {
- return Compare(string1, offset1, string2, offset2, 0);
- }
-
- public virtual int Compare(string? string1, int offset1, int length1, string? string2, int offset2, int length2, CompareOptions options)
- {
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- int result = string.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
- if ((length1 != length2) && result == 0)
- {
- return length1 > length2 ? 1 : -1;
- }
-
- return result;
- }
-
- if (length1 < 0 || length2 < 0)
- {
- throw new ArgumentOutOfRangeException((length1 < 0) ? nameof(length1) : nameof(length2), SR.ArgumentOutOfRange_NeedPosNum);
- }
- if (offset1 < 0 || offset2 < 0)
- {
- throw new ArgumentOutOfRangeException((offset1 < 0) ? nameof(offset1) : nameof(offset2), SR.ArgumentOutOfRange_NeedPosNum);
- }
- if (offset1 > (string1 == null ? 0 : string1.Length) - length1)
- {
- throw new ArgumentOutOfRangeException(nameof(string1), SR.ArgumentOutOfRange_OffsetLength);
- }
- if (offset2 > (string2 == null ? 0 : string2.Length) - length2)
- {
- throw new ArgumentOutOfRangeException(nameof(string2), SR.ArgumentOutOfRange_OffsetLength);
- }
- if ((options & CompareOptions.Ordinal) != 0)
- {
- if (options != CompareOptions.Ordinal)
- {
- throw new ArgumentException(SR.Argument_CompareOptionOrdinal,
- nameof(options));
- }
- }
- else if ((options & ValidCompareMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- if (string1 == null)
- {
- if (string2 == null)
- {
- return 0;
- }
- return -1;
- }
- if (string2 == null)
- {
- return 1;
- }
-
- ReadOnlySpan<char> span1 = string1.AsSpan(offset1, length1);
- ReadOnlySpan<char> span2 = string2.AsSpan(offset2, length2);
-
- if (options == CompareOptions.Ordinal)
- {
- return string.CompareOrdinal(span1, span2);
- }
-
- if (GlobalizationMode.Invariant)
- {
- if ((options & CompareOptions.IgnoreCase) != 0)
- {
- return CompareOrdinalIgnoreCase(span1, span2);
- }
-
- return string.CompareOrdinal(span1, span2);
- }
-
- return CompareString(span1, span2, options);
- }
-
- /// <summary>
- /// CompareOrdinalIgnoreCase compare two string ordinally with ignoring the case.
- /// it assumes the strings are Ascii string till we hit non Ascii character in strA or strB and then we continue the comparison by
- /// calling the OS.
- /// </summary>
- internal static int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB)
- {
- Debug.Assert(indexA + lengthA <= strA.Length);
- Debug.Assert(indexB + lengthB <= strB.Length);
- return CompareOrdinalIgnoreCase(
- ref Unsafe.Add(ref strA.GetRawStringData(), indexA),
- lengthA,
- ref Unsafe.Add(ref strB.GetRawStringData(), indexB),
- lengthB);
- }
-
- internal static int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
- {
- return CompareOrdinalIgnoreCase(ref MemoryMarshal.GetReference(strA), strA.Length, ref MemoryMarshal.GetReference(strB), strB.Length);
- }
-
- internal static int CompareOrdinalIgnoreCase(string strA, string strB)
- {
- return CompareOrdinalIgnoreCase(ref strA.GetRawStringData(), strA.Length, ref strB.GetRawStringData(), strB.Length);
- }
-
- internal static int CompareOrdinalIgnoreCase(ref char strA, int lengthA, ref char strB, int lengthB)
- {
- int length = Math.Min(lengthA, lengthB);
- int range = length;
-
- ref char charA = ref strA;
- ref char charB = ref strB;
-
- // in InvariantMode we support all range and not only the ascii characters.
- char maxChar = (GlobalizationMode.Invariant ? (char)0xFFFF : (char)0x7F);
-
- while (length != 0 && charA <= maxChar && charB <= maxChar)
- {
- // Ordinal equals or lowercase equals if the result ends up in the a-z range
- if (charA == charB ||
- ((charA | 0x20) == (charB | 0x20) &&
- (uint)((charA | 0x20) - 'a') <= (uint)('z' - 'a')))
- {
- length--;
- charA = ref Unsafe.Add(ref charA, 1);
- charB = ref Unsafe.Add(ref charB, 1);
- }
- else
- {
- int currentA = charA;
- int currentB = charB;
-
- // Uppercase both chars if needed
- if ((uint)(charA - 'a') <= 'z' - 'a')
- {
- currentA -= 0x20;
- }
- if ((uint)(charB - 'a') <= 'z' - 'a')
- {
- currentB -= 0x20;
- }
-
- // Return the (case-insensitive) difference between them.
- return currentA - currentB;
- }
- }
-
- if (length == 0)
- {
- return lengthA - lengthB;
- }
-
- Debug.Assert(!GlobalizationMode.Invariant);
-
- range -= length;
-
- return CompareStringOrdinalIgnoreCase(ref charA, lengthA - range, ref charB, lengthB - range);
- }
-
- internal static bool EqualsOrdinalIgnoreCase(ref char charA, ref char charB, int length)
- {
- IntPtr byteOffset = IntPtr.Zero;
-
-#if BIT64
- // Read 4 chars (64 bits) at a time from each string
- while ((uint)length >= 4)
- {
- ulong valueA = Unsafe.ReadUnaligned<ulong>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charA, byteOffset)));
- ulong valueB = Unsafe.ReadUnaligned<ulong>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charB, byteOffset)));
-
- // A 32-bit test - even with the bit-twiddling here - is more efficient than a 64-bit test.
- ulong temp = valueA | valueB;
- if (!Utf16Utility.AllCharsInUInt32AreAscii((uint)temp | (uint)(temp >> 32)))
- {
- goto NonAscii; // one of the inputs contains non-ASCII data
- }
-
- // Generally, the caller has likely performed a first-pass check that the input strings
- // are likely equal. Consider a dictionary which computes the hash code of its key before
- // performing a proper deep equality check of the string contents. We want to optimize for
- // the case where the equality check is likely to succeed, which means that we want to avoid
- // branching within this loop unless we're about to exit the loop, either due to failure or
- // due to us running out of input data.
-
- if (!Utf16Utility.UInt64OrdinalIgnoreCaseAscii(valueA, valueB))
- {
- return false;
- }
-
- byteOffset += 8;
- length -= 4;
- }
-#endif
-
- // Read 2 chars (32 bits) at a time from each string
-#if BIT64
- if ((uint)length >= 2)
-#else
- while ((uint)length >= 2)
-#endif
- {
- uint valueA = Unsafe.ReadUnaligned<uint>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charA, byteOffset)));
- uint valueB = Unsafe.ReadUnaligned<uint>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charB, byteOffset)));
-
- if (!Utf16Utility.AllCharsInUInt32AreAscii(valueA | valueB))
- {
- goto NonAscii; // one of the inputs contains non-ASCII data
- }
-
- // Generally, the caller has likely performed a first-pass check that the input strings
- // are likely equal. Consider a dictionary which computes the hash code of its key before
- // performing a proper deep equality check of the string contents. We want to optimize for
- // the case where the equality check is likely to succeed, which means that we want to avoid
- // branching within this loop unless we're about to exit the loop, either due to failure or
- // due to us running out of input data.
-
- if (!Utf16Utility.UInt32OrdinalIgnoreCaseAscii(valueA, valueB))
- {
- return false;
- }
-
- byteOffset += 4;
- length -= 2;
- }
-
- if (length != 0)
- {
- Debug.Assert(length == 1);
-
- uint valueA = Unsafe.AddByteOffset(ref charA, byteOffset);
- uint valueB = Unsafe.AddByteOffset(ref charB, byteOffset);
-
- if ((valueA | valueB) > 0x7Fu)
- {
- goto NonAscii; // one of the inputs contains non-ASCII data
- }
-
- if (valueA == valueB)
- {
- return true; // exact match
- }
-
- valueA |= 0x20u;
- if ((uint)(valueA - 'a') > (uint)('z' - 'a'))
- {
- return false; // not exact match, and first input isn't in [A-Za-z]
- }
-
- // The ternary operator below seems redundant but helps RyuJIT generate more optimal code.
- // See https://github.com/dotnet/coreclr/issues/914.
- return (valueA == (valueB | 0x20u)) ? true : false;
- }
-
- Debug.Assert(length == 0);
- return true;
-
- NonAscii:
- // The non-ASCII case is factored out into its own helper method so that the JIT
- // doesn't need to emit a complex prolog for its caller (this method).
- return EqualsOrdinalIgnoreCaseNonAscii(ref Unsafe.AddByteOffset(ref charA, byteOffset), ref Unsafe.AddByteOffset(ref charB, byteOffset), length);
- }
-
- private static bool EqualsOrdinalIgnoreCaseNonAscii(ref char charA, ref char charB, int length)
- {
- if (!GlobalizationMode.Invariant)
- {
- return CompareStringOrdinalIgnoreCase(ref charA, length, ref charB, length) == 0;
- }
- else
- {
- // If we don't have localization tables to consult, we'll still perform a case-insensitive
- // check for ASCII characters, but if we see anything outside the ASCII range we'll immediately
- // fail if it doesn't have true bitwise equality.
-
- IntPtr byteOffset = IntPtr.Zero;
- while (length != 0)
- {
- // Ordinal equals or lowercase equals if the result ends up in the a-z range
- uint valueA = Unsafe.AddByteOffset(ref charA, byteOffset);
- uint valueB = Unsafe.AddByteOffset(ref charB, byteOffset);
-
- if (valueA == valueB ||
- ((valueA | 0x20) == (valueB | 0x20) &&
- (uint)((valueA | 0x20) - 'a') <= (uint)('z' - 'a')))
- {
- byteOffset += 2;
- length--;
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
- }
-
- /// <summary>
- /// Determines whether prefix is a prefix of string. If prefix equals
- /// string.Empty, true is returned.
- /// </summary>
- public virtual bool IsPrefix(string source, string prefix, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (prefix == null)
- {
- throw new ArgumentNullException(nameof(prefix));
- }
-
- if (prefix.Length == 0)
- {
- return true;
- }
- if (source.Length == 0)
- {
- return false;
- }
-
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
- }
-
- if (options == CompareOptions.Ordinal)
- {
- return source.StartsWith(prefix, StringComparison.Ordinal);
- }
-
- if ((options & ValidIndexMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- if (GlobalizationMode.Invariant)
- {
- return source.StartsWith(prefix, (options & CompareOptions.IgnoreCase) != 0 ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
- }
-
- return StartsWith(source, prefix, options);
- }
-
- internal bool IsPrefix(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
- {
- Debug.Assert(prefix.Length != 0);
- Debug.Assert(source.Length != 0);
- Debug.Assert((options & ValidIndexMaskOffFlags) == 0);
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- return StartsWith(source, prefix, options);
- }
-
- public virtual bool IsPrefix(string source, string prefix)
- {
- return IsPrefix(source, prefix, 0);
- }
-
- /// <summary>
- /// Determines whether suffix is a suffix of string. If suffix equals
- /// string.Empty, true is returned.
- /// </summary>
- public virtual bool IsSuffix(string source, string suffix, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (suffix == null)
- {
- throw new ArgumentNullException(nameof(suffix));
- }
-
- if (suffix.Length == 0)
- {
- return true;
- }
- if (source.Length == 0)
- {
- return false;
- }
-
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return source.EndsWith(suffix, StringComparison.OrdinalIgnoreCase);
- }
-
- if (options == CompareOptions.Ordinal)
- {
- return source.EndsWith(suffix, StringComparison.Ordinal);
- }
-
- if ((options & ValidIndexMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- if (GlobalizationMode.Invariant)
- {
- return source.EndsWith(suffix, (options & CompareOptions.IgnoreCase) != 0 ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
- }
-
- return EndsWith(source, suffix, options);
- }
-
- internal bool IsSuffix(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
- {
- Debug.Assert(suffix.Length != 0);
- Debug.Assert(source.Length != 0);
- Debug.Assert((options & ValidIndexMaskOffFlags) == 0);
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
-
- return EndsWith(source, suffix, options);
- }
-
- public virtual bool IsSuffix(string source, string suffix)
- {
- return IsSuffix(source, suffix, 0);
- }
-
- /// <summary>
- /// Returns the first index where value is found in string. The
- /// search starts from startIndex and ends at endIndex. Returns -1 if
- /// the specified value is not found. If value equals string.Empty,
- /// startIndex is returned. Throws IndexOutOfRange if startIndex or
- /// endIndex is less than zero or greater than the length of string.
- /// Throws ArgumentException if value is null.
- /// </summary>
- public virtual int IndexOf(string source, char value)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return IndexOf(source, value, 0, source.Length, CompareOptions.None);
- }
-
- public virtual int IndexOf(string source, string value)
- {
- if (source == null)
- throw new ArgumentNullException(nameof(source));
-
- return IndexOf(source, value, 0, source.Length, CompareOptions.None);
- }
-
- public virtual int IndexOf(string source, char value, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return IndexOf(source, value, 0, source.Length, options);
- }
-
- public virtual int IndexOf(string source, string value, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return IndexOf(source, value, 0, source.Length, options);
- }
-
- public virtual int IndexOf(string source, char value, int startIndex)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None);
- }
-
- public virtual int IndexOf(string source, string value, int startIndex)
- {
- if (source == null)
- throw new ArgumentNullException(nameof(source));
-
- return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None);
- }
-
- public virtual int IndexOf(string source, char value, int startIndex, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return IndexOf(source, value, startIndex, source.Length - startIndex, options);
- }
-
- public virtual int IndexOf(string source, string value, int startIndex, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return IndexOf(source, value, startIndex, source.Length - startIndex, options);
- }
-
- public virtual int IndexOf(string source, char value, int startIndex, int count)
- {
- return IndexOf(source, value, startIndex, count, CompareOptions.None);
- }
-
- public virtual int IndexOf(string source, string value, int startIndex, int count)
- {
- return IndexOf(source, value, startIndex, count, CompareOptions.None);
- }
-
- public virtual unsafe int IndexOf(string source, char value, int startIndex, int count, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (startIndex < 0 || startIndex > source.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- }
- if (count < 0 || startIndex > source.Length - count)
- {
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- }
-
- if (source.Length == 0)
- {
- return -1;
- }
-
- // Validate CompareOptions
- // Ordinal can't be selected with other flags
- if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal && options != CompareOptions.OrdinalIgnoreCase))
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- return IndexOf(source, char.ToString(value), startIndex, count, options, null);
- }
-
- public virtual unsafe int IndexOf(string source, string value, int startIndex, int count, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (startIndex > source.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- }
-
- // In Everett we used to return -1 for empty string even if startIndex is negative number so we keeping same behavior here.
- // We return 0 if both source and value are empty strings for Everett compatibility too.
- if (source.Length == 0)
- {
- if (value.Length == 0)
- {
- return 0;
- }
- return -1;
- }
-
- if (startIndex < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- }
-
- if (count < 0 || startIndex > source.Length - count)
- {
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- }
-
- // Validate CompareOptions
- // Ordinal can't be selected with other flags
- if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal && options != CompareOptions.OrdinalIgnoreCase))
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- return IndexOf(source, value, startIndex, count, options, null);
- }
-
- internal int IndexOfOrdinalIgnoreCase(ReadOnlySpan<char> source, ReadOnlySpan<char> value)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!value.IsEmpty);
-
- return IndexOfOrdinalCore(source, value, ignoreCase: true, fromBeginning: true);
- }
-
- internal int LastIndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!value.IsEmpty);
- return IndexOfOrdinalCore(source, value, ignoreCase, fromBeginning: false);
- }
-
- internal unsafe int IndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!value.IsEmpty);
- return IndexOfCore(source, value, options, null, fromBeginning: true);
- }
-
- internal unsafe int LastIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(!source.IsEmpty);
- Debug.Assert(!value.IsEmpty);
- return IndexOfCore(source, value, options, null, fromBeginning: false);
- }
-
- /// <summary>
- /// The following IndexOf overload is mainly used by String.Replace. This overload assumes the parameters are already validated
- /// and the caller is passing a valid matchLengthPtr pointer.
- /// </summary>
- internal unsafe int IndexOf(string source, string value, int startIndex, int count, CompareOptions options, int* matchLengthPtr, bool fromBeginning = true)
- {
- Debug.Assert(source != null);
- Debug.Assert(value != null);
- Debug.Assert(startIndex >= 0);
-
- if (matchLengthPtr != null)
- {
- *matchLengthPtr = 0;
- }
-
- if (value.Length == 0)
- {
- return startIndex;
- }
-
- if (startIndex >= source.Length)
- {
- return -1;
- }
-
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- int res;
- if (fromBeginning)
- {
- res = IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
- }
- else
- {
- res = LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
- }
-
- if (res >= 0 && matchLengthPtr != null)
- {
- *matchLengthPtr = value.Length;
- }
- return res;
- }
-
- if (GlobalizationMode.Invariant)
- {
- bool ignoreCase = (options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0;
- int res;
-
- if (fromBeginning)
- {
- res = IndexOfOrdinal(source, value, startIndex, count, ignoreCase);
- }
- else
- {
- res = LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase);
- }
-
- if (res >= 0 && matchLengthPtr != null)
- {
- *matchLengthPtr = value.Length;
- }
- return res;
- }
-
- if (options == CompareOptions.Ordinal)
- {
- int retValue;
-
- if (fromBeginning)
- {
- retValue = SpanHelpers.IndexOf(
- ref Unsafe.Add(ref source.GetRawStringData(), startIndex),
- count,
- ref value.GetRawStringData(),
- value.Length);
- }
- else
- {
- retValue = SpanHelpers.LastIndexOf(
- ref Unsafe.Add(ref source.GetRawStringData(), startIndex),
- count,
- ref value.GetRawStringData(),
- value.Length);
- }
-
- if (retValue >= 0)
- {
- retValue += startIndex;
- if (matchLengthPtr != null)
- {
- *matchLengthPtr = value.Length;
- }
- }
-
- return retValue;
- }
- else
- {
- if (fromBeginning)
- {
- // Call the string-based overload, as it special-cases IsFastSort as a perf optimization.
- return IndexOfCore(source, value, startIndex, count, options, matchLengthPtr);
- }
- else
- {
- return IndexOfCore(source.AsSpan(startIndex, count), value, options, matchLengthPtr, fromBeginning: false);
- }
- }
- }
-
- internal static int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- if (!ignoreCase)
- {
- int result = SpanHelpers.IndexOf(
- ref Unsafe.Add(ref source.GetRawStringData(), startIndex),
- count,
- ref value.GetRawStringData(),
- value.Length);
-
- return (result >= 0 ? startIndex : 0) + result;
- }
-
- if (GlobalizationMode.Invariant)
- {
- return InvariantIndexOf(source, value, startIndex, count, ignoreCase);
- }
-
- return IndexOfOrdinalCore(source, value, startIndex, count, ignoreCase);
- }
-
- /// <summary>
- /// Returns the last index where value is found in string. The
- /// search starts from startIndex and ends at endIndex. Returns -1 if
- /// the specified value is not found. If value equals string.Empty,
- /// endIndex is returned. Throws IndexOutOfRange if startIndex or
- /// endIndex is less than zero or greater than the length of string.
- /// Throws ArgumentException if value is null.
- /// </summary>
- public virtual int LastIndexOf(string source, char value)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- // Can't start at negative index, so make sure we check for the length == 0 case.
- return LastIndexOf(source, value, source.Length - 1, source.Length, CompareOptions.None);
- }
-
- public virtual int LastIndexOf(string source, string value)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- // Can't start at negative index, so make sure we check for the length == 0 case.
- return LastIndexOf(source, value, source.Length - 1,
- source.Length, CompareOptions.None);
- }
-
- public virtual int LastIndexOf(string source, char value, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- // Can't start at negative index, so make sure we check for the length == 0 case.
- return LastIndexOf(source, value, source.Length - 1, source.Length, options);
- }
-
- public virtual int LastIndexOf(string source, string value, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- // Can't start at negative index, so make sure we check for the length == 0 case.
- return LastIndexOf(source, value, source.Length - 1, source.Length, options);
- }
-
- public virtual int LastIndexOf(string source, char value, int startIndex)
- {
- return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None);
- }
-
- public virtual int LastIndexOf(string source, string value, int startIndex)
- {
- return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None);
- }
-
- public virtual int LastIndexOf(string source, char value, int startIndex, CompareOptions options)
- {
- return LastIndexOf(source, value, startIndex, startIndex + 1, options);
- }
-
- public virtual int LastIndexOf(string source, string value, int startIndex, CompareOptions options)
- {
- return LastIndexOf(source, value, startIndex, startIndex + 1, options);
- }
-
- public virtual int LastIndexOf(string source, char value, int startIndex, int count)
- {
- return LastIndexOf(source, value, startIndex, count, CompareOptions.None);
- }
-
- public virtual int LastIndexOf(string source, string value, int startIndex, int count)
- {
- return LastIndexOf(source, value, startIndex, count, CompareOptions.None);
- }
-
- public virtual int LastIndexOf(string source, char value, int startIndex, int count, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- // Validate CompareOptions
- // Ordinal can't be selected with other flags
- if ((options & ValidIndexMaskOffFlags) != 0 &&
- (options != CompareOptions.Ordinal) &&
- (options != CompareOptions.OrdinalIgnoreCase))
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- // Special case for 0 length input strings
- if (source.Length == 0 && (startIndex == -1 || startIndex == 0))
- {
- return -1;
- }
-
- // Make sure we're not out of range
- if (startIndex < 0 || startIndex > source.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- }
-
- // Make sure that we allow startIndex == source.Length
- if (startIndex == source.Length)
- {
- startIndex--;
- if (count > 0)
- {
- count--;
- }
- }
-
- // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
- if (count < 0 || startIndex - count + 1 < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- }
-
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return source.LastIndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase);
- }
-
- if (GlobalizationMode.Invariant)
- {
- return InvariantLastIndexOf(source, char.ToString(value), startIndex, count, (options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0);
- }
-
- return LastIndexOfCore(source, value.ToString(), startIndex, count, options);
- }
-
- public virtual int LastIndexOf(string source, string value, int startIndex, int count, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- // Validate CompareOptions
- // Ordinal can't be selected with other flags
- if ((options & ValidIndexMaskOffFlags) != 0 &&
- (options != CompareOptions.Ordinal) &&
- (options != CompareOptions.OrdinalIgnoreCase))
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
-
- // Special case for 0 length input strings
- if (source.Length == 0 && (startIndex == -1 || startIndex == 0))
- {
- return (value.Length == 0) ? 0 : -1;
- }
-
- // Make sure we're not out of range
- if (startIndex < 0 || startIndex > source.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- }
-
- // Make sure that we allow startIndex == source.Length
- if (startIndex == source.Length)
- {
- startIndex--;
- if (count > 0)
- {
- count--;
- }
-
- // If we are looking for nothing, just return 0
- if (value.Length == 0 && count >= 0 && startIndex - count + 1 >= 0)
- {
- return startIndex;
- }
- }
-
- // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
- if (count < 0 || startIndex - count + 1 < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- }
-
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
- }
-
- if (GlobalizationMode.Invariant)
- return InvariantLastIndexOf(source, value, startIndex, count, (options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0);
-
- return LastIndexOfCore(source, value, startIndex, count, options);
- }
-
- internal static int LastIndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
- {
- if (GlobalizationMode.Invariant)
- {
- return InvariantLastIndexOf(source, value, startIndex, count, ignoreCase);
- }
-
- return LastIndexOfOrdinalCore(source, value, startIndex, count, ignoreCase);
- }
-
- /// <summary>
- /// Gets the SortKey for the given string with the given options.
- /// </summary>
- public virtual SortKey GetSortKey(string source, CompareOptions options)
- {
- if (GlobalizationMode.Invariant)
- {
- return InvariantCreateSortKey(source, options);
- }
-
- return CreateSortKey(source, options);
- }
-
- public virtual SortKey GetSortKey(string source)
- {
- if (GlobalizationMode.Invariant)
- {
- return InvariantCreateSortKey(source, CompareOptions.None);
- }
-
- return CreateSortKey(source, CompareOptions.None);
- }
-
- public override bool Equals(object? value)
- {
- return value is CompareInfo otherCompareInfo
- && Name == otherCompareInfo.Name;
- }
-
- public override int GetHashCode() => Name.GetHashCode();
-
- /// <summary>
- /// This internal method allows a method that allows the equivalent of creating a Sortkey for a
- /// string from CompareInfo, and generate a hashcode value from it. It is not very convenient
- /// to use this method as is and it creates an unnecessary Sortkey object that will be GC'ed.
- ///
- /// The hash code is guaranteed to be the same for string A and B where A.Equals(B) is true and both
- /// the CompareInfo and the CompareOptions are the same. If two different CompareInfo objects
- /// treat the string the same way, this implementation will treat them differently (the same way that
- /// Sortkey does at the moment).
- ///
- /// This method will never be made public itself, but public consumers of it could be created, e.g.:
- ///
- /// string.GetHashCode(CultureInfo)
- /// string.GetHashCode(CompareInfo)
- /// string.GetHashCode(CultureInfo, CompareOptions)
- /// string.GetHashCode(CompareInfo, CompareOptions)
- /// etc.
- ///
- /// (the methods above that take a CultureInfo would use CultureInfo.CompareInfo)
- /// </summary>
- internal int GetHashCodeOfString(string source, CompareOptions options)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if ((options & ValidHashCodeOfStringMaskOffFlags) == 0)
- {
- // No unsupported flags are set - continue on with the regular logic
- if (GlobalizationMode.Invariant)
- {
- return ((options & CompareOptions.IgnoreCase) != 0) ? source.GetHashCodeOrdinalIgnoreCase() : source.GetHashCode();
- }
-
- return GetHashCodeOfStringCore(source, options);
- }
- else if (options == CompareOptions.Ordinal)
- {
- // We allow Ordinal in isolation
- return source.GetHashCode();
- }
- else if (options == CompareOptions.OrdinalIgnoreCase)
- {
- // We allow OrdinalIgnoreCase in isolation
- return source.GetHashCodeOrdinalIgnoreCase();
- }
- else
- {
- // Unsupported combination of flags specified
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
- }
-
- public virtual int GetHashCode(string source, CompareOptions options)
- {
- // virtual method delegates to non-virtual method
- return GetHashCodeOfString(source, options);
- }
-
- public int GetHashCode(ReadOnlySpan<char> source, CompareOptions options)
- {
- if ((options & ValidHashCodeOfStringMaskOffFlags) == 0)
- {
- // No unsupported flags are set - continue on with the regular logic
- if (GlobalizationMode.Invariant)
- {
- return ((options & CompareOptions.IgnoreCase) != 0) ? string.GetHashCodeOrdinalIgnoreCase(source) : string.GetHashCode(source);
- }
-
- return GetHashCodeOfStringCore(source, options);
- }
- else if (options == CompareOptions.Ordinal)
- {
- // We allow Ordinal in isolation
- return string.GetHashCode(source);
- }
- else if (options == CompareOptions.OrdinalIgnoreCase)
- {
- // We allow OrdinalIgnoreCase in isolation
- return string.GetHashCodeOrdinalIgnoreCase(source);
- }
- else
- {
- // Unsupported combination of flags specified
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
- }
-
- public override string ToString() => "CompareInfo - " + Name;
-
- public SortVersion Version
- {
- get
- {
- if (m_SortVersion == null)
- {
- if (GlobalizationMode.Invariant)
- {
- m_SortVersion = new SortVersion(0, CultureInfo.LOCALE_INVARIANT, new Guid(0, 0, 0, 0, 0, 0, 0,
- (byte)(CultureInfo.LOCALE_INVARIANT >> 24),
- (byte)((CultureInfo.LOCALE_INVARIANT & 0x00FF0000) >> 16),
- (byte)((CultureInfo.LOCALE_INVARIANT & 0x0000FF00) >> 8),
- (byte)(CultureInfo.LOCALE_INVARIANT & 0xFF)));
- }
- else
- {
- m_SortVersion = GetSortVersion();
- }
- }
-
- return m_SortVersion;
- }
- }
-
- public int LCID => CultureInfo.GetCultureInfo(Name).LCID;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareOptions.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CompareOptions.cs
deleted file mode 100644
index 366ece403c0..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CompareOptions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- [Flags]
- public enum CompareOptions
- {
- None = 0x00000000,
- IgnoreCase = 0x00000001,
- IgnoreNonSpace = 0x00000002,
- IgnoreSymbols = 0x00000004,
- IgnoreKanaType = 0x00000008,
- IgnoreWidth = 0x00000010,
- OrdinalIgnoreCase = 0x10000000, // This flag can not be used with other flags.
- StringSort = 0x20000000,
- Ordinal = 0x40000000, // This flag can not be used with other flags.
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
deleted file mode 100644
index cbd42e62fd6..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
+++ /dev/null
@@ -1,421 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Text;
-
-namespace System.Globalization
-{
- internal partial class CultureData
- {
- // ICU constants
- private const int ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY = 100; // max size of keyword or value
- private const int ICU_ULOC_FULLNAME_CAPACITY = 157; // max size of locale name
- private const string ICU_COLLATION_KEYWORD = "@collation=";
-
- /// <summary>
- /// This method uses the sRealName field (which is initialized by the constructor before this is called) to
- /// initialize the rest of the state of CultureData based on the underlying OS globalization library.
- /// </summary>
- private unsafe bool InitCultureData()
- {
- Debug.Assert(_sRealName != null);
-
- Debug.Assert(!GlobalizationMode.Invariant);
-
- string realNameBuffer = _sRealName;
-
- // Basic validation
- if (realNameBuffer.Contains('@'))
- {
- return false; // don't allow ICU variants to come in directly
- }
-
- // Replace _ (alternate sort) with @collation= for ICU
- ReadOnlySpan<char> alternateSortName = default;
- int index = realNameBuffer.IndexOf('_');
- if (index > 0)
- {
- if (index >= (realNameBuffer.Length - 1) // must have characters after _
- || realNameBuffer.IndexOf('_', index + 1) >= 0) // only one _ allowed
- {
- return false; // fail
- }
- alternateSortName = realNameBuffer.AsSpan(index + 1);
- realNameBuffer = string.Concat(realNameBuffer.AsSpan(0, index), ICU_COLLATION_KEYWORD, alternateSortName);
- }
-
- // Get the locale name from ICU
- if (!GetLocaleName(realNameBuffer, out _sWindowsName))
- {
- return false; // fail
- }
-
- // Replace the ICU collation keyword with an _
- Debug.Assert(_sWindowsName != null);
- index = _sWindowsName.IndexOf(ICU_COLLATION_KEYWORD, StringComparison.Ordinal);
- if (index >= 0)
- {
- _sName = string.Concat(_sWindowsName.AsSpan(0, index), "_", alternateSortName);
- }
- else
- {
- _sName = _sWindowsName;
- }
- _sRealName = _sName;
-
- _iLanguage = LCID;
- if (_iLanguage == 0)
- {
- _iLanguage = CultureInfo.LOCALE_CUSTOM_UNSPECIFIED;
- }
-
- _bNeutral = TwoLetterISOCountryName.Length == 0;
-
- _sSpecificCulture = _bNeutral ? LocaleData.GetSpecificCultureName(_sRealName) : _sRealName;
-
- // Remove the sort from sName unless custom culture
- if (index > 0 && !_bNeutral && !IsCustomCultureId(_iLanguage))
- {
- _sName = _sWindowsName.Substring(0, index);
- }
- return true;
- }
-
- internal static unsafe bool GetLocaleName(string localeName, out string? windowsName)
- {
- // Get the locale name from ICU
- char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY];
- if (!Interop.Globalization.GetLocaleName(localeName, buffer, ICU_ULOC_FULLNAME_CAPACITY))
- {
- windowsName = null;
- return false; // fail
- }
-
- // Success - use the locale name returned which may be different than realNameBuffer (casing)
- windowsName = new string(buffer); // the name passed to subsequent ICU calls
- return true;
- }
-
- internal static unsafe bool GetDefaultLocaleName(out string? windowsName)
- {
- // Get the default (system) locale name from ICU
- char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY];
- if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY))
- {
- windowsName = null;
- return false; // fail
- }
-
- // Success - use the locale name returned which may be different than realNameBuffer (casing)
- windowsName = new string(buffer); // the name passed to subsequent ICU calls
- return true;
- }
-
- private string GetLocaleInfo(LocaleStringData type)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo] Expected _sWindowsName to be populated already");
- return GetLocaleInfo(_sWindowsName, type);
- }
-
- // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the
- // "windows" name, which can be specific for downlevel (< windows 7) os's.
- private unsafe string GetLocaleInfo(string localeName, LocaleStringData type)
- {
- Debug.Assert(localeName != null, "[CultureData.GetLocaleInfo] Expected localeName to be not be null");
-
- switch (type)
- {
- case LocaleStringData.NegativeInfinitySymbol:
- // not an equivalent in ICU; prefix the PositiveInfinitySymbol with NegativeSign
- return GetLocaleInfo(localeName, LocaleStringData.NegativeSign) +
- GetLocaleInfo(localeName, LocaleStringData.PositiveInfinitySymbol);
- }
-
- char* buffer = stackalloc char[ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY];
- bool result = Interop.Globalization.GetLocaleInfoString(localeName, (uint)type, buffer, ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY);
- if (!result)
- {
- // Failed, just use empty string
- Debug.Fail("[CultureData.GetLocaleInfo(LocaleStringData)] Failed");
- return string.Empty;
- }
-
- return new string(buffer);
- }
-
- private int GetLocaleInfo(LocaleNumberData type)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleNumberData)] Expected _sWindowsName to be populated already");
-
- switch (type)
- {
- case LocaleNumberData.CalendarType:
- // returning 0 will cause the first supported calendar to be returned, which is the preferred calendar
- return 0;
- }
-
-
- int value = 0;
- bool result = Interop.Globalization.GetLocaleInfoInt(_sWindowsName, (uint)type, ref value);
- if (!result)
- {
- // Failed, just use 0
- Debug.Fail("[CultureData.GetLocaleInfo(LocaleNumberData)] failed");
- }
-
- return value;
- }
-
- private int[] GetLocaleInfo(LocaleGroupingData type)
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleGroupingData)] Expected _sWindowsName to be populated already");
-
- int primaryGroupingSize = 0;
- int secondaryGroupingSize = 0;
- bool result = Interop.Globalization.GetLocaleInfoGroupingSizes(_sWindowsName, (uint)type, ref primaryGroupingSize, ref secondaryGroupingSize);
- if (!result)
- {
- Debug.Fail("[CultureData.GetLocaleInfo(LocaleGroupingData type)] failed");
- }
-
- if (secondaryGroupingSize == 0)
- {
- return new int[] { primaryGroupingSize };
- }
-
- return new int[] { primaryGroupingSize, secondaryGroupingSize };
- }
-
- private string GetTimeFormatString() => GetTimeFormatString(shortFormat: false);
-
- private unsafe string GetTimeFormatString(bool shortFormat)
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.GetTimeFormatString(bool shortFormat)] Expected _sWindowsName to be populated already");
-
- char* buffer = stackalloc char[ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY];
-
- bool result = Interop.Globalization.GetLocaleTimeFormat(_sWindowsName, shortFormat, buffer, ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY);
- if (!result)
- {
- // Failed, just use empty string
- Debug.Fail("[CultureData.GetTimeFormatString(bool shortFormat)] Failed");
- return string.Empty;
- }
-
- var span = new ReadOnlySpan<char>(buffer, ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY);
- return ConvertIcuTimeFormatString(span.Slice(0, span.IndexOf('\0')));
- }
-
- private int GetFirstDayOfWeek() => GetLocaleInfo(LocaleNumberData.FirstDayOfWeek);
-
- private string[] GetTimeFormats()
- {
- string format = GetTimeFormatString(false);
- return new string[] { format };
- }
-
- private string[] GetShortTimeFormats()
- {
- string format = GetTimeFormatString(true);
- return new string[] { format };
- }
-
- private static CultureData? GetCultureDataFromRegionName(string? regionName)
- {
- // no support to lookup by region name, other than the hard-coded list in CultureData
- return null;
- }
-
- private static string GetLanguageDisplayName(string cultureName)
- {
- return new CultureInfo(cultureName)._cultureData.GetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName);
- }
-
- private static string? GetRegionDisplayName()
- {
- // use the fallback which is to return NativeName
- return null;
- }
-
- private static string ConvertIcuTimeFormatString(ReadOnlySpan<char> icuFormatString)
- {
- Debug.Assert(icuFormatString.Length < ICU_ULOC_FULLNAME_CAPACITY);
- Span<char> result = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY];
-
- bool amPmAdded = false;
- int resultPos = 0;
-
- for (int i = 0; i < icuFormatString.Length; i++)
- {
- switch (icuFormatString[i])
- {
- case '\'':
- result[resultPos++] = icuFormatString[i++];
- while (i < icuFormatString.Length)
- {
- char current = icuFormatString[i++];
- result[resultPos++] = current;
- if (current == '\'')
- {
- break;
- }
- }
- break;
-
- case ':':
- case '.':
- case 'H':
- case 'h':
- case 'm':
- case 's':
- result[resultPos++] = icuFormatString[i];
- break;
-
- case ' ':
- case '\u00A0':
- // Convert nonbreaking spaces into regular spaces
- result[resultPos++] = ' ';
- break;
-
- case 'a': // AM/PM
- if (!amPmAdded)
- {
- amPmAdded = true;
- result[resultPos++] = 't';
- result[resultPos++] = 't';
- }
- break;
-
- }
- }
-
- return result.Slice(0, resultPos).ToString();
- }
-
- private static string? LCIDToLocaleName(int culture)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- return LocaleData.LCIDToLocaleName(culture);
- }
-
- private static int LocaleNameToLCID(string cultureName)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- int lcid = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.Lcid);
- return lcid == -1 ? CultureInfo.LOCALE_CUSTOM_UNSPECIFIED : lcid;
- }
-
- private static int GetAnsiCodePage(string cultureName)
- {
- int ansiCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.AnsiCodePage);
- return ansiCodePage == -1 ? CultureData.Invariant.ANSICodePage : ansiCodePage;
- }
-
- private static int GetOemCodePage(string cultureName)
- {
- int oemCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.OemCodePage);
- return oemCodePage == -1 ? CultureData.Invariant.OEMCodePage : oemCodePage;
- }
-
- private static int GetMacCodePage(string cultureName)
- {
- int macCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.MacCodePage);
- return macCodePage == -1 ? CultureData.Invariant.MacCodePage : macCodePage;
- }
-
- private static int GetEbcdicCodePage(string cultureName)
- {
- int ebcdicCodePage = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.EbcdicCodePage);
- return ebcdicCodePage == -1 ? CultureData.Invariant.EBCDICCodePage : ebcdicCodePage;
- }
-
- private static int GetGeoId(string cultureName)
- {
- int geoId = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.GeoId);
- return geoId == -1 ? CultureData.Invariant.GeoId : geoId;
- }
-
- private static int GetDigitSubstitution(string cultureName)
- {
- int digitSubstitution = LocaleData.GetLocaleDataNumericPart(cultureName, LocaleDataParts.DigitSubstitution);
- return digitSubstitution == -1 ? (int) DigitShapes.None : digitSubstitution;
- }
-
- private static string GetThreeLetterWindowsLanguageName(string cultureName)
- {
- return LocaleData.GetThreeLetterWindowsLanguageName(cultureName) ?? "ZZZ" /* default lang name */;
- }
-
- private static CultureInfo[] EnumCultures(CultureTypes types)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- if ((types & (CultureTypes.NeutralCultures | CultureTypes.SpecificCultures)) == 0)
- {
- return Array.Empty<CultureInfo>();
- }
-
- int bufferLength = Interop.Globalization.GetLocales(null, 0);
- if (bufferLength <= 0)
- {
- return Array.Empty<CultureInfo>();
- }
-
- char [] chars = new char[bufferLength];
-
- bufferLength = Interop.Globalization.GetLocales(chars, bufferLength);
- if (bufferLength <= 0)
- {
- return Array.Empty<CultureInfo>();
- }
-
- bool enumNeutrals = (types & CultureTypes.NeutralCultures) != 0;
- bool enumSpecificss = (types & CultureTypes.SpecificCultures) != 0;
-
- List<CultureInfo> list = new List<CultureInfo>();
- if (enumNeutrals)
- {
- list.Add(CultureInfo.InvariantCulture);
- }
-
- int index = 0;
- while (index < bufferLength)
- {
- int length = (int) chars[index++];
- if (index + length <= bufferLength)
- {
- CultureInfo ci = CultureInfo.GetCultureInfo(new string(chars, index, length));
- if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecificss && !ci.IsNeutralCulture))
- {
- list.Add(ci);
- }
- }
-
- index += length;
- }
-
- return list.ToArray();
- }
-
- private static string GetConsoleFallbackName(string cultureName)
- {
- return LocaleData.GetConsoleUICulture(cultureName);
- }
-
- internal bool IsWin32Installed => false;
-
- internal bool IsReplacementCulture => false;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
deleted file mode 100644
index b8ae4083724..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
+++ /dev/null
@@ -1,718 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using Internal.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- internal partial class CultureData
- {
- /// <summary>
- /// Check with the OS to see if this is a valid culture.
- /// If so we populate a limited number of fields. If its not valid we return false.
- ///
- /// The fields we populate:
- ///
- /// sWindowsName -- The name that windows thinks this culture is, ie:
- /// en-US if you pass in en-US
- /// de-DE_phoneb if you pass in de-DE_phoneb
- /// fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine)
- /// fj if you pass in fj (neutral, post-Windows 7 machine)
- ///
- /// sRealName -- The name you used to construct the culture, in pretty form
- /// en-US if you pass in EN-us
- /// en if you pass in en
- /// de-DE_phoneb if you pass in de-DE_phoneb
- ///
- /// sSpecificCulture -- The specific culture for this culture
- /// en-US for en-US
- /// en-US for en
- /// de-DE_phoneb for alt sort
- /// fj-FJ for fj (neutral)
- ///
- /// sName -- The IETF name of this culture (ie: no sort info, could be neutral)
- /// en-US if you pass in en-US
- /// en if you pass in en
- /// de-DE if you pass in de-DE_phoneb
- ///
- /// bNeutral -- TRUE if it is a neutral locale
- ///
- /// For a neutral we just populate the neutral name, but we leave the windows name pointing to the
- /// windows locale that's going to provide data for us.
- /// </summary>
- private unsafe bool InitCultureData()
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- int result;
- string realNameBuffer = _sRealName;
- char* pBuffer = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH];
-
- result = GetLocaleInfoEx(realNameBuffer, Interop.Kernel32.LOCALE_SNAME, pBuffer, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH);
-
- // Did it fail?
- if (result == 0)
- {
- return false;
- }
-
- // It worked, note that the name is the locale name, so use that (even for neutrals)
- // We need to clean up our "real" name, which should look like the windows name right now
- // so overwrite the input with the cleaned up name
- _sRealName = new string(pBuffer, 0, result - 1);
- realNameBuffer = _sRealName;
-
- // Check for neutrality, don't expect to fail
- // (buffer has our name in it, so we don't have to do the gc. stuff)
-
- result = GetLocaleInfoEx(realNameBuffer, Interop.Kernel32.LOCALE_INEUTRAL | Interop.Kernel32.LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char));
- if (result == 0)
- {
- return false;
- }
-
- // Remember our neutrality
- _bNeutral = *((uint*)pBuffer) != 0;
-
- // Note: Parents will be set dynamically
-
- // Start by assuming the windows name will be the same as the specific name since windows knows
- // about specifics on all versions. Only for downlevel Neutral locales does this have to change.
- _sWindowsName = realNameBuffer;
-
- // Neutrals and non-neutrals are slightly different
- if (_bNeutral)
- {
- // Neutral Locale
-
- // IETF name looks like neutral name
- _sName = realNameBuffer;
-
- // Specific locale name is whatever ResolveLocaleName (win7+) returns.
- // (Buffer has our name in it, and we can recycle that because windows resolves it before writing to the buffer)
- result = Interop.Kernel32.ResolveLocaleName(realNameBuffer, pBuffer, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH);
-
- // 0 is failure, 1 is invariant (""), which we expect
- if (result < 1)
- {
- return false;
- }
- // We found a locale name, so use it.
- // In vista this should look like a sort name (de-DE_phoneb) or a specific culture (en-US) and be in the "pretty" form
- _sSpecificCulture = new string(pBuffer, 0, result - 1);
- }
- else
- {
- // Specific Locale
-
- // Specific culture's the same as the locale name since we know its not neutral
- // On mac we'll use this as well, even for neutrals. There's no obvious specific
- // culture to use and this isn't exposed, but behaviorally this is correct on mac.
- // Note that specifics include the sort name (de-DE_phoneb)
- _sSpecificCulture = realNameBuffer;
-
- _sName = realNameBuffer;
-
- // We need the IETF name (sname)
- // If we aren't an alt sort locale then this is the same as the windows name.
- // If we are an alt sort locale then this is the same as the part before the _ in the windows name
- // This is for like de-DE_phoneb and es-ES_tradnl that hsouldn't have the _ part
-
- result = GetLocaleInfoEx(realNameBuffer, Interop.Kernel32.LOCALE_ILANGUAGE | Interop.Kernel32.LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char));
- if (result == 0)
- {
- return false;
- }
-
- _iLanguage = *((int*)pBuffer);
-
- if (!IsCustomCultureId(_iLanguage))
- {
- // not custom locale
- int index = realNameBuffer.IndexOf('_');
- if (index > 0 && index < realNameBuffer.Length)
- {
- _sName = realNameBuffer.Substring(0, index);
- }
- }
- }
-
- // It succeeded.
- return true;
- }
-
- // Wrappers around the GetLocaleInfoEx APIs which handle marshalling the returned
- // data as either and Int or string.
- internal static unsafe string? GetLocaleInfoEx(string localeName, uint field)
- {
- // REVIEW: Determine the maximum size for the buffer
- const int BUFFER_SIZE = 530;
-
- char* pBuffer = stackalloc char[BUFFER_SIZE];
- int resultCode = GetLocaleInfoEx(localeName, field, pBuffer, BUFFER_SIZE);
- if (resultCode > 0)
- {
- return new string(pBuffer);
- }
-
- return null;
- }
-
- internal static unsafe int GetLocaleInfoExInt(string localeName, uint field)
- {
- field |= Interop.Kernel32.LOCALE_RETURN_NUMBER;
- int value = 0;
- GetLocaleInfoEx(localeName, field, (char*)&value, sizeof(int));
- return value;
- }
-
- internal static unsafe int GetLocaleInfoEx(string lpLocaleName, uint lcType, char* lpLCData, int cchData)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- return Interop.Kernel32.GetLocaleInfoEx(lpLocaleName, lcType, lpLCData, cchData);
- }
-
- private string GetLocaleInfo(LocaleStringData type)
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected _sWindowsName to be populated by already");
- return GetLocaleInfo(_sWindowsName, type);
- }
-
- // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the
- // "windows" name, which can be specific for downlevel (< windows 7) os's.
- private string GetLocaleInfo(string localeName, LocaleStringData type)
- {
- uint lctype = (uint)type;
-
- return GetLocaleInfoFromLCType(localeName, lctype, UseUserOverride);
- }
-
- private int GetLocaleInfo(LocaleNumberData type)
- {
- uint lctype = (uint)type;
-
- // Fix lctype if we don't want overrides
- if (!UseUserOverride)
- {
- lctype |= Interop.Kernel32.LOCALE_NOUSEROVERRIDE;
- }
-
- // Ask OS for data, note that we presume it returns success, so we have to know that
- // sWindowsName is valid before calling.
- Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already");
- return GetLocaleInfoExInt(_sWindowsName, lctype);
- }
-
- private int[] GetLocaleInfo(LocaleGroupingData type)
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already");
- return ConvertWin32GroupString(GetLocaleInfoFromLCType(_sWindowsName, (uint)type, UseUserOverride));
- }
-
- private string? GetTimeFormatString()
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already");
- return ReescapeWin32String(GetLocaleInfoFromLCType(_sWindowsName, Interop.Kernel32.LOCALE_STIMEFORMAT, UseUserOverride));
- }
-
- private int GetFirstDayOfWeek()
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already");
-
- int result = GetLocaleInfoExInt(_sWindowsName, Interop.Kernel32.LOCALE_IFIRSTDAYOFWEEK | (!UseUserOverride ? Interop.Kernel32.LOCALE_NOUSEROVERRIDE : 0));
-
- // Win32 and .NET disagree on the numbering for days of the week, so we have to convert.
- return ConvertFirstDayOfWeekMonToSun(result);
- }
-
- private string[]? GetTimeFormats()
- {
- // Note that this gets overrides for us all the time
- Debug.Assert(_sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected _sWindowsName to be populated by already");
- string[]? result = ReescapeWin32Strings(nativeEnumTimeFormats(_sWindowsName, 0, UseUserOverride));
-
- return result;
- }
-
- private string[]? GetShortTimeFormats()
- {
- // Note that this gets overrides for us all the time
- Debug.Assert(_sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected _sWindowsName to be populated by already");
- string[]? result = ReescapeWin32Strings(nativeEnumTimeFormats(_sWindowsName, Interop.Kernel32.TIME_NOSECONDS, UseUserOverride));
-
- return result;
- }
-
- // Enumerate all system cultures and then try to find out which culture has
- // region name match the requested region name
- private static CultureData? GetCultureDataFromRegionName(string regionName)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(regionName != null);
-
- EnumLocaleData context;
- context.cultureName = null;
- context.regionName = regionName;
-
- unsafe
- {
- Interop.Kernel32.EnumSystemLocalesEx(EnumSystemLocalesProc, Interop.Kernel32.LOCALE_SPECIFICDATA | Interop.Kernel32.LOCALE_SUPPLEMENTAL, Unsafe.AsPointer(ref context), IntPtr.Zero);
- }
-
- if (context.cultureName != null)
- {
- // we got a matched culture
- return GetCultureData(context.cultureName, true);
- }
-
- return null;
- }
-
- private string GetLanguageDisplayName(string cultureName)
- {
- // Usually the UI culture shouldn't be different than what we got from WinRT except
- // if DefaultThreadCurrentUICulture was set
- CultureInfo? ci;
-
- if (CultureInfo.DefaultThreadCurrentUICulture != null &&
- ((ci = CultureInfo.GetUserDefaultCulture()) != null) &&
- !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name))
- {
- return NativeName;
- }
- else
- {
- return GetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName);
- }
- }
-
- private string GetRegionDisplayName()
- {
- // If the current UI culture matching the OS UI language, we'll get the display name from the OS.
- // otherwise, we use the native name as we don't carry resources for the region display names anyway.
- if (CultureInfo.CurrentUICulture.Name.Equals(CultureInfo.UserDefaultUICulture.Name))
- {
- return GetLocaleInfo(LocaleStringData.LocalizedCountryName);
- }
-
- return NativeCountryName;
- }
-
- // PAL methods end here.
-
- private static string GetLocaleInfoFromLCType(string localeName, uint lctype, bool useUserOveride)
- {
- Debug.Assert(localeName != null, "[CultureData.GetLocaleInfoFromLCType] Expected localeName to be not be null");
-
- // Fix lctype if we don't want overrides
- if (!useUserOveride)
- {
- lctype |= Interop.Kernel32.LOCALE_NOUSEROVERRIDE;
- }
-
- // Ask OS for data
- // Failed? Just use empty string
- return GetLocaleInfoEx(localeName, lctype) ?? string.Empty;
- }
-
- /// <summary>
- /// Reescape a Win32 style quote string as a NLS+ style quoted string
- ///
- /// This is also the escaping style used by custom culture data files
- ///
- /// NLS+ uses \ to escape the next character, whether in a quoted string or
- /// not, so we always have to change \ to \\.
- ///
- /// NLS+ uses \' to escape a quote inside a quoted string so we have to change
- /// '' to \' (if inside a quoted string)
- ///
- /// We don't build the stringbuilder unless we find something to change
- /// </summary>
- [return: NotNullIfNotNull("str")]
- internal static string? ReescapeWin32String(string? str)
- {
- // If we don't have data, then don't try anything
- if (str == null)
- {
- return null;
- }
-
- StringBuilder? result = null;
-
- bool inQuote = false;
- for (int i = 0; i < str.Length; i++)
- {
- // Look for quote
- if (str[i] == '\'')
- {
- // Already in quote?
- if (inQuote)
- {
- // See another single quote. Is this '' of 'fred''s' or '''', or is it an ending quote?
- if (i + 1 < str.Length && str[i + 1] == '\'')
- {
- // Found another ', so we have ''. Need to add \' instead.
- // 1st make sure we have our stringbuilder
- result ??= new StringBuilder(str, 0, i, str.Length * 2);
-
- // Append a \' and keep going (so we don't turn off quote mode)
- result.Append("\\'");
- i++;
- continue;
- }
-
- // Turning off quote mode, fall through to add it
- inQuote = false;
- }
- else
- {
- // Found beginning quote, fall through to add it
- inQuote = true;
- }
- }
- // Is there a single \ character?
- else if (str[i] == '\\')
- {
- // Found a \, need to change it to \\
- // 1st make sure we have our stringbuilder
- result ??= new StringBuilder(str, 0, i, str.Length * 2);
-
- // Append our \\ to the string & continue
- result.Append("\\\\");
- continue;
- }
-
- // If we have a builder we need to add our character
- result?.Append(str[i]);
- }
-
- // Unchanged string? , just return input string
- if (result == null)
- return str;
-
- // String changed, need to use the builder
- return result.ToString();
- }
-
- [return: NotNullIfNotNull("array")]
- internal static string[]? ReescapeWin32Strings(string[]? array)
- {
- if (array != null)
- {
- for (int i = 0; i < array.Length; i++)
- {
- array[i] = ReescapeWin32String(array[i]);
- }
- }
-
- return array;
- }
-
- // If we get a group from windows, then its in 3;0 format with the 0 backwards
- // of how NLS+ uses it (ie: if the string has a 0, then the int[] shouldn't and vice versa)
- // EXCEPT in the case where the list only contains 0 in which NLS and NLS+ have the same meaning.
- private static int[] ConvertWin32GroupString(string win32Str)
- {
- // None of these cases make any sense
- if (string.IsNullOrEmpty(win32Str))
- {
- return new int[] { 3 };
- }
-
- if (win32Str[0] == '0')
- {
- return new int[] { 0 };
- }
-
- // Since its in n;n;n;n;n format, we can always get the length quickly
- int[] values;
- if (win32Str[^1] == '0')
- {
- // Trailing 0 gets dropped. 1;0 -> 1
- values = new int[win32Str.Length / 2];
- }
- else
- {
- // Need extra space for trailing zero 1 -> 1;0
- values = new int[(win32Str.Length / 2) + 2];
- values[^1] = 0;
- }
-
- int i;
- int j;
- for (i = 0, j = 0; i < win32Str.Length && j < values.Length; i += 2, j++)
- {
- // Note that this # shouldn't ever be zero, 'cause 0 is only at end
- // But we'll test because its registry that could be anything
- if (win32Str[i] < '1' || win32Str[i] > '9')
- return new int[] { 3 };
-
- values[j] = (int)(win32Str[i] - '0');
- }
-
- return values;
- }
-
- private static int ConvertFirstDayOfWeekMonToSun(int iTemp)
- {
- // Convert Mon-Sun to Sun-Sat format
- iTemp++;
- if (iTemp > 6)
- {
- // Wrap Sunday and convert invalid data to Sunday
- iTemp = 0;
- }
- return iTemp;
- }
-
- // Context for EnumCalendarInfoExEx callback.
- private struct EnumLocaleData
- {
- public string regionName;
- public string? cultureName;
- }
-
- // EnumSystemLocaleEx callback.
- // [NativeCallable(CallingConvention = CallingConvention.StdCall)]
- private static unsafe Interop.BOOL EnumSystemLocalesProc(char* lpLocaleString, uint flags, void* contextHandle)
- {
- ref EnumLocaleData context = ref Unsafe.As<byte, EnumLocaleData>(ref *(byte*)contextHandle);
- try
- {
- string cultureName = new string(lpLocaleString);
- string? regionName = GetLocaleInfoEx(cultureName, Interop.Kernel32.LOCALE_SISO3166CTRYNAME);
- if (regionName != null && regionName.Equals(context.regionName, StringComparison.OrdinalIgnoreCase))
- {
- context.cultureName = cultureName;
- return Interop.BOOL.FALSE; // we found a match, then stop the enumeration
- }
-
- return Interop.BOOL.TRUE;
- }
- catch (Exception)
- {
- return Interop.BOOL.FALSE;
- }
- }
-
- // EnumSystemLocaleEx callback.
- // [NativeCallable(CallingConvention = CallingConvention.StdCall)]
- private static unsafe Interop.BOOL EnumAllSystemLocalesProc(char* lpLocaleString, uint flags, void* contextHandle)
- {
- ref EnumData context = ref Unsafe.As<byte, EnumData>(ref *(byte*)contextHandle);
- try
- {
- context.strings.Add(new string(lpLocaleString));
- return Interop.BOOL.TRUE;
- }
- catch (Exception)
- {
- return Interop.BOOL.FALSE;
- }
- }
-
- // Context for EnumTimeFormatsEx callback.
- private struct EnumData
- {
- public List<string> strings;
- }
-
- // EnumTimeFormatsEx callback itself.
- // [NativeCallable(CallingConvention = CallingConvention.StdCall)]
- private static unsafe Interop.BOOL EnumTimeCallback(char* lpTimeFormatString, void* lParam)
- {
- ref EnumData context = ref Unsafe.As<byte, EnumData>(ref *(byte*)lParam);
- try
- {
- context.strings.Add(new string(lpTimeFormatString));
- return Interop.BOOL.TRUE;
- }
- catch (Exception)
- {
- return Interop.BOOL.FALSE;
- }
- }
-
- private static unsafe string[]? nativeEnumTimeFormats(string localeName, uint dwFlags, bool useUserOverride)
- {
- EnumData data = default;
- data.strings = new List<string>();
-
- // Now call the enumeration API. Work is done by our callback function
- Interop.Kernel32.EnumTimeFormatsEx(EnumTimeCallback, localeName, (uint)dwFlags, Unsafe.AsPointer(ref data));
-
- if (data.strings.Count > 0)
- {
- // Now we need to allocate our stringarray and populate it
- string[] results = data.strings.ToArray();
-
- if (!useUserOverride && data.strings.Count > 1)
- {
- // Since there is no "NoUserOverride" aware EnumTimeFormatsEx, we always get an override
- // The override is the first entry if it is overriden.
- // We can check if we have overrides by checking the GetLocaleInfo with no override
- // If we do have an override, we don't know if it is a user defined override or if the
- // user has just selected one of the predefined formats so we can't just remove it
- // but we can move it down.
- uint lcType = (dwFlags == Interop.Kernel32.TIME_NOSECONDS) ? Interop.Kernel32.LOCALE_SSHORTTIME : Interop.Kernel32.LOCALE_STIMEFORMAT;
- string timeFormatNoUserOverride = GetLocaleInfoFromLCType(localeName, lcType, useUserOverride);
- if (timeFormatNoUserOverride != "")
- {
- string firstTimeFormat = results[0];
- if (timeFormatNoUserOverride != firstTimeFormat)
- {
- results[0] = results[1];
- results[1] = firstTimeFormat;
- }
- }
- }
-
- return results;
- }
-
- return null;
- }
-
- private static int LocaleNameToLCID(string cultureName)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- return Interop.Kernel32.LocaleNameToLCID(cultureName, Interop.Kernel32.LOCALE_ALLOW_NEUTRAL_NAMES);
- }
-
- private static unsafe string? LCIDToLocaleName(int culture)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- char* pBuffer = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1]; // +1 for the null termination
- int length = Interop.Kernel32.LCIDToLocaleName(culture, pBuffer, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1, Interop.Kernel32.LOCALE_ALLOW_NEUTRAL_NAMES);
-
- if (length > 0)
- {
- return new string(pBuffer);
- }
-
- return null;
- }
-
- private int GetAnsiCodePage(string cultureName)
- {
- return GetLocaleInfo(LocaleNumberData.AnsiCodePage);
- }
-
- private int GetOemCodePage(string cultureName)
- {
- return GetLocaleInfo(LocaleNumberData.OemCodePage);
- }
-
- private int GetMacCodePage(string cultureName)
- {
- return GetLocaleInfo(LocaleNumberData.MacCodePage);
- }
-
- private int GetEbcdicCodePage(string cultureName)
- {
- return GetLocaleInfo(LocaleNumberData.EbcdicCodePage);
- }
-
- private int GetGeoId(string cultureName)
- {
- return GetLocaleInfo(LocaleNumberData.GeoId);
- }
-
- private int GetDigitSubstitution(string cultureName)
- {
- return GetLocaleInfo(LocaleNumberData.DigitSubstitution);
- }
-
- private string GetThreeLetterWindowsLanguageName(string cultureName)
- {
- return GetLocaleInfo(cultureName, LocaleStringData.AbbreviatedWindowsLanguageName);
- }
-
- private static CultureInfo[] EnumCultures(CultureTypes types)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- uint flags = 0;
-
-#pragma warning disable 618
- if ((types & (CultureTypes.FrameworkCultures | CultureTypes.InstalledWin32Cultures | CultureTypes.ReplacementCultures)) != 0)
- {
- flags |= Interop.Kernel32.LOCALE_NEUTRALDATA | Interop.Kernel32.LOCALE_SPECIFICDATA;
- }
-#pragma warning restore 618
-
- if ((types & CultureTypes.NeutralCultures) != 0)
- {
- flags |= Interop.Kernel32.LOCALE_NEUTRALDATA;
- }
-
- if ((types & CultureTypes.SpecificCultures) != 0)
- {
- flags |= Interop.Kernel32.LOCALE_SPECIFICDATA;
- }
-
- if ((types & CultureTypes.UserCustomCulture) != 0)
- {
- flags |= Interop.Kernel32.LOCALE_SUPPLEMENTAL;
- }
-
- if ((types & CultureTypes.ReplacementCultures) != 0)
- {
- flags |= Interop.Kernel32.LOCALE_SUPPLEMENTAL;
- }
-
- EnumData context = default;
- context.strings = new List<string>();
-
- unsafe
- {
- Interop.Kernel32.EnumSystemLocalesEx(EnumAllSystemLocalesProc, flags, Unsafe.AsPointer(ref context), IntPtr.Zero);
- }
-
- CultureInfo[] cultures = new CultureInfo[context.strings.Count];
- for (int i = 0; i < cultures.Length; i++)
- {
- cultures[i] = new CultureInfo(context.strings[i]);
- }
-
- return cultures;
- }
-
- private string GetConsoleFallbackName(string cultureName)
- {
- return GetLocaleInfo(cultureName, LocaleStringData.ConsoleFallbackName);
- }
-
- internal bool IsWin32Installed => true;
-
- internal bool IsReplacementCulture
- {
- get
- {
- EnumData context = default;
- context.strings = new List<string>();
-
- unsafe
- {
- Interop.Kernel32.EnumSystemLocalesEx(EnumAllSystemLocalesProc, Interop.Kernel32.LOCALE_REPLACEMENT, Unsafe.AsPointer(ref context), IntPtr.Zero);
- }
-
- for (int i = 0; i < context.strings.Count; i++)
- {
- if (string.Equals(context.strings[i], _sWindowsName, StringComparison.OrdinalIgnoreCase))
- return true;
- }
-
- return false;
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
deleted file mode 100644
index cad208b1974..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
+++ /dev/null
@@ -1,2252 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Text;
-
-namespace System.Globalization
-{
- /// <summary>
- /// List of culture data
- /// Note the we cache overrides.
- /// Note that localized names (resource names) aren't available from here.
- /// </summary>
- /// <remarks>
- /// Our names are a tad confusing.
- ///
- /// sWindowsName -- The name that windows thinks this culture is, ie:
- /// en-US if you pass in en-US
- /// de-DE_phoneb if you pass in de-DE_phoneb
- /// fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine)
- /// fj if you pass in fj (neutral, post-Windows 7 machine)
- ///
- /// sRealName -- The name you used to construct the culture, in pretty form
- /// en-US if you pass in EN-us
- /// en if you pass in en
- /// de-DE_phoneb if you pass in de-DE_phoneb
- ///
- /// sSpecificCulture -- The specific culture for this culture
- /// en-US for en-US
- /// en-US for en
- /// de-DE_phoneb for alt sort
- /// fj-FJ for fj (neutral)
- ///
- /// sName -- The IETF name of this culture (ie: no sort info, could be neutral)
- /// en-US if you pass in en-US
- /// en if you pass in en
- /// de-DE if you pass in de-DE_phoneb
- /// </remarks>
- internal partial class CultureData
- {
- private const int LocaleNameMaxLength = 85;
- private const int undef = -1;
-
- // Override flag
- private string _sRealName = null!; // Name you passed in (ie: en-US, en, or de-DE_phoneb). Initialized by helper called during initialization.
- private string? _sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
-
- // Identity
- private string? _sName; // locale name (ie: en-us, NO sort info, but could be neutral)
- private string? _sParent; // Parent name (which may be a custom locale/culture)
- private string? _sLocalizedDisplayName; // Localized pretty name for this locale
- private string? _sEnglishDisplayName; // English pretty name for this locale
- private string? _sNativeDisplayName; // Native pretty name for this locale
- private string? _sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort
-
- // Language
- private string? _sISO639Language; // ISO 639 Language Name
- private string? _sISO639Language2; // ISO 639 Language Name
- private string? _sLocalizedLanguage; // Localized name for this language
- private string? _sEnglishLanguage; // English name for this language
- private string? _sNativeLanguage; // Native name of this language
- private string? _sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU
- private string? _sConsoleFallbackName; // The culture name for the console fallback UI culture
- private int _iInputLanguageHandle = undef; // input language handle
-
- // Region
- private string? _sRegionName; // (RegionInfo)
- private string? _sLocalizedCountry; // localized country name
- private string? _sEnglishCountry; // english country name (RegionInfo)
- private string? _sNativeCountry; // native country name
- private string? _sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US
- private string? _sISO3166CountryName2; // 3 char ISO 3166 country name 2 2(RegionInfo) ex: USA (ISO)
- private int _iGeoId = undef; // GeoId
-
- // Numbers
- private string? _sPositiveSign; // (user can override) positive sign
- private string? _sNegativeSign; // (user can override) negative sign
- // (nfi populates these 5, don't have to be = undef)
- private int _iDigits; // (user can override) number of fractional digits
- private int _iNegativeNumber; // (user can override) negative number format
- private int[]? _waGrouping; // (user can override) grouping of digits
- private string? _sDecimalSeparator; // (user can override) decimal separator
- private string? _sThousandSeparator; // (user can override) thousands separator
- private string? _sNaN; // Not a Number
- private string? _sPositiveInfinity; // + Infinity
- private string? _sNegativeInfinity; // - Infinity
-
- // Percent
- private int _iNegativePercent = undef; // Negative Percent (0-3)
- private int _iPositivePercent = undef; // Positive Percent (0-11)
- private string? _sPercent; // Percent (%) symbol
- private string? _sPerMille; // PerMille symbol
-
- // Currency
- private string? _sCurrency; // (user can override) local monetary symbol
- private string? _sIntlMonetarySymbol; // international monetary symbol (RegionInfo)
- private string? _sEnglishCurrency; // English name for this currency
- private string? _sNativeCurrency; // Native name for this currency
- // (nfi populates these 4, don't have to be = undef)
- private int _iCurrencyDigits; // (user can override) # local monetary fractional digits
- private int _iCurrency; // (user can override) positive currency format
- private int _iNegativeCurrency; // (user can override) negative currency format
- private int[]? _waMonetaryGrouping; // (user can override) monetary grouping of digits
- private string? _sMonetaryDecimal; // (user can override) monetary decimal separator
- private string? _sMonetaryThousand; // (user can override) monetary thousands separator
-
- // Misc
- private int _iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo)
- private string? _sListSeparator; // (user can override) list separator
-
- // Time
- private string? _sAM1159; // (user can override) AM designator
- private string? _sPM2359; // (user can override) PM designator
- private string? _sTimeSeparator;
- private volatile string[]? _saLongTimes; // (user can override) time format
- private volatile string[]? _saShortTimes; // short time format
- private volatile string[]? _saDurationFormats; // time duration format
-
- // Calendar specific data
- private int _iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really)
- private int _iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really)
- private volatile CalendarId[]? _waCalendars; // all available calendar type(s). The first one is the default calendar
-
- // Store for specific data about each calendar
- private CalendarData?[]? _calendars; // Store for specific calendar data
-
- // Text information
- private int _iReadingLayout = undef; // Reading layout data
- // 0 - Left to right (eg en-US)
- // 1 - Right to left (eg arabic locales)
- // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
- // 3 - Vertical top to bottom with columns proceeding to the right
-
- // CoreCLR depends on this even though its not exposed publicly.
-
- private int _iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP)
- private int _iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM)
- private int _iDefaultMacCodePage = undef; // default macintosh code page
- private int _iDefaultEbcdicCodePage = undef; // default EBCDIC code page
-
- private int _iLanguage; // locale ID (0409) - NO sort information
- private bool _bUseOverrides; // use user overrides?
- private bool _bNeutral; // Flags for the culture (ie: neutral or not right now)
-
- /// <summary>
- /// Region Name to Culture Name mapping table
- /// </summary>
- /// <remarks>
- /// Using a property so we avoid creating the dictionary until we need it
- /// </remarks>
- private static Dictionary<string, string> RegionNames =>
- s_regionNames ??=
- new Dictionary<string, string>(211 /* prime */)
- {
- { "029", "en-029" },
- { "AE", "ar-AE" },
- { "AF", "prs-AF" },
- { "AL", "sq-AL" },
- { "AM", "hy-AM" },
- { "AR", "es-AR" },
- { "AT", "de-AT" },
- { "AU", "en-AU" },
- { "AZ", "az-Cyrl-AZ" },
- { "BA", "bs-Latn-BA" },
- { "BD", "bn-BD" },
- { "BE", "nl-BE" },
- { "BG", "bg-BG" },
- { "BH", "ar-BH" },
- { "BN", "ms-BN" },
- { "BO", "es-BO" },
- { "BR", "pt-BR" },
- { "BY", "be-BY" },
- { "BZ", "en-BZ" },
- { "CA", "en-CA" },
- { "CH", "it-CH" },
- { "CL", "es-CL" },
- { "CN", "zh-CN" },
- { "CO", "es-CO" },
- { "CR", "es-CR" },
- { "CS", "sr-Cyrl-CS" },
- { "CZ", "cs-CZ" },
- { "DE", "de-DE" },
- { "DK", "da-DK" },
- { "DO", "es-DO" },
- { "DZ", "ar-DZ" },
- { "EC", "es-EC" },
- { "EE", "et-EE" },
- { "EG", "ar-EG" },
- { "ES", "es-ES" },
- { "ET", "am-ET" },
- { "FI", "fi-FI" },
- { "FO", "fo-FO" },
- { "FR", "fr-FR" },
- { "GB", "en-GB" },
- { "GE", "ka-GE" },
- { "GL", "kl-GL" },
- { "GR", "el-GR" },
- { "GT", "es-GT" },
- { "HK", "zh-HK" },
- { "HN", "es-HN" },
- { "HR", "hr-HR" },
- { "HU", "hu-HU" },
- { "ID", "id-ID" },
- { "IE", "en-IE" },
- { "IL", "he-IL" },
- { "IN", "hi-IN" },
- { "IQ", "ar-IQ" },
- { "IR", "fa-IR" },
- { "IS", "is-IS" },
- { "IT", "it-IT" },
- { "IV", "" },
- { "JM", "en-JM" },
- { "JO", "ar-JO" },
- { "JP", "ja-JP" },
- { "KE", "sw-KE" },
- { "KG", "ky-KG" },
- { "KH", "km-KH" },
- { "KR", "ko-KR" },
- { "KW", "ar-KW" },
- { "KZ", "kk-KZ" },
- { "LA", "lo-LA" },
- { "LB", "ar-LB" },
- { "LI", "de-LI" },
- { "LK", "si-LK" },
- { "LT", "lt-LT" },
- { "LU", "lb-LU" },
- { "LV", "lv-LV" },
- { "LY", "ar-LY" },
- { "MA", "ar-MA" },
- { "MC", "fr-MC" },
- { "ME", "sr-Latn-ME" },
- { "MK", "mk-MK" },
- { "MN", "mn-MN" },
- { "MO", "zh-MO" },
- { "MT", "mt-MT" },
- { "MV", "dv-MV" },
- { "MX", "es-MX" },
- { "MY", "ms-MY" },
- { "NG", "ig-NG" },
- { "NI", "es-NI" },
- { "NL", "nl-NL" },
- { "NO", "nn-NO" },
- { "NP", "ne-NP" },
- { "NZ", "en-NZ" },
- { "OM", "ar-OM" },
- { "PA", "es-PA" },
- { "PE", "es-PE" },
- { "PH", "en-PH" },
- { "PK", "ur-PK" },
- { "PL", "pl-PL" },
- { "PR", "es-PR" },
- { "PT", "pt-PT" },
- { "PY", "es-PY" },
- { "QA", "ar-QA" },
- { "RO", "ro-RO" },
- { "RS", "sr-Latn-RS" },
- { "RU", "ru-RU" },
- { "RW", "rw-RW" },
- { "SA", "ar-SA" },
- { "SE", "sv-SE" },
- { "SG", "zh-SG" },
- { "SI", "sl-SI" },
- { "SK", "sk-SK" },
- { "SN", "wo-SN" },
- { "SV", "es-SV" },
- { "SY", "ar-SY" },
- { "TH", "th-TH" },
- { "TJ", "tg-Cyrl-TJ" },
- { "TM", "tk-TM" },
- { "TN", "ar-TN" },
- { "TR", "tr-TR" },
- { "TT", "en-TT" },
- { "TW", "zh-TW" },
- { "UA", "uk-UA" },
- { "US", "en-US" },
- { "UY", "es-UY" },
- { "UZ", "uz-Cyrl-UZ" },
- { "VE", "es-VE" },
- { "VN", "vi-VN" },
- { "YE", "ar-YE" },
- { "ZA", "af-ZA" },
- { "ZW", "en-ZW" }
- };
-
- // Cache of regions we've already looked up
- private static volatile Dictionary<string, CultureData>? s_cachedRegions;
- private static volatile Dictionary<string, string>? s_regionNames;
-
- internal static CultureData? GetCultureDataForRegion(string? cultureName, bool useUserOverride)
- {
- // First do a shortcut for Invariant
- if (string.IsNullOrEmpty(cultureName))
- {
- return CultureData.Invariant;
- }
-
- // First check if GetCultureData() can find it (ie: its a real culture)
- CultureData? retVal = GetCultureData(cultureName, useUserOverride);
- if (retVal != null && !retVal.IsNeutralCulture)
- {
- return retVal;
- }
-
- // Not a specific culture, perhaps it's region-only name
- // (Remember this isn't a core clr path where that's not supported)
-
- // If it was neutral remember that so that RegionInfo() can throw the right exception
- CultureData? neutral = retVal;
-
- // Try the hash table next
- string hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
- Dictionary<string, CultureData>? tempHashTable = s_cachedRegions;
-
- if (tempHashTable == null)
- {
- // No table yet, make a new one
- tempHashTable = new Dictionary<string, CultureData>();
- }
- else
- {
- // Check the hash table
- lock (s_lock)
- {
- tempHashTable.TryGetValue(hashName, out retVal);
- }
- if (retVal != null)
- {
- return retVal;
- }
- }
-
- // Not found in the hash table, look it up the hard way
-
- // If not a valid mapping from the registry we'll have to try the hard coded table
- if (retVal == null || retVal.IsNeutralCulture)
- {
- // Not a valid mapping, try the hard coded table
- string? name;
- if (RegionNames.TryGetValue(cultureName, out name))
- {
- // Make sure we can get culture data for it
- retVal = GetCultureData(name, useUserOverride);
- }
- }
-
- // If not found in the hard coded table we'll have to find a culture that works for us
- if (!GlobalizationMode.Invariant && (retVal == null || retVal.IsNeutralCulture))
- {
- retVal = GetCultureDataFromRegionName(cultureName);
- }
-
- // If we found one we can use, then cache it for next time
- if (retVal != null && !retVal.IsNeutralCulture)
- {
- // first add it to the cache
- lock (s_lock)
- {
- tempHashTable[hashName] = retVal;
- }
-
- // Copy the hashtable to the corresponding member variables. This will potentially overwrite
- // new tables simultaneously created by a new thread, but maximizes thread safety.
- s_cachedRegions = tempHashTable;
- }
- else
- {
- // Unable to find a matching culture/region, return null or neutral
- // (regionInfo throws a more specific exception on neutrals)
- retVal = neutral;
- }
-
- // Return the found culture to use, null, or the neutral culture.
- return retVal;
- }
-
- // Clear our internal caches
- internal static void ClearCachedData()
- {
- s_cachedCultures = null;
- s_cachedRegions = null;
- }
-
- internal static CultureInfo[] GetCultures(CultureTypes types)
- {
- // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
-#pragma warning disable 618
- // Validate flags
- if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures |
- CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture |
- CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures |
- CultureTypes.FrameworkCultures)) != 0)
- {
- throw new ArgumentOutOfRangeException(nameof(types),
- SR.Format(SR.ArgumentOutOfRange_Range, CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures));
- }
-
- // We have deprecated CultureTypes.FrameworkCultures.
- // When this enum is used, we will enumerate Whidbey framework cultures (for compatibility).
-
- // We have deprecated CultureTypes.WindowsOnlyCultures.
- // When this enum is used, we will return an empty array for this enum.
- if ((types & CultureTypes.WindowsOnlyCultures) != 0)
- {
- // Remove the enum as it is an no-op.
- types &= (~CultureTypes.WindowsOnlyCultures);
- }
-
- if (GlobalizationMode.Invariant)
- {
- // in invariant mode we always return invariant culture only from the enumeration
- return new CultureInfo[] { new CultureInfo("") };
- }
-
-#pragma warning restore 618
- return EnumCultures(types);
- }
-
- private static CultureData CreateCultureWithInvariantData()
- {
- // Make a new culturedata
- CultureData invariant = new CultureData();
-
- // Basics
- // Note that we override the resources since this IS NOT supposed to change (by definition)
- invariant._bUseOverrides = false;
- invariant._sRealName = ""; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
- invariant._sWindowsName = ""; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
-
- // Identity
- invariant._sName = ""; // locale name (ie: en-us)
- invariant._sParent = ""; // Parent name (which may be a custom locale/culture)
- invariant._bNeutral = false; // Flags for the culture (ie: neutral or not right now)
- invariant._sEnglishDisplayName = "Invariant Language (Invariant Country)"; // English pretty name for this locale
- invariant._sNativeDisplayName = "Invariant Language (Invariant Country)"; // Native pretty name for this locale
- invariant._sSpecificCulture = ""; // The culture name to be used in CultureInfo.CreateSpecificCulture()
-
- // Language
- invariant._sISO639Language = "iv"; // ISO 639 Language Name
- invariant._sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2
- invariant._sLocalizedLanguage = "Invariant Language"; // Display name for this Language
- invariant._sEnglishLanguage = "Invariant Language"; // English name for this language
- invariant._sNativeLanguage = "Invariant Language"; // Native name of this language
- invariant._sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name)
- invariant._sConsoleFallbackName = ""; // The culture name for the console fallback UI culture
- invariant._iInputLanguageHandle = 0x07F; // input language handle
-
- // Region
- invariant._sRegionName = "IV"; // (RegionInfo)
- invariant._sEnglishCountry = "Invariant Country"; // english country name (RegionInfo)
- invariant._sNativeCountry = "Invariant Country"; // native country name (Windows Only)
- invariant._sISO3166CountryName = "IV"; // (RegionInfo), ie: US
- invariant._sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo)
- invariant._iGeoId = 244; // GeoId (Windows Only)
-
- // Numbers
- invariant._sPositiveSign = "+"; // positive sign
- invariant._sNegativeSign = "-"; // negative sign
- invariant._iDigits = 2; // number of fractional digits
- invariant._iNegativeNumber = 1; // negative number format
- invariant._waGrouping = new int[] { 3 }; // grouping of digits
- invariant._sDecimalSeparator = "."; // decimal separator
- invariant._sThousandSeparator = ","; // thousands separator
- invariant._sNaN = "NaN"; // Not a Number
- invariant._sPositiveInfinity = "Infinity"; // + Infinity
- invariant._sNegativeInfinity = "-Infinity"; // - Infinity
-
- // Percent
- invariant._iNegativePercent = 0; // Negative Percent (0-3)
- invariant._iPositivePercent = 0; // Positive Percent (0-11)
- invariant._sPercent = "%"; // Percent (%) symbol
- invariant._sPerMille = "\x2030"; // PerMille symbol
-
- // Currency
- invariant._sCurrency = "\x00a4"; // local monetary symbol: for international monetary symbol
- invariant._sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo)
- invariant._sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only)
- invariant._sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only)
- invariant._iCurrencyDigits = 2; // # local monetary fractional digits
- invariant._iCurrency = 0; // positive currency format
- invariant._iNegativeCurrency = 0; // negative currency format
- invariant._waMonetaryGrouping = new int[] { 3 }; // monetary grouping of digits
- invariant._sMonetaryDecimal = "."; // monetary decimal separator
- invariant._sMonetaryThousand = ","; // monetary thousands separator
-
- // Misc
- invariant._iMeasure = 0; // system of measurement 0=metric, 1=US (RegionInfo)
- invariant._sListSeparator = ","; // list separator
-
- // Time
- invariant._sTimeSeparator = ":";
- invariant._sAM1159 = "AM"; // AM designator
- invariant._sPM2359 = "PM"; // PM designator
- invariant._saLongTimes = new string[] { "HH:mm:ss" }; // time format
- invariant._saShortTimes = new string[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format
- invariant._saDurationFormats = new string[] { "HH:mm:ss" }; // time duration format
-
- // Calendar specific data
- invariant._iFirstDayOfWeek = 0; // first day of week
- invariant._iFirstWeekOfYear = 0; // first week of year
- invariant._waCalendars = new CalendarId[] { CalendarId.GREGORIAN }; // all available calendar type(s). The first one is the default calendar
-
- // Store for specific data about each calendar
- invariant._calendars = new CalendarData[CalendarData.MAX_CALENDARS];
- invariant._calendars[0] = CalendarData.Invariant;
-
- // Text information
- invariant._iReadingLayout = 0;
-
- // These are desktop only, not coreclr
-
- invariant._iLanguage = CultureInfo.LOCALE_INVARIANT; // locale ID (0409) - NO sort information
- invariant._iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP)
- invariant._iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM)
- invariant._iDefaultMacCodePage = 10000; // default macintosh code page
- invariant._iDefaultEbcdicCodePage = 037; // default EBCDIC code page
-
- if (GlobalizationMode.Invariant)
- {
- invariant._sLocalizedDisplayName = invariant._sNativeDisplayName;
- invariant._sLocalizedCountry = invariant._sNativeCountry;
- }
-
- return invariant;
- }
-
- /// <summary>
- /// Build our invariant information
- /// We need an invariant instance, which we build hard-coded
- /// </summary>
- internal static CultureData Invariant => s_Invariant ??= CreateCultureWithInvariantData();
- private static volatile CultureData? s_Invariant;
-
- // Cache of cultures we've already looked up
- private static volatile Dictionary<string, CultureData>? s_cachedCultures;
- private static readonly object s_lock = new object();
-
- internal static CultureData? GetCultureData(string? cultureName, bool useUserOverride)
- {
- // First do a shortcut for Invariant
- if (string.IsNullOrEmpty(cultureName))
- {
- return CultureData.Invariant;
- }
-
- // Try the hash table first
- string hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
- Dictionary<string, CultureData>? tempHashTable = s_cachedCultures;
- if (tempHashTable == null)
- {
- // No table yet, make a new one
- tempHashTable = new Dictionary<string, CultureData>();
- }
- else
- {
- // Check the hash table
- bool ret;
- CultureData? retVal;
- lock (s_lock)
- {
- ret = tempHashTable.TryGetValue(hashName, out retVal);
- }
- if (ret && retVal != null)
- {
- return retVal;
- }
- }
-
- // Not found in the hash table, need to see if we can build one that works for us
- CultureData? culture = CreateCultureData(cultureName, useUserOverride);
- if (culture == null)
- {
- return null;
- }
-
- // Found one, add it to the cache
- lock (s_lock)
- {
- tempHashTable[hashName] = culture;
- }
-
- // Copy the hashtable to the corresponding member variables. This will potentially overwrite
- // new tables simultaneously created by a new thread, but maximizes thread safety.
- s_cachedCultures = tempHashTable;
-
- return culture;
- }
-
- private static string NormalizeCultureName(string name, out bool isNeutralName)
- {
- isNeutralName = true;
- int i = 0;
-
- if (name.Length > LocaleNameMaxLength)
- {
- // Theoretically we shouldn't hit this exception.
- throw new ArgumentException(SR.Format(SR.Argument_InvalidId, nameof(name)));
- }
-
- Span<char> normalizedName = stackalloc char[name.Length];
-
- bool changed = false;
-
- while (i < name.Length && name[i] != '-' && name[i] != '_')
- {
- if (name[i] >= 'A' && name[i] <= 'Z')
- {
- // lowercase characters before '-'
- normalizedName[i] = (char)(((int)name[i]) + 0x20);
- changed = true;
- }
- else
- {
- normalizedName[i] = name[i];
- }
- i++;
- }
-
- if (i < name.Length)
- {
- // this is not perfect to detect the non neutral cultures but it is good enough when we are running in invariant mode
- isNeutralName = false;
- }
-
- while (i < name.Length)
- {
- if (name[i] >= 'a' && name[i] <= 'z')
- {
- normalizedName[i] = (char)(((int)name[i]) - 0x20);
- changed = true;
- }
- else
- {
- normalizedName[i] = name[i];
- }
- i++;
- }
-
- if (changed)
- {
- return new string(normalizedName);
- }
-
- return name;
- }
-
- private static CultureData? CreateCultureData(string cultureName, bool useUserOverride)
- {
- if (GlobalizationMode.Invariant)
- {
- if (cultureName.Length > LocaleNameMaxLength || !CultureInfo.VerifyCultureName(cultureName, false))
- {
- return null;
- }
- CultureData cd = CreateCultureWithInvariantData();
- cd._bUseOverrides = useUserOverride;
- cd._sName = NormalizeCultureName(cultureName, out cd._bNeutral);
- cd._sRealName = cd._sName;
- cd._sWindowsName = cd._sName;
- cd._iLanguage = CultureInfo.LOCALE_CUSTOM_UNSPECIFIED;
-
- return cd;
- }
-
- if (cultureName.Length == 1 && (cultureName[0] == 'C' || cultureName[0] == 'c'))
- {
- // Always map the "C" locale to Invariant to avoid mapping it to en_US_POSIX on Linux because POSIX
- // locale collation doesn't support case insensitive comparisons.
- // We do the same mapping on Windows for the sake of consistency.
- return CultureData.Invariant;
- }
-
- CultureData culture = new CultureData();
- culture._bUseOverrides = useUserOverride;
- culture._sRealName = cultureName;
-
- // Ask native code if that one's real
- if (!culture.InitCultureData() && !culture.InitCompatibilityCultureData())
- {
- return null;
- }
-
- return culture;
- }
-
- private bool InitCompatibilityCultureData()
- {
- // for compatibility handle the deprecated ids: zh-chs, zh-cht
- string cultureName = _sRealName!;
-
- string fallbackCultureName;
- string realCultureName;
- switch (AnsiToLower(cultureName))
- {
- case "zh-chs":
- fallbackCultureName = "zh-Hans";
- realCultureName = "zh-CHS";
- break;
- case "zh-cht":
- fallbackCultureName = "zh-Hant";
- realCultureName = "zh-CHT";
- break;
- default:
- return false;
- }
-
- _sRealName = fallbackCultureName;
- if (!InitCultureData())
- {
- return false;
- }
-
- // fixup our data
- _sName = realCultureName; // the name that goes back to the user
- _sParent = fallbackCultureName;
-
- return true;
- }
-
- /// We'd rather people use the named version since this doesn't allow custom locales
- internal static CultureData GetCultureData(int culture, bool bUseUserOverride)
- {
- string? localeName = null;
- CultureData? retVal = null;
-
- if (culture == CultureInfo.LOCALE_INVARIANT)
- {
- return Invariant;
- }
-
- if (GlobalizationMode.Invariant)
- {
- // LCID is not supported in the InvariantMode
- throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported);
- }
-
- // Convert the lcid to a name, then use that
- // Note that this will return neutral names (unlike Vista native API)
- localeName = LCIDToLocaleName(culture);
-
- if (!string.IsNullOrEmpty(localeName))
- {
- // Valid name, use it
- retVal = GetCultureData(localeName, bUseUserOverride);
- }
-
- // If not successful, throw
- if (retVal == null)
- {
- throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported);
- }
-
- // Return the one we found
- return retVal;
- }
-
- /// <summary>
- /// The real name used to construct the locale (ie: de-DE_phoneb)
- /// </summary>
- internal string CultureName
- {
- get
- {
- Debug.Assert(_sRealName != null, "[CultureData.CultureName] Expected _sRealName to be populated by already");
- // since windows doesn't know about zh-CHS and zh-CHT,
- // we leave sRealName == zh-Hanx but we still need to
- // pretend that it was zh-CHX.
- switch (_sName)
- {
- case "zh-CHS":
- case "zh-CHT":
- return _sName;
- }
- return _sRealName;
- }
- }
-
- /// <summary>
- /// Are overrides enabled?
- /// </summary>
- internal bool UseUserOverride => _bUseOverrides;
-
- /// <summary>
- /// locale name (ie: de-DE, NO sort information)
- /// </summary>
- internal string Name => _sName ?? string.Empty;
-
- // Parent name (which may be a custom locale/culture)
- // Ask using the real name, so that we get parents of neutrals
- internal string ParentName => _sParent ??= GetLocaleInfo(_sRealName!, LocaleStringData.ParentName);
-
- // Localized pretty name for this locale (ie: Inglis (estados Unitos))
- internal string DisplayName
- {
- get
- {
- string? localizedDisplayName = _sLocalizedDisplayName;
- if (localizedDisplayName == null)
- {
- if (IsSupplementalCustomCulture)
- {
- if (IsNeutralCulture)
- {
- localizedDisplayName = NativeLanguageName;
- }
- else
- {
- localizedDisplayName = NativeName;
- }
- }
- else
- {
- try
- {
- const string ZH_CHT = "zh-CHT";
- const string ZH_CHS = "zh-CHS";
-
- if (Name.Equals(ZH_CHT, StringComparison.OrdinalIgnoreCase))
- {
- localizedDisplayName = GetLanguageDisplayName("zh-Hant");
- }
- else if (Name.Equals(ZH_CHS, StringComparison.OrdinalIgnoreCase))
- {
- localizedDisplayName = GetLanguageDisplayName("zh-Hans");
- }
- else
- {
- localizedDisplayName = GetLanguageDisplayName(Name);
- }
- }
- catch
- {
- // do nothing
- }
- }
-
- // If it hasn't been found (Windows 8 and up), fallback to the system
- if (string.IsNullOrEmpty(localizedDisplayName))
- {
- // If its neutral use the language name
- if (IsNeutralCulture)
- {
- localizedDisplayName = LocalizedLanguageName;
- }
- else
- {
- // Usually the UI culture shouldn't be different than what we got from WinRT except
- // if DefaultThreadCurrentUICulture was set
- CultureInfo ci;
-
- if (CultureInfo.DefaultThreadCurrentUICulture != null &&
- ((ci = CultureInfo.GetUserDefaultCulture()) != null) &&
- !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name))
- {
- localizedDisplayName = NativeName;
- }
- else
- {
- localizedDisplayName = GetLocaleInfo(LocaleStringData.LocalizedDisplayName);
- }
- }
- }
-
- _sLocalizedDisplayName = localizedDisplayName;
- }
-
- return localizedDisplayName;
- }
- }
-
- /// <summary>
- /// English pretty name for this locale (ie: English (United States))
- /// </summary>
- internal string EnglishName
- {
- get
- {
- string? englishDisplayName = _sEnglishDisplayName;
- if (englishDisplayName == null)
- {
- // If its neutral use the language name
- if (IsNeutralCulture)
- {
- englishDisplayName = EnglishLanguageName;
- // differentiate the legacy display names
- switch (_sName)
- {
- case "zh-CHS":
- case "zh-CHT":
- englishDisplayName += " Legacy";
- break;
- }
- }
- else
- {
- englishDisplayName = GetLocaleInfo(LocaleStringData.EnglishDisplayName);
-
- // if it isn't found build one:
- if (string.IsNullOrEmpty(englishDisplayName))
- {
- // Our existing names mostly look like:
- // "English" + "United States" -> "English (United States)"
- // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
- if (EnglishLanguageName[^1] == ')')
- {
- // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
- englishDisplayName = string.Concat(
- EnglishLanguageName.AsSpan(0, _sEnglishLanguage!.Length - 1),
- ", ",
- EnglishCountryName,
- ")");
- }
- else
- {
- // "English" + "United States" -> "English (United States)"
- englishDisplayName = EnglishLanguageName + " (" + EnglishCountryName + ")";
- }
- }
- }
-
- _sEnglishDisplayName = englishDisplayName;
- }
-
- return englishDisplayName;
- }
- }
-
- /// <summary>
- /// Native pretty name for this locale (ie: Deutsch (Deutschland))
- /// </summary>
- internal string NativeName
- {
- get
- {
- string? nativeDisplayName = _sNativeDisplayName;
- if (nativeDisplayName == null)
- {
- // If its neutral use the language name
- if (IsNeutralCulture)
- {
- nativeDisplayName = NativeLanguageName;
- // differentiate the legacy display names
- switch (_sName)
- {
- case "zh-CHS":
- nativeDisplayName += " \u65E7\u7248";
- break;
- case "zh-CHT":
- nativeDisplayName += " \u820A\u7248";
- break;
- }
- }
- else
- {
- nativeDisplayName = GetLocaleInfo(LocaleStringData.NativeDisplayName);
-
- // if it isn't found build one:
- if (string.IsNullOrEmpty(nativeDisplayName))
- {
- // These should primarily be "Deutsch (Deutschland)" type names
- nativeDisplayName = NativeLanguageName + " (" + NativeCountryName + ")";
- }
- }
-
- _sNativeDisplayName = nativeDisplayName;
- }
-
- return nativeDisplayName;
- }
- }
-
- /// <summary>
- /// The culture name to be used in CultureInfo.CreateSpecificCulture()
- /// </summary>
- internal string SpecificCultureName
- {
- get
- {
- // This got populated during the culture initialization
- Debug.Assert(_sSpecificCulture != null, "[CultureData.SpecificCultureName] Expected this.sSpecificCulture to be populated by culture data initialization already");
- return _sSpecificCulture;
- }
- }
-
- /// <summary>
- /// iso 639 language name, ie: en
- /// </summary>
- internal string TwoLetterISOLanguageName => _sISO639Language ??= GetLocaleInfo(LocaleStringData.Iso639LanguageTwoLetterName);
-
- /// <summary>
- /// iso 639 language name, ie: eng
- /// </summary>
- internal string ThreeLetterISOLanguageName => _sISO639Language2 ??= GetLocaleInfo(LocaleStringData.Iso639LanguageThreeLetterName);
-
- /// <summary>
- /// abbreviated windows language name (ie: enu) (non-standard, avoid this)
- /// </summary>
- internal string ThreeLetterWindowsLanguageName => _sAbbrevLang ??= GetThreeLetterWindowsLanguageName(_sRealName!);
-
- /// <summary>
- /// Localized name for this language (Windows Only) ie: Inglis
- /// This is only valid for Windows 8 and higher neutrals:
- /// </summary>
- private string LocalizedLanguageName
- {
- get
- {
- if (_sLocalizedLanguage == null)
- {
- // Usually the UI culture shouldn't be different than what we got from WinRT except
- // if DefaultThreadCurrentUICulture was set
- CultureInfo ci;
-
- if (CultureInfo.DefaultThreadCurrentUICulture != null &&
- ((ci = CultureInfo.GetUserDefaultCulture()) != null) &&
- !CultureInfo.DefaultThreadCurrentUICulture!.Name.Equals(ci.Name))
- {
- _sLocalizedLanguage = NativeLanguageName;
- }
- else
- {
- _sLocalizedLanguage = GetLocaleInfo(LocaleStringData.LocalizedLanguageName);
- }
- }
-
- return _sLocalizedLanguage;
- }
- }
-
- /// <summary>
- /// English name for this language (Windows Only) ie: German
- /// </summary>
- private string EnglishLanguageName => _sEnglishLanguage ??= GetLocaleInfo(LocaleStringData.EnglishLanguageName);
-
- /// <summary>
- /// Native name of this language (Windows Only) ie: Deutsch
- /// </summary>
- private string NativeLanguageName => _sNativeLanguage ??= GetLocaleInfo(LocaleStringData.NativeLanguageName);
-
- /// <summary>
- /// region name (eg US)
- /// </summary>
- internal string RegionName => _sRegionName ??= GetLocaleInfo(LocaleStringData.Iso3166CountryName);
-
- internal int GeoId
- {
- get
- {
- if (_iGeoId == undef)
- {
- _iGeoId = GetGeoId(_sRealName!);
- }
- return _iGeoId;
- }
- }
-
- /// <summary>
- /// localized name for the country
- /// </summary>
- internal string LocalizedCountryName
- {
- get
- {
- string? localizedCountry = _sLocalizedCountry;
- if (localizedCountry == null)
- {
- try
- {
- localizedCountry = GetRegionDisplayName();
- }
- catch
- {
- // do nothing. we'll fallback
- }
-
- localizedCountry ??= NativeCountryName;
- _sLocalizedCountry = localizedCountry;
- }
-
- return localizedCountry;
- }
- }
-
- /// <summary>
- /// english country name (RegionInfo) ie: Germany
- /// </summary>
- internal string EnglishCountryName => _sEnglishCountry ??= GetLocaleInfo(LocaleStringData.EnglishCountryName);
-
- /// <summary>
- /// native country name (RegionInfo) ie: Deutschland
- /// </summary>
- internal string NativeCountryName => _sNativeCountry ??= GetLocaleInfo(LocaleStringData.NativeCountryName);
-
- /// <summary>
- /// ISO 3166 Country Name
- /// </summary>
- internal string TwoLetterISOCountryName => _sISO3166CountryName ??= GetLocaleInfo(LocaleStringData.Iso3166CountryName);
-
- /// <summary>
- /// 3 letter ISO 3166 country code
- /// </summary>
- internal string ThreeLetterISOCountryName => _sISO3166CountryName2 ??= GetLocaleInfo(LocaleStringData.Iso3166CountryName2);
-
- internal int KeyboardLayoutId
- {
- get
- {
- if (_iInputLanguageHandle == undef)
- {
- if (IsSupplementalCustomCulture)
- {
- _iInputLanguageHandle = 0x0409;
- }
- else
- {
- // Input Language is same as LCID for built-in cultures
- _iInputLanguageHandle = LCID;
- }
- }
- return _iInputLanguageHandle;
- }
- }
-
- /// <summary>
- /// Console fallback name (ie: locale to use for console apps for unicode-only locales)
- /// </summary>
- internal string SCONSOLEFALLBACKNAME => _sConsoleFallbackName ??= GetConsoleFallbackName(_sRealName!);
-
- /// <summary>
- /// (user can override) grouping of digits
- /// </summary>
- internal int[] NumberGroupSizes => _waGrouping ??= GetLocaleInfo(LocaleGroupingData.Digit);
-
- /// <summary>
- /// Not a Number
- /// </summary>
- private string NaNSymbol => _sNaN ??= GetLocaleInfo(LocaleStringData.NaNSymbol);
-
- /// <summary>
- /// + Infinity
- /// </summary>
- private string PositiveInfinitySymbol => _sPositiveInfinity ??= GetLocaleInfo(LocaleStringData.PositiveInfinitySymbol);
-
- /// <summary>
- /// - Infinity
- /// </summary>
- private string NegativeInfinitySymbol => _sNegativeInfinity ??= GetLocaleInfo(LocaleStringData.NegativeInfinitySymbol);
-
- /// <summary>
- /// Negative Percent (0-3)
- /// </summary>
- private int PercentNegativePattern
- {
- get
- {
- if (_iNegativePercent == undef)
- {
- // Note that <= Windows Vista this is synthesized by native code
- _iNegativePercent = GetLocaleInfo(LocaleNumberData.NegativePercentFormat);
- }
- return _iNegativePercent;
- }
- }
-
- /// <summary>
- /// Positive Percent (0-11)
- /// </summary>
- private int PercentPositivePattern
- {
- get
- {
- if (_iPositivePercent == undef)
- {
- // Note that <= Windows Vista this is synthesized by native code
- _iPositivePercent = GetLocaleInfo(LocaleNumberData.PositivePercentFormat);
- }
- return _iPositivePercent;
- }
- }
-
- /// <summary>
- /// Percent (%) symbol
- /// </summary>
- private string PercentSymbol => _sPercent ??= GetLocaleInfo(LocaleStringData.PercentSymbol);
-
- /// <summary>
- /// PerMille symbol
- /// </summary>
- private string PerMilleSymbol => _sPerMille ??= GetLocaleInfo(LocaleStringData.PerMilleSymbol);
-
- /// <summary>
- /// (user can override) local monetary symbol, eg: $
- /// </summary>
- internal string CurrencySymbol => _sCurrency ??= GetLocaleInfo(LocaleStringData.MonetarySymbol);
-
- /// <summary>
- /// international monetary symbol (RegionInfo), eg: USD
- /// </summary>
- internal string ISOCurrencySymbol => _sIntlMonetarySymbol ??= GetLocaleInfo(LocaleStringData.Iso4217MonetarySymbol);
-
- /// <summary>
- /// English name for this currency (RegionInfo), eg: US Dollar
- /// </summary>
- internal string CurrencyEnglishName => _sEnglishCurrency ??= GetLocaleInfo(LocaleStringData.CurrencyEnglishName);
-
- /// <summary>
- /// Native name for this currency (RegionInfo), eg: Schweiz Frank
- /// </summary>
- internal string CurrencyNativeName => _sNativeCurrency ??= GetLocaleInfo(LocaleStringData.CurrencyNativeName);
-
- /// <summary>
- /// (user can override) monetary grouping of digits
- /// </summary>
- internal int[] CurrencyGroupSizes => _waMonetaryGrouping ??= GetLocaleInfo(LocaleGroupingData.Monetary);
-
- /// <summary>
- /// (user can override) system of measurement 0=metric, 1=US (RegionInfo)
- /// </summary>
- internal int MeasurementSystem
- {
- get
- {
- if (_iMeasure == undef)
- {
- _iMeasure = GetLocaleInfo(LocaleNumberData.MeasurementSystem);
- }
- return _iMeasure;
- }
- }
-
- /// <summary>
- /// (user can override) list Separator
- /// </summary>
- internal string ListSeparator => _sListSeparator ??= GetLocaleInfo(LocaleStringData.ListSeparator);
-
- /// <summary>
- /// (user can override) AM designator
- /// </summary>
- internal string AMDesignator => _sAM1159 ??= GetLocaleInfo(LocaleStringData.AMDesignator);
-
- /// <summary>
- /// (user can override) PM designator
- /// </summary>
- internal string PMDesignator => _sPM2359 ??= GetLocaleInfo(LocaleStringData.PMDesignator);
-
- /// <summary>
- /// (user can override) time format
- /// </summary>
- internal string[] LongTimes
- {
- get
- {
- if (_saLongTimes == null)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- string[]? longTimes = GetTimeFormats();
- if (longTimes == null || longTimes.Length == 0)
- {
- _saLongTimes = Invariant._saLongTimes!;
- }
- else
- {
- _saLongTimes = longTimes;
- }
- }
- return _saLongTimes;
- }
- }
-
- /// <summary>
- /// short time format
- /// Short times (derived from long times format)
- /// </summary>
- internal string[] ShortTimes
- {
- get
- {
- if (_saShortTimes == null)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- // Try to get the short times from the OS/culture.dll
- string[]? shortTimes = GetShortTimeFormats();
-
- if (shortTimes == null || shortTimes.Length == 0)
- {
- //
- // If we couldn't find short times, then compute them from long times
- // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll)
- //
- shortTimes = DeriveShortTimesFromLong();
- }
-
- // Found short times, use them
- _saShortTimes = shortTimes;
- }
- return _saShortTimes;
- }
- }
-
- private string[] DeriveShortTimesFromLong()
- {
- // Our logic is to look for h,H,m,s,t. If we find an s, then we check the string
- // between it and the previous marker, if any. If its a short, unescaped separator,
- // then we don't retain that part.
- // We then check after the ss and remove anything before the next h,H,m,t...
- string[] longTimes = LongTimes;
- string[] shortTimes = new string[longTimes.Length];
-
- for (int i = 0; i < longTimes.Length; i++)
- {
- shortTimes[i] = StripSecondsFromPattern(longTimes[i]);
- }
- return shortTimes;
- }
-
- private static string StripSecondsFromPattern(string time)
- {
- bool bEscape = false;
- int iLastToken = -1;
-
- // Find the seconds
- for (int j = 0; j < time.Length; j++)
- {
- // Change escape mode?
- if (time[j] == '\'')
- {
- // Continue
- bEscape = !bEscape;
- continue;
- }
-
- // See if there was a single \
- if (time[j] == '\\')
- {
- // Skip next char
- j++;
- continue;
- }
-
- if (bEscape)
- {
- continue;
- }
-
- switch (time[j])
- {
- // Check for seconds
- case 's':
- // Found seconds, see if there was something unescaped and short between
- // the last marker and the seconds. Windows says separator can be a
- // maximum of three characters (without null)
- // If 1st or last characters were ', then ignore it
- if ((j - iLastToken) <= 4 && (j - iLastToken) > 1 &&
- (time[iLastToken + 1] != '\'') &&
- (time[j - 1] != '\''))
- {
- // There was something there we want to remember
- if (iLastToken >= 0)
- {
- j = iLastToken + 1;
- }
- }
-
- bool containsSpace;
- int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace);
-
- string sep;
-
- if (containsSpace)
- {
- sep = " ";
- }
- else
- {
- sep = "";
- }
-
- time = string.Concat(time.AsSpan(0, j), sep, time.AsSpan(endIndex));
- break;
- case 'm':
- case 'H':
- case 'h':
- iLastToken = j;
- break;
- }
- }
- return time;
- }
-
- private static int GetIndexOfNextTokenAfterSeconds(string time, int index, out bool containsSpace)
- {
- bool shouldEscape = false;
- containsSpace = false;
- for (; index < time.Length; index++)
- {
- switch (time[index])
- {
- case '\'':
- shouldEscape = !shouldEscape;
- continue;
- case '\\':
- index++;
- if (time[index] == ' ')
- {
- containsSpace = true;
- }
- continue;
- case ' ':
- containsSpace = true;
- break;
- case 't':
- case 'm':
- case 'H':
- case 'h':
- if (shouldEscape)
- {
- continue;
- }
- return index;
- }
- }
- containsSpace = false;
- return index;
- }
-
- // (user can override) first day of week
- internal int FirstDayOfWeek
- {
- get
- {
- if (_iFirstDayOfWeek == undef)
- {
- _iFirstDayOfWeek = GetFirstDayOfWeek();
- }
- return _iFirstDayOfWeek;
- }
- }
-
- // (user can override) first week of year
- internal int CalendarWeekRule
- {
- get
- {
- if (_iFirstWeekOfYear == undef)
- {
- _iFirstWeekOfYear = GetLocaleInfo(LocaleNumberData.FirstWeekOfYear);
- }
- return _iFirstWeekOfYear;
- }
- }
-
- /// <summary>
- /// (user can override default only) short date format
- /// </summary>
- internal string[] ShortDates(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saShortDates;
- }
-
- /// <summary>
- /// (user can override default only) long date format
- /// </summary>
- internal string[] LongDates(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saLongDates;
- }
-
- /// <summary>
- /// (user can override) date year/month format.
- /// </summary>
- internal string[] YearMonths(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saYearMonths;
- }
-
- internal string[] DayNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saDayNames;
- }
-
- internal string[] AbbreviatedDayNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saAbbrevDayNames;
- }
-
- internal string[] SuperShortDayNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saSuperShortDayNames;
- }
-
- internal string[] MonthNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saMonthNames;
- }
-
- internal string[] GenitiveMonthNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saMonthGenitiveNames;
- }
-
- internal string[] AbbreviatedMonthNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saAbbrevMonthNames;
- }
-
- internal string[] AbbreviatedGenitiveMonthNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saAbbrevMonthGenitiveNames;
- }
-
- /// <remarks>>
- /// Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name
- /// the non-leap names skip the 7th name in the normal month name array
- /// </remarks>
- internal string[] LeapYearMonthNames(CalendarId calendarId)
- {
- return GetCalendar(calendarId).saLeapYearMonthNames;
- }
-
- internal string MonthDay(CalendarId calendarId)
- {
- return GetCalendar(calendarId).sMonthDay;
- }
-
- /// <summary>
- /// All available calendar type(s). The first one is the default calendar.
- /// </summary>
- internal CalendarId[] CalendarIds
- {
- get
- {
- if (_waCalendars == null)
- {
- // We pass in an array of ints, and native side fills it up with count calendars.
- // We then have to copy that list to a new array of the right size.
- // Default calendar should be first
- CalendarId[] calendars = new CalendarId[23];
- Debug.Assert(_sWindowsName != null, "[CultureData.CalendarIds] Expected _sWindowsName to be populated by already");
- int count = CalendarData.GetCalendars(_sWindowsName, _bUseOverrides, calendars);
-
- // See if we had a calendar to add.
- if (count == 0)
- {
- // Failed for some reason, just grab Gregorian from Invariant
- _waCalendars = Invariant._waCalendars!;
- }
- else
- {
- // The OS may not return calendar 4 for zh-TW, but we've always allowed it.
- // TODO: Is this hack necessary long-term?
- if (_sWindowsName == "zh-TW")
- {
- bool found = false;
-
- // Do we need to insert calendar 4?
- for (int i = 0; i < count; i++)
- {
- // Stop if we found calendar four
- if (calendars[i] == CalendarId.TAIWAN)
- {
- found = true;
- break;
- }
- }
-
- // If not found then insert it
- if (!found)
- {
- // Insert it as the 2nd calendar
- count++;
- // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added.
- Array.Copy(calendars, 1, calendars, 2, 23 - 1 - 1);
- calendars[1] = CalendarId.TAIWAN;
- }
- }
-
- // It worked, remember the list
- CalendarId[] temp = new CalendarId[count];
- Array.Copy(calendars, temp, count);
-
- // Want 1st calendar to be default
- // Prior to Vista the enumeration didn't have default calendar first
- if (temp.Length > 1)
- {
- CalendarId i = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType);
- if (temp[1] == i)
- {
- temp[1] = temp[0];
- temp[0] = i;
- }
- }
-
- _waCalendars = temp;
- }
- }
-
- return _waCalendars;
- }
- }
-
- /// <summary>
- /// Native calendar names. Index of optional calendar - 1, empty if
- /// no optional calendar at that number
- /// </summary>
- internal string CalendarName(CalendarId calendarId)
- {
- return GetCalendar(calendarId).sNativeName;
- }
-
- internal CalendarData GetCalendar(CalendarId calendarId)
- {
- Debug.Assert(calendarId > 0 && calendarId <= CalendarId.LAST_CALENDAR,
- "[CultureData.GetCalendar] Expect calendarId to be in a valid range");
-
- // arrays are 0 based, calendarIds are 1 based
- int calendarIndex = (int)calendarId - 1;
-
- // Have to have calendars
- _calendars ??= new CalendarData[CalendarData.MAX_CALENDARS];
-
- // we need the following local variable to avoid returning null
- // when another thread creates a new array of CalendarData (above)
- // right after we insert the newly created CalendarData (below)
- CalendarData? calendarData = _calendars[calendarIndex];
- // Make sure that calendar has data
- if (calendarData == null)
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.GetCalendar] Expected _sWindowsName to be populated by already");
- calendarData = new CalendarData(_sWindowsName, calendarId, UseUserOverride);
- _calendars[calendarIndex] = calendarData;
- }
-
- return calendarData;
- }
-
- internal bool IsRightToLeft =>
- // Returns one of the following 4 reading layout values:
- // 0 - Left to right (eg en-US)
- // 1 - Right to left (eg arabic locales)
- // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
- // 3 - Vertical top to bottom with columns proceeding to the right
- ReadingLayout == 1;
-
- /// <summary>
- /// Returns one of the following 4 reading layout values:
- /// 0 - Left to right (eg en-US)
- /// 1 - Right to left (eg arabic locales)
- /// 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
- /// 3 - Vertical top to bottom with columns proceeding to the right
- /// </summary>
- private int ReadingLayout
- {
- get
- {
- if (_iReadingLayout == undef)
- {
- Debug.Assert(_sRealName != null, "[CultureData.IsRightToLeft] Expected _sRealName to be populated by already");
- _iReadingLayout = GetLocaleInfo(LocaleNumberData.ReadingLayout);
- }
-
- return _iReadingLayout;
- }
- }
-
- /// <summary>
- /// // Text info name to use for text information
- /// The TextInfo name never includes that alternate sort and is always specific
- /// For customs, it uses the SortLocale (since the textinfo is not exposed in Win7)
- /// en -> en-US
- /// en-US -> en-US
- /// fj (custom neutral) -> en-US (assuming that en-US is the sort locale for fj)
- /// fj_FJ (custom specific) -> en-US (assuming that en-US is the sort locale for fj-FJ)
- /// es-ES_tradnl -> es-ES
- /// </summary>
- internal string TextInfoName
- {
- get
- {
- // Note: Custom cultures might point at another culture's textinfo, however windows knows how
- // to redirect it to the desired textinfo culture, so this is OK.
- Debug.Assert(_sRealName != null, "[CultureData.TextInfoName] Expected _sRealName to be populated by already");
- return _sRealName;
- }
- }
-
- /// <summary>
- /// Compare info name (including sorting key) to use if custom
- /// </summary>
- internal string SortName
- {
- get
- {
- Debug.Assert(_sRealName != null, "[CultureData.SortName] Expected _sRealName to be populated by already");
- return _sRealName;
- }
- }
-
- internal bool IsSupplementalCustomCulture => IsCustomCultureId(LCID);
-
- /// <summary>
- /// Default ansi code page ID (ACP)
- /// </summary>
- internal int ANSICodePage
- {
- get
- {
- if (_iDefaultAnsiCodePage == undef)
- {
- _iDefaultAnsiCodePage = GetAnsiCodePage(_sRealName!);
- }
- return _iDefaultAnsiCodePage;
- }
- }
-
- /// <summary>
- /// Default oem code page ID (OCP or OEM).
- /// </summary>
- internal int OEMCodePage
- {
- get
- {
- if (_iDefaultOemCodePage == undef)
- {
- _iDefaultOemCodePage = GetOemCodePage(_sRealName!);
- }
- return _iDefaultOemCodePage;
- }
- }
-
- /// <summary>
- /// Default macintosh code page.
- /// </summary>
- internal int MacCodePage
- {
- get
- {
- if (_iDefaultMacCodePage == undef)
- {
- _iDefaultMacCodePage = GetMacCodePage(_sRealName!);
- }
- return _iDefaultMacCodePage;
- }
- }
-
- /// <summary>
- /// Default EBCDIC code page.
- /// </summary>
- internal int EBCDICCodePage
- {
- get
- {
- if (_iDefaultEbcdicCodePage == undef)
- {
- _iDefaultEbcdicCodePage = GetEbcdicCodePage(_sRealName!);
- }
- return _iDefaultEbcdicCodePage;
- }
- }
-
- internal int LCID
- {
- get
- {
- if (_iLanguage == 0)
- {
- Debug.Assert(_sRealName != null, "[CultureData.LCID] Expected this.sRealName to be populated already");
- _iLanguage = LocaleNameToLCID(_sRealName);
- }
- return _iLanguage;
- }
- }
-
- internal bool IsNeutralCulture =>
- // InitCultureData told us if we're neutral or not
- _bNeutral;
-
- internal bool IsInvariantCulture => string.IsNullOrEmpty(Name);
-
- /// <summary>
- /// Get an instance of our default calendar
- /// </summary>
- internal Calendar DefaultCalendar
- {
- get
- {
- if (GlobalizationMode.Invariant)
- {
- return CultureInfo.GetCalendarInstance(CalendarIds[0]);
- }
-
- CalendarId defaultCalId = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType);
-
- if (defaultCalId == 0)
- {
- defaultCalId = CalendarIds[0];
- }
-
- return CultureInfo.GetCalendarInstance(defaultCalId);
- }
- }
-
- /// <summary>
- /// All of our era names
- /// </summary>
- internal string[] EraNames(CalendarId calendarId)
- {
- Debug.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0");
- return GetCalendar(calendarId).saEraNames;
- }
-
- internal string[] AbbrevEraNames(CalendarId calendarId)
- {
- Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
- return GetCalendar(calendarId).saAbbrevEraNames;
- }
-
- internal string[] AbbreviatedEnglishEraNames(CalendarId calendarId)
- {
- Debug.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
- return GetCalendar(calendarId).saAbbrevEnglishEraNames;
- }
-
- /// <summary>
- /// Time separator (derived from time format)
- /// </summary>
- internal string TimeSeparator
- {
- get
- {
- if (_sTimeSeparator == null)
- {
- string? longTimeFormat = GetTimeFormatString();
- if (string.IsNullOrEmpty(longTimeFormat))
- {
- longTimeFormat = LongTimes[0];
- }
-
- // Compute STIME from time format
- _sTimeSeparator = GetTimeSeparator(longTimeFormat);
- }
- return _sTimeSeparator;
- }
- }
-
- /// <summary>
- /// Date separator (derived from short date format)
- /// </summary>
- internal string DateSeparator(CalendarId calendarId)
- {
- if (calendarId == CalendarId.JAPAN && !LocalAppContextSwitches.EnforceLegacyJapaneseDateParsing)
- {
- // The date separator is derived from the default short date pattern. So far this pattern is using
- // '/' as date separator when using the Japanese calendar which make the formatting and parsing work fine.
- // changing the default pattern is likely will happen in the near future which can easily break formatting
- // and parsing.
- // We are forcing here the date separator to '/' to ensure the parsing is not going to break when changing
- // the default short date pattern. The application still can override this in the code by DateTimeFormatInfo.DateSeparartor.
- return "/";
- }
-
- return GetDateSeparator(ShortDates(calendarId)[0]);
- }
-
- /// <summary>
- /// Unescape a NLS style quote string
- ///
- /// This removes single quotes:
- /// 'fred' -> fred
- /// 'fred -> fred
- /// fred' -> fred
- /// fred's -> freds
- ///
- /// This removes the first \ of escaped characters:
- /// fred\'s -> fred's
- /// a\\b -> a\b
- /// a\b -> ab
- ///
- /// We don't build the stringbuilder unless we find a ' or a \. If we find a ' or a \, we
- /// always build a stringbuilder because we need to remove the ' or \.
- /// </summary>
- private static string UnescapeNlsString(string str, int start, int end)
- {
- Debug.Assert(str != null);
- Debug.Assert(start >= 0);
- Debug.Assert(end >= 0);
- StringBuilder? result = null;
-
- for (int i = start; i < str.Length && i <= end; i++)
- {
- switch (str[i])
- {
- case '\'':
- result ??= new StringBuilder(str, start, i - start, str.Length);
- break;
- case '\\':
- result ??= new StringBuilder(str, start, i - start, str.Length);
- ++i;
- if (i < str.Length)
- {
- result.Append(str[i]);
- }
- break;
- default:
- result?.Append(str[i]);
- break;
- }
- }
-
- if (result == null)
- {
- return str.Substring(start, end - start + 1);
- }
-
- return result.ToString();
- }
-
- /// <summary>
- /// Time format separator (ie: : in 12:39:00)
- /// We calculate this from the provided time format
- /// </summary>
- private static string GetTimeSeparator(string format)
- {
- // Find the time separator so that we can pretend we know TimeSeparator.
- return GetSeparator(format, "Hhms");
- }
-
- /// <summary>
- /// Date format separator (ie: / in 9/1/03)
- /// We calculate this from the provided short date
- /// </summary>
- private static string GetDateSeparator(string format)
- {
- // Find the date separator so that we can pretend we know DateSeparator.
- return GetSeparator(format, "dyM");
- }
-
- private static string GetSeparator(string format, string timeParts)
- {
- int index = IndexOfTimePart(format, 0, timeParts);
-
- if (index != -1)
- {
- // Found a time part, find out when it changes
- char cTimePart = format[index];
-
- do
- {
- index++;
- } while (index < format.Length && format[index] == cTimePart);
-
- int separatorStart = index;
-
- // Now we need to find the end of the separator
- if (separatorStart < format.Length)
- {
- int separatorEnd = IndexOfTimePart(format, separatorStart, timeParts);
- if (separatorEnd != -1)
- {
- // From [separatorStart, count) is our string, except we need to unescape
- return UnescapeNlsString(format, separatorStart, separatorEnd - 1);
- }
- }
- }
-
- return string.Empty;
- }
-
- private static int IndexOfTimePart(string format, int startIndex, string timeParts)
- {
- Debug.Assert(startIndex >= 0, "startIndex cannot be negative");
- Debug.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters");
- bool inQuote = false;
- for (int i = startIndex; i < format.Length; ++i)
- {
- // See if we have a time Part
- if (!inQuote && timeParts.Contains(format[i]))
- {
- return i;
- }
- switch (format[i])
- {
- case '\\':
- if (i + 1 < format.Length)
- {
- ++i;
- switch (format[i])
- {
- case '\'':
- case '\\':
- break;
- default:
- --i; // backup since we will move over this next
- break;
- }
- }
- break;
- case '\'':
- inQuote = !inQuote;
- break;
- }
- }
-
- return -1;
- }
-
- internal static bool IsCustomCultureId(int cultureId)
- {
- return cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED;
- }
-
- internal void GetNFIValues(NumberFormatInfo nfi)
- {
- if (GlobalizationMode.Invariant || IsInvariantCulture)
- {
- nfi._positiveSign = _sPositiveSign!;
- nfi._negativeSign = _sNegativeSign!;
-
- nfi._numberGroupSeparator = _sThousandSeparator!;
- nfi._numberDecimalSeparator = _sDecimalSeparator!;
- nfi._numberDecimalDigits = _iDigits;
- nfi._numberNegativePattern = _iNegativeNumber;
-
- nfi._currencySymbol = _sCurrency!;
- nfi._currencyGroupSeparator = _sMonetaryThousand!;
- nfi._currencyDecimalSeparator = _sMonetaryDecimal!;
- nfi._currencyDecimalDigits = _iCurrencyDigits;
- nfi._currencyNegativePattern = _iNegativeCurrency;
- nfi._currencyPositivePattern = _iCurrency;
- }
- else
- {
- Debug.Assert(_sWindowsName != null, "[CultureData.GetNFIValues] Expected _sWindowsName to be populated by already");
- // String values
- nfi._positiveSign = GetLocaleInfo(LocaleStringData.PositiveSign);
- nfi._negativeSign = GetLocaleInfo(LocaleStringData.NegativeSign);
-
- nfi._numberDecimalSeparator = GetLocaleInfo(LocaleStringData.DecimalSeparator);
- nfi._numberGroupSeparator = GetLocaleInfo(LocaleStringData.ThousandSeparator);
- nfi._currencyGroupSeparator = GetLocaleInfo(LocaleStringData.MonetaryThousandSeparator);
- nfi._currencyDecimalSeparator = GetLocaleInfo(LocaleStringData.MonetaryDecimalSeparator);
- nfi._currencySymbol = GetLocaleInfo(LocaleStringData.MonetarySymbol);
-
- // Numeric values
- nfi._numberDecimalDigits = GetLocaleInfo(LocaleNumberData.FractionalDigitsCount);
- nfi._currencyDecimalDigits = GetLocaleInfo(LocaleNumberData.MonetaryFractionalDigitsCount);
- nfi._currencyPositivePattern = GetLocaleInfo(LocaleNumberData.PositiveMonetaryNumberFormat);
- nfi._currencyNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeMonetaryNumberFormat);
- nfi._numberNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeNumberFormat);
-
- // LOCALE_SNATIVEDIGITS (array of 10 single character strings).
- string digits = GetLocaleInfo(LocaleStringData.Digits);
- nfi._nativeDigits = new string[10];
- for (int i = 0; i < nfi._nativeDigits.Length; i++)
- {
- nfi._nativeDigits[i] = char.ToString(digits[i]);
- }
-
- Debug.Assert(_sRealName != null);
- nfi._digitSubstitution = GetDigitSubstitution(_sRealName);
- }
-
- // Gather additional data
- nfi._numberGroupSizes = NumberGroupSizes;
- nfi._currencyGroupSizes = CurrencyGroupSizes;
-
- // prefer the cached value since these do not have user overrides
- nfi._percentNegativePattern = PercentNegativePattern;
- nfi._percentPositivePattern = PercentPositivePattern;
- nfi._percentSymbol = PercentSymbol;
- nfi._perMilleSymbol = PerMilleSymbol;
-
- nfi._negativeInfinitySymbol = NegativeInfinitySymbol;
- nfi._positiveInfinitySymbol = PositiveInfinitySymbol;
- nfi._nanSymbol = NaNSymbol;
-
- // We don't have percent values, so use the number values
- nfi._percentDecimalDigits = nfi._numberDecimalDigits;
- nfi._percentDecimalSeparator = nfi._numberDecimalSeparator;
- nfi._percentGroupSizes = nfi._numberGroupSizes;
- nfi._percentGroupSeparator = nfi._numberGroupSeparator;
-
- // Clean up a few odd values
-
- // Windows usually returns an empty positive sign, but we like it to be "+"
- if (string.IsNullOrEmpty(nfi._positiveSign))
- {
- nfi._positiveSign = "+";
- }
-
- // Special case for Italian. The currency decimal separator in the control panel is the empty string. When the user
- // specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the
- // decimal point doesn't show up. We'll just hack this here because our default currency format will never use nfi.
- if (string.IsNullOrEmpty(nfi._currencyDecimalSeparator))
- {
- nfi._currencyDecimalSeparator = nfi._numberDecimalSeparator;
- }
- }
-
- /// <remarks>
- /// This is ONLY used for caching names and shouldn't be used for anything else
- /// </remarks>
- internal static string AnsiToLower(string testString) => TextInfo.ToLowerAsciiInvariant(testString);
-
- /// <remarks>
- /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation
- /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes.
- /// </remarks>
- private enum LocaleStringData : uint
- {
- /// <summary>localized name of locale, eg "German (Germany)" in UI language (corresponds to LOCALE_SLOCALIZEDDISPLAYNAME)</summary>
- LocalizedDisplayName = 0x00000002,
- /// <summary>Display name (language + country usually) in English, eg "German (Germany)" (corresponds to LOCALE_SENGLISHDISPLAYNAME)</summary>
- EnglishDisplayName = 0x00000072,
- /// <summary>Display name in native locale language, eg "Deutsch (Deutschland) (corresponds to LOCALE_SNATIVEDISPLAYNAME)</summary>
- NativeDisplayName = 0x00000073,
- /// <summary>Language Display Name for a language, eg "German" in UI language (corresponds to LOCALE_SLOCALIZEDLANGUAGENAME)</summary>
- LocalizedLanguageName = 0x0000006f,
- /// <summary>English name of language, eg "German" (corresponds to LOCALE_SENGLISHLANGUAGENAME)</summary>
- EnglishLanguageName = 0x00001001,
- /// <summary>native name of language, eg "Deutsch" (corresponds to LOCALE_SNATIVELANGUAGENAME)</summary>
- NativeLanguageName = 0x00000004,
- /// <summary>localized name of country, eg "Germany" in UI language (corresponds to LOCALE_SLOCALIZEDCOUNTRYNAME)</summary>
- LocalizedCountryName = 0x00000006,
- /// <summary>English name of country, eg "Germany" (corresponds to LOCALE_SENGLISHCOUNTRYNAME)</summary>
- EnglishCountryName = 0x00001002,
- /// <summary>native name of country, eg "Deutschland" (corresponds to LOCALE_SNATIVECOUNTRYNAME)</summary>
- NativeCountryName = 0x00000008,
- /// <summary>abbreviated language name (corresponds to LOCALE_SABBREVLANGNAME)</summary>
- AbbreviatedWindowsLanguageName = 0x00000003,
- /// <summary>list item separator (corresponds to LOCALE_SLIST)</summary>
- ListSeparator = 0x0000000C,
- /// <summary>decimal separator (corresponds to LOCALE_SDECIMAL)</summary>
- DecimalSeparator = 0x0000000E,
- /// <summary>thousand separator (corresponds to LOCALE_STHOUSAND)</summary>
- ThousandSeparator = 0x0000000F,
- /// <summary>digit grouping (corresponds to LOCALE_SGROUPING)</summary>
- Digits = 0x00000013,
- /// <summary>local monetary symbol (corresponds to LOCALE_SCURRENCY)</summary>
- MonetarySymbol = 0x00000014,
- /// <summary>English currency name (corresponds to LOCALE_SENGCURRNAME)</summary>
- CurrencyEnglishName = 0x00001007,
- /// <summary>Native currency name (corresponds to LOCALE_SNATIVECURRNAME)</summary>
- CurrencyNativeName = 0x00001008,
- /// <summary>uintl monetary symbol (corresponds to LOCALE_SINTLSYMBOL)</summary>
- Iso4217MonetarySymbol = 0x00000015,
- /// <summary>monetary decimal separator (corresponds to LOCALE_SMONDECIMALSEP)</summary>
- MonetaryDecimalSeparator = 0x00000016,
- /// <summary>monetary thousand separator (corresponds to LOCALE_SMONTHOUSANDSEP)</summary>
- MonetaryThousandSeparator = 0x00000017,
- /// <summary>AM designator (corresponds to LOCALE_S1159)</summary>
- AMDesignator = 0x00000028,
- /// <summary>PM designator (corresponds to LOCALE_S2359)</summary>
- PMDesignator = 0x00000029,
- /// <summary>positive sign (corresponds to LOCALE_SPOSITIVESIGN)</summary>
- PositiveSign = 0x00000050,
- /// <summary>negative sign (corresponds to LOCALE_SNEGATIVESIGN)</summary>
- NegativeSign = 0x00000051,
- /// <summary>ISO abbreviated language name (corresponds to LOCALE_SISO639LANGNAME)</summary>
- Iso639LanguageTwoLetterName = 0x00000059,
- /// <summary>ISO abbreviated country name (corresponds to LOCALE_SISO639LANGNAME2)</summary>
- Iso639LanguageThreeLetterName = 0x00000067,
- /// <summary>ISO abbreviated language name (corresponds to LOCALE_SISO639LANGNAME)</summary>
- Iso639LanguageName = 0x00000059,
- /// <summary>ISO abbreviated country name (corresponds to LOCALE_SISO3166CTRYNAME)</summary>
- Iso3166CountryName = 0x0000005A,
- /// <summary>3 letter ISO country code (corresponds to LOCALE_SISO3166CTRYNAME2)</summary>
- Iso3166CountryName2 = 0x00000068, // 3 character ISO country name
- /// <summary>Not a Number (corresponds to LOCALE_SNAN)</summary>
- NaNSymbol = 0x00000069,
- /// <summary>+ Infinity (corresponds to LOCALE_SPOSINFINITY)</summary>
- PositiveInfinitySymbol = 0x0000006a,
- /// <summary>- Infinity (corresponds to LOCALE_SNEGINFINITY)</summary>
- NegativeInfinitySymbol = 0x0000006b,
- /// <summary>Fallback name for resources (corresponds to LOCALE_SPARENT)</summary>
- ParentName = 0x0000006d,
- /// <summary>Fallback name for within the console (corresponds to LOCALE_SCONSOLEFALLBACKNAME)</summary>
- ConsoleFallbackName = 0x0000006e,
- /// <summary>Returns the percent symbol (corresponds to LOCALE_SPERCENT)</summary>
- PercentSymbol = 0x00000076,
- /// <summary>Returns the permille (U+2030) symbol (corresponds to LOCALE_SPERMILLE)</summary>
- PerMilleSymbol = 0x00000077
- }
-
- /// <remarks>
- /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation
- /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes.
- /// </remarks>
- private enum LocaleGroupingData : uint
- {
- /// <summary>digit grouping (corresponds to LOCALE_SGROUPING)</summary>
- Digit = 0x00000010,
- /// <summary>monetary grouping (corresponds to LOCALE_SMONGROUPING)</summary>
- Monetary = 0x00000018,
- }
-
- /// <remarks>
- /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation
- /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes.
- /// </remarks>
- private enum LocaleNumberData : uint
- {
- /// <summary>language id (corresponds to LOCALE_ILANGUAGE)</summary>
- LanguageId = 0x00000001,
- /// <summary>geographical location id, (corresponds to LOCALE_IGEOID)</summary>
- GeoId = 0x0000005B,
- /// <summary>0 = context, 1 = none, 2 = national (corresponds to LOCALE_IDIGITSUBSTITUTION)</summary>
- DigitSubstitution = 0x00001014,
- /// <summary>0 = metric, 1 = US (corresponds to LOCALE_IMEASURE)</summary>
- MeasurementSystem = 0x0000000D,
- /// <summary>number of fractional digits (corresponds to LOCALE_IDIGITS)</summary>
- FractionalDigitsCount = 0x00000011,
- /// <summary>negative number mode (corresponds to LOCALE_INEGNUMBER)</summary>
- NegativeNumberFormat = 0x00001010,
- /// <summary># local monetary digits (corresponds to LOCALE_ICURRDIGITS)</summary>
- MonetaryFractionalDigitsCount = 0x00000019,
- /// <summary>positive currency mode (corresponds to LOCALE_ICURRENCY)</summary>
- PositiveMonetaryNumberFormat = 0x0000001B,
- /// <summary>negative currency mode (corresponds to LOCALE_INEGCURR)</summary>
- NegativeMonetaryNumberFormat = 0x0000001C,
- /// <summary>type of calendar specifier (corresponds to LOCALE_ICALENDARTYPE)</summary>
- CalendarType = 0x00001009,
- /// <summary>first day of week specifier (corresponds to LOCALE_IFIRSTDAYOFWEEK)</summary>
- FirstDayOfWeek = 0x0000100C,
- /// <summary>first week of year specifier (corresponds to LOCALE_IFIRSTWEEKOFYEAR)</summary>
- FirstWeekOfYear = 0x0000100D,
- /// <summary>
- /// Returns one of the following 4 reading layout values:
- /// 0 - Left to right (eg en-US)
- /// 1 - Right to left (eg arabic locales)
- /// 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
- /// 3 - Vertical top to bottom with columns proceeding to the right
- /// (corresponds to LOCALE_IREADINGLAYOUT)
- /// </summary>
- ReadingLayout = 0x00000070,
- /// <summary>Returns 0-11 for the negative percent format (corresponds to LOCALE_INEGATIVEPERCENT)</summary>
- NegativePercentFormat = 0x00000074,
- /// <summary>Returns 0-3 for the positive percent format (corresponds to LOCALE_IPOSITIVEPERCENT)</summary>
- PositivePercentFormat = 0x00000075,
- /// <summary>default ansi code page (corresponds to LOCALE_IDEFAULTCODEPAGE)</summary>
- OemCodePage = 0x0000000B,
- /// <summary>default ansi code page (corresponds to LOCALE_IDEFAULTANSICODEPAGE)</summary>
- AnsiCodePage = 0x00001004,
- /// <summary>default mac code page (corresponds to LOCALE_IDEFAULTMACCODEPAGE)</summary>
- MacCodePage = 0x00001011,
- /// <summary>default ebcdic code page (corresponds to LOCALE_IDEFAULTEBCDICCODEPAGE)</summary>
- EbcdicCodePage = 0x00001012,
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Unix.cs
deleted file mode 100644
index 2a16ab6111f..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Unix.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- public partial class CultureInfo : IFormatProvider
- {
- internal static CultureInfo GetUserDefaultCulture()
- {
- if (GlobalizationMode.Invariant)
- return CultureInfo.InvariantCulture;
-
- CultureInfo cultureInfo;
- string? localeName;
- if (CultureData.GetDefaultLocaleName(out localeName))
- {
- Debug.Assert(localeName != null);
- cultureInfo = GetCultureByName(localeName);
- }
- else
- {
- cultureInfo = CultureInfo.InvariantCulture;
- }
-
- return cultureInfo;
- }
-
- private static CultureInfo GetUserDefaultUICulture()
- {
- return InitializeUserDefaultCulture();
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs
deleted file mode 100644
index 1a8e8e81cb5..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public partial class CultureInfo : IFormatProvider
- {
- internal static CultureInfo GetUserDefaultCulture()
- {
- if (GlobalizationMode.Invariant)
- return CultureInfo.InvariantCulture;
-
- string? strDefault = CultureData.GetLocaleInfoEx(Interop.Kernel32.LOCALE_NAME_USER_DEFAULT, Interop.Kernel32.LOCALE_SNAME);
- if (strDefault == null)
- {
- strDefault = CultureData.GetLocaleInfoEx(Interop.Kernel32.LOCALE_NAME_SYSTEM_DEFAULT, Interop.Kernel32.LOCALE_SNAME);
-
- if (strDefault == null)
- {
- // If system default doesn't work, use invariant
- return CultureInfo.InvariantCulture;
- }
- }
-
- return GetCultureByName(strDefault);
- }
-
- private static unsafe CultureInfo GetUserDefaultUICulture()
- {
- if (GlobalizationMode.Invariant)
- return CultureInfo.InvariantCulture;
-
- const uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention
- uint langCount = 0;
- uint bufLen = 0;
-
- if (Interop.Kernel32.GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &langCount, null, &bufLen) != Interop.BOOL.FALSE)
- {
- char[] languages = new char[bufLen];
- fixed (char* pLanguages = languages)
- {
- if (Interop.Kernel32.GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &langCount, pLanguages, &bufLen) != Interop.BOOL.FALSE)
- {
- int index = 0;
- while (languages[index] != (char)0 && index < languages.Length)
- {
- index++;
- }
-
- return GetCultureByName(new string(languages, 0, index));
- }
- }
- }
-
- return InitializeUserDefaultCulture();
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.cs
deleted file mode 100644
index bc276e2bae0..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureInfo.cs
+++ /dev/null
@@ -1,1166 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-// Purpose: This class represents the software preferences of a particular
-// culture or community. It includes information such as the
-// language, writing system, and a calendar used by the culture
-// as well as methods for common operations such as printing
-// dates and sorting strings.
-//
-//
-//
-// !!!! NOTE WHEN CHANGING THIS CLASS !!!!
-//
-// If adding or removing members to this class, please update CultureInfoBaseObject
-// in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be
-// different than the order in which members are declared. For instance, all
-// reference types will come first in the class before value types (like ints, bools, etc)
-// regardless of the order in which they are declared. The best way to see the
-// actual order of the class is to do a !dumpobj on an instance of the managed
-// object inside of the debugger.
-//
-////////////////////////////////////////////////////////////////////////////
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class represents the software preferences of a particular culture
- /// or community. It includes information such as the language, writing
- /// system and a calendar used by the culture as well as methods for
- /// common operations such as printing dates and sorting strings.
- /// </summary>
- /// <remarks>
- /// !!!! NOTE WHEN CHANGING THIS CLASS !!!!
- /// If adding or removing members to this class, please update
- /// CultureInfoBaseObject in ndp/clr/src/vm/object.h. Note, the "actual"
- /// layout of the class may be different than the order in which members
- /// are declared. For instance, all reference types will come first in the
- /// class before value types (like ints, bools, etc) regardless of the
- /// order in which they are declared. The best way to see the actual
- /// order of the class is to do a !dumpobj on an instance of the managed
- /// object inside of the debugger.
- /// </remarks>
- public partial class CultureInfo : IFormatProvider, ICloneable
- {
- // We use an RFC4646 type string to construct CultureInfo.
- // This string is stored in _name and is authoritative.
- // We use the _cultureData to get the data for our object
-
- private bool _isReadOnly;
- private CompareInfo? _compareInfo;
- private TextInfo? _textInfo;
- internal NumberFormatInfo? _numInfo;
- internal DateTimeFormatInfo? _dateTimeInfo;
- private Calendar? _calendar;
- //
- // The CultureData instance that we are going to read data from.
- // For supported culture, this will be the CultureData instance that read data from mscorlib assembly.
- // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
- //
- internal CultureData _cultureData;
-
- internal bool _isInherited;
-
- private CultureInfo? _consoleFallbackCulture;
-
- // Names are confusing. Here are 3 names we have:
- //
- // new CultureInfo() _name _nonSortName _sortName
- // en-US en-US en-US en-US
- // de-de_phoneb de-DE_phoneb de-DE de-DE_phoneb
- // fj-fj (custom) fj-FJ fj-FJ en-US (if specified sort is en-US)
- // en en
- //
- // Note that in Silverlight we ask the OS for the text and sort behavior, so the
- // textinfo and compareinfo names are the same as the name
-
- // This has a de-DE, de-DE_phoneb or fj-FJ style name
- internal string _name;
-
- // This will hold the non sorting name to be returned from CultureInfo.Name property.
- // This has a de-DE style name even for de-DE_phoneb type cultures
- private string? _nonSortName;
-
- // This will hold the sorting name to be returned from CultureInfo.SortName property.
- // This might be completely unrelated to the culture name if a custom culture. Ie en-US for fj-FJ.
- // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
- private string? _sortName;
-
- // Get the current user default culture. This one is almost always used, so we create it by default.
- private static volatile CultureInfo? s_userDefaultCulture;
-
- // The culture used in the user interface. This is mostly used to load correct localized resources.
- private static volatile CultureInfo? s_userDefaultUICulture;
-
- // WARNING: We allow diagnostic tools to directly inspect these three members (s_InvariantCultureInfo, s_DefaultThreadCurrentUICulture and s_DefaultThreadCurrentCulture)
- // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
- // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
- // Get in touch with the diagnostics team if you have questions.
-
- // The Invariant culture;
- private static readonly CultureInfo s_InvariantCultureInfo = new CultureInfo(CultureData.Invariant, isReadOnly: true);
-
- // These are defaults that we use if a thread has not opted into having an explicit culture
- private static volatile CultureInfo? s_DefaultThreadCurrentUICulture;
- private static volatile CultureInfo? s_DefaultThreadCurrentCulture;
-
- [ThreadStatic]
- private static CultureInfo? s_currentThreadCulture;
- [ThreadStatic]
- private static CultureInfo? s_currentThreadUICulture;
-
- private static AsyncLocal<CultureInfo>? s_asyncLocalCurrentCulture;
- private static AsyncLocal<CultureInfo>? s_asyncLocalCurrentUICulture;
-
- private static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs<CultureInfo> args)
- {
- s_currentThreadCulture = args.CurrentValue;
- }
-
- private static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs<CultureInfo> args)
- {
- s_currentThreadUICulture = args.CurrentValue;
- }
-
- private static volatile Dictionary<string, CultureInfo>? s_cachedCulturesByName;
- private static volatile Dictionary<int, CultureInfo>? s_cachedCulturesByLcid;
-
- // The parent culture.
- private CultureInfo? _parent;
-
- // LOCALE constants of interest to us internally and privately for LCID functions
- // (ie: avoid using these and use names if possible)
- internal const int LOCALE_NEUTRAL = 0x0000;
- private const int LOCALE_USER_DEFAULT = 0x0400;
- private const int LOCALE_SYSTEM_DEFAULT = 0x0800;
- internal const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000;
- internal const int LOCALE_CUSTOM_DEFAULT = 0x0c00;
- internal const int LOCALE_INVARIANT = 0x007F;
-
- private static CultureInfo InitializeUserDefaultCulture()
- {
- Interlocked.CompareExchange(ref s_userDefaultCulture, GetUserDefaultCulture(), null);
- return s_userDefaultCulture!;
- }
-
- private static CultureInfo InitializeUserDefaultUICulture()
- {
- Interlocked.CompareExchange(ref s_userDefaultUICulture, GetUserDefaultUICulture(), null);
- return s_userDefaultUICulture!;
- }
-
- public CultureInfo(string name) : this(name, true)
- {
- }
-
- public CultureInfo(string name, bool useUserOverride)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- // Get our data providing record
- CultureData? cultureData = CultureData.GetCultureData(name, useUserOverride);
-
- if (cultureData == null)
- {
- throw new CultureNotFoundException(nameof(name), name, SR.Argument_CultureNotSupported);
- }
-
- _cultureData = cultureData;
- _name = _cultureData.CultureName;
- _isInherited = GetType() != typeof(CultureInfo);
- }
-
- private CultureInfo(CultureData cultureData, bool isReadOnly = false)
- {
- Debug.Assert(cultureData != null);
- _cultureData = cultureData;
- _name = cultureData.CultureName;
- _isInherited = false;
- _isReadOnly = isReadOnly;
- }
-
- private static CultureInfo? CreateCultureInfoNoThrow(string name, bool useUserOverride)
- {
- Debug.Assert(name != null);
- CultureData? cultureData = CultureData.GetCultureData(name, useUserOverride);
- if (cultureData == null)
- {
- return null;
- }
-
- return new CultureInfo(cultureData);
- }
-
- public CultureInfo(int culture) : this(culture, true)
- {
- }
-
- public CultureInfo(int culture, bool useUserOverride)
- {
- // We don't check for other invalid LCIDS here...
- if (culture < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum);
- }
-
- switch (culture)
- {
- case LOCALE_CUSTOM_DEFAULT:
- case LOCALE_SYSTEM_DEFAULT:
- case LOCALE_NEUTRAL:
- case LOCALE_USER_DEFAULT:
- case LOCALE_CUSTOM_UNSPECIFIED:
- // Can't support unknown custom cultures and we do not support neutral or
- // non-custom user locales.
- throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported);
- default:
- // Now see if this LCID is supported in the system default CultureData table.
- _cultureData = CultureData.GetCultureData(culture, useUserOverride);
- break;
- }
- _isInherited = GetType() != typeof(CultureInfo);
- _name = _cultureData.CultureName;
- }
-
- /// <summary>
- /// Constructor called by SQL Server's special munged culture - creates a culture with
- /// a TextInfo and CompareInfo that come from a supplied alternate source. This object
- /// is ALWAYS read-only.
- /// Note that we really cannot use an LCID version of this override as the cached
- /// name we create for it has to include both names, and the logic for this is in
- /// the GetCultureInfo override *only*.
- /// </summary>
- internal CultureInfo(string cultureName, string textAndCompareCultureName)
- {
- if (cultureName == null)
- {
- throw new ArgumentNullException(nameof(cultureName), SR.ArgumentNull_String);
- }
-
- CultureData? cultureData = CultureData.GetCultureData(cultureName, false) ??
- throw new CultureNotFoundException(nameof(cultureName), cultureName, SR.Argument_CultureNotSupported);
-
- _cultureData = cultureData;
-
- _name = _cultureData.CultureName;
-
- CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName);
- _compareInfo = altCulture.CompareInfo;
- _textInfo = altCulture.TextInfo;
- }
-
- /// <summary>
- /// We do this to try to return the system UI language and the default user languages
- /// This method will fallback if this fails (like Invariant)
- /// </summary>
- private static CultureInfo GetCultureByName(string name)
- {
- try
- {
- return new CultureInfo(name)
- {
- _isReadOnly = true
- };
- }
- catch (ArgumentException)
- {
- return InvariantCulture;
- }
- }
-
- /// <summary>
- /// Return a specific culture. A tad irrelevent now since we always
- /// return valid data for neutral locales.
- ///
- /// Note that there's interesting behavior that tries to find a
- /// smaller name, ala RFC4647, if we can't find a bigger name.
- /// That doesn't help with things like "zh" though, so the approach
- /// is of questionable value
- /// </summary>
- public static CultureInfo CreateSpecificCulture(string name)
- {
- CultureInfo? culture;
-
- try
- {
- culture = new CultureInfo(name);
- }
- catch (ArgumentException)
- {
- // When CultureInfo throws this exception, it may be because someone passed the form
- // like "az-az" because it came out of an http accept lang. We should try a little
- // parsing to perhaps fall back to "az" here and use *it* to create the neutral.
- culture = null;
- for (int idx = 0; idx < name.Length; idx++)
- {
- if ('-' == name[idx])
- {
- try
- {
- culture = new CultureInfo(name.Substring(0, idx));
- break;
- }
- catch (ArgumentException)
- {
- // throw the original exception so the name in the string will be right
- throw;
- }
- }
- }
-
- if (culture == null)
- {
- // nothing to save here; throw the original exception
- throw;
- }
- }
-
- // In the most common case, they've given us a specific culture, so we'll just return that.
- if (!culture.IsNeutralCulture)
- {
- return culture;
- }
-
- return new CultureInfo(culture._cultureData.SpecificCultureName);
- }
-
- internal static bool VerifyCultureName(string cultureName, bool throwException)
- {
- // This function is used by ResourceManager.GetResourceFileName().
- // ResourceManager searches for resource using CultureInfo.Name,
- // so we should check against CultureInfo.Name.
- for (int i = 0; i < cultureName.Length; i++)
- {
- char c = cultureName[i];
- // TODO: Names can only be RFC4646 names (ie: a-zA-Z0-9) while this allows any unicode letter/digit
- if (char.IsLetterOrDigit(c) || c == '-' || c == '_')
- {
- continue;
- }
- if (throwException)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidResourceCultureName, cultureName));
- }
- return false;
- }
- return true;
- }
-
- internal static bool VerifyCultureName(CultureInfo culture, bool throwException)
- {
- // If we have an instance of one of our CultureInfos, the user can't have changed the
- // name and we know that all names are valid in files.
- if (!culture._isInherited)
- {
- return true;
- }
-
- return VerifyCultureName(culture.Name, throwException);
- }
-
- /// <summary>
- /// This instance provides methods based on the current user settings.
- /// These settings are volatile and may change over the lifetime of the
- /// thread.
- /// </summary>
- /// <remarks>
- /// We use the following order to return CurrentCulture and CurrentUICulture
- /// o Use WinRT to return the current user profile language
- /// o use current thread culture if the user already set one using CurrentCulture/CurrentUICulture
- /// o use thread culture if the user already set one using DefaultThreadCurrentCulture
- /// or DefaultThreadCurrentUICulture
- /// o Use NLS default user culture
- /// o Use NLS default system culture
- /// o Use Invariant culture
- /// </remarks>
- public static CultureInfo CurrentCulture
- {
- get
- {
- return s_currentThreadCulture ??
- s_DefaultThreadCurrentCulture ??
- s_userDefaultCulture ??
- InitializeUserDefaultCulture();
- }
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- if (s_asyncLocalCurrentCulture == null)
- {
- Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentCulture), null);
- }
- s_asyncLocalCurrentCulture!.Value = value;
- }
- }
-
- public static CultureInfo CurrentUICulture
- {
- get
- {
- return s_currentThreadUICulture ??
- s_DefaultThreadCurrentUICulture ??
- UserDefaultUICulture;
- }
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- CultureInfo.VerifyCultureName(value, true);
-
- if (s_asyncLocalCurrentUICulture == null)
- {
- Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentUICulture), null);
- }
-
- // this one will set s_currentThreadUICulture too
- s_asyncLocalCurrentUICulture!.Value = value;
- }
- }
-
- internal static CultureInfo UserDefaultUICulture => s_userDefaultUICulture ?? InitializeUserDefaultUICulture();
-
- public static CultureInfo InstalledUICulture => s_userDefaultCulture ?? InitializeUserDefaultCulture();
-
- public static CultureInfo? DefaultThreadCurrentCulture
- {
- get => s_DefaultThreadCurrentCulture;
- set =>
- // If you add pre-conditions to this method, check to see if you also need to
- // add them to Thread.CurrentCulture.set.
- s_DefaultThreadCurrentCulture = value;
- }
-
- public static CultureInfo? DefaultThreadCurrentUICulture
- {
- get => s_DefaultThreadCurrentUICulture;
- set
- {
- // If they're trying to use a Culture with a name that we can't use in resource lookup,
- // don't even let them set it on the thread.
-
- // If you add more pre-conditions to this method, check to see if you also need to
- // add them to Thread.CurrentUICulture.set.
-
- if (value != null)
- {
- CultureInfo.VerifyCultureName(value, true);
- }
-
- s_DefaultThreadCurrentUICulture = value;
- }
- }
-
- /// <summary>
- /// This instance provides methods, for example for casing and sorting,
- /// that are independent of the system and current user settings. It
- /// should be used only by processes such as some system services that
- /// require such invariant results (eg. file systems). In general,
- /// the results are not linguistically correct and do not match any
- /// culture info.
- /// </summary>
- public static CultureInfo InvariantCulture
- {
- get
- {
- Debug.Assert(s_InvariantCultureInfo != null);
- return s_InvariantCultureInfo;
- }
- }
-
- /// <summary>
- /// Return the parent CultureInfo for the current instance.
- /// </summary>
- public virtual CultureInfo Parent
- {
- get
- {
- if (_parent == null)
- {
- CultureInfo culture;
- string parentName = _cultureData.ParentName;
-
- if (string.IsNullOrEmpty(parentName))
- {
- culture = InvariantCulture;
- }
- else
- {
- culture = CreateCultureInfoNoThrow(parentName, _cultureData.UseUserOverride) ??
- // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
- // We can't allow ourselves to fail. In case of custom cultures the parent of the
- // current custom culture isn't installed.
- InvariantCulture;
- }
-
- Interlocked.CompareExchange<CultureInfo?>(ref _parent, culture, null);
- }
- return _parent!;
- }
- }
-
- public virtual int LCID => _cultureData.LCID;
-
- public virtual int KeyboardLayoutId => _cultureData.KeyboardLayoutId;
-
- public static CultureInfo[] GetCultures(CultureTypes types)
- {
- // internally we treat UserCustomCultures as Supplementals but v2
- // treats as Supplementals and Replacements
- if ((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture)
- {
- types |= CultureTypes.ReplacementCultures;
- }
- return CultureData.GetCultures(types);
- }
-
- /// <summary>
- /// Returns the full name of the CultureInfo. The name is in format like
- /// "en-US" This version does NOT include sort information in the name.
- /// </summary>
- public virtual string Name => _nonSortName ??= (_cultureData.Name ?? string.Empty);
-
- /// <summary>
- /// This one has the sort information (ie: de-DE_phoneb)
- /// </summary>
- internal string SortName => _sortName ??= _cultureData.SortName;
-
- public string IetfLanguageTag =>
- // special case the compatibility cultures
- Name switch
- {
- "zh-CHT" => "zh-Hant",
- "zh-CHS" => "zh-Hans",
- _ => Name,
- };
-
- /// <summary>
- /// Returns the full name of the CultureInfo in the localized language.
- /// For example, if the localized language of the runtime is Spanish and the CultureInfo is
- /// US English, "Ingles (Estados Unidos)" will be returned.
- /// </summary>
- public virtual string DisplayName
- {
- get
- {
- Debug.Assert(_name != null, "[CultureInfo.DisplayName] Always expect _name to be set");
- return _cultureData.DisplayName;
- }
- }
-
- /// <summary>
- /// Returns the full name of the CultureInfo in the native language.
- /// For example, if the CultureInfo is US English, "English
- /// (United States)" will be returned.
- /// </summary>
- public virtual string NativeName => _cultureData.NativeName;
-
- /// <summary>
- /// Returns the full name of the CultureInfo in English.
- /// For example, if the CultureInfo is US English, "English
- /// (United States)" will be returned.
- /// </summary>
- public virtual string EnglishName => _cultureData.EnglishName;
-
- /// <summary>
- /// ie: en
- /// </summary>
- public virtual string TwoLetterISOLanguageName => _cultureData.TwoLetterISOLanguageName;
-
- /// <summary>
- /// ie: eng
- /// </summary>
- public virtual string ThreeLetterISOLanguageName => _cultureData.ThreeLetterISOLanguageName;
-
- /// <summary>
- /// Returns the 3 letter windows language name for the current instance. eg: "ENU"
- /// The ISO names are much preferred
- /// </summary>
- public virtual string ThreeLetterWindowsLanguageName => _cultureData.ThreeLetterWindowsLanguageName;
-
- /// <summary>
- /// Gets the CompareInfo for this culture.
- /// </summary>
- public virtual CompareInfo CompareInfo => _compareInfo ??=
- // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from
- // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
- (UseUserOverride ? GetCultureInfo(_name).CompareInfo : new CompareInfo(this));
-
- /// <summary>
- /// Gets the TextInfo for this culture.
- /// </summary>
- public virtual TextInfo TextInfo
- {
- get
- {
- if (_textInfo == null)
- {
- // Make a new textInfo
- TextInfo tempTextInfo = new TextInfo(_cultureData);
- tempTextInfo.SetReadOnlyState(_isReadOnly);
- _textInfo = tempTextInfo;
- }
- return _textInfo;
- }
- }
-
- public override bool Equals(object? value)
- {
- if (object.ReferenceEquals(this, value))
- {
- return true;
- }
-
- if (value is CultureInfo that)
- {
- // using CompareInfo to verify the data passed through the constructor
- // CultureInfo(String cultureName, String textAndCompareCultureName)
- return Name.Equals(that.Name) && CompareInfo.Equals(that.CompareInfo);
- }
-
- return false;
- }
-
- public override int GetHashCode()
- {
- return Name.GetHashCode() + CompareInfo.GetHashCode();
- }
-
- /// <summary>
- /// Implements object.ToString(). Returns the name of the CultureInfo,
- /// eg. "de-DE_phoneb", "en-US", or "fj-FJ".
- /// </summary>
- public override string ToString() => _name;
-
- public virtual object? GetFormat(Type? formatType)
- {
- if (formatType == typeof(NumberFormatInfo))
- {
- return NumberFormat;
- }
- if (formatType == typeof(DateTimeFormatInfo))
- {
- return DateTimeFormat;
- }
-
- return null;
- }
-
- public virtual bool IsNeutralCulture => _cultureData.IsNeutralCulture;
-
- public CultureTypes CultureTypes
- {
- get
- {
- CultureTypes types = _cultureData.IsNeutralCulture ?
- CultureTypes.NeutralCultures :
- CultureTypes.SpecificCultures;
-
- if (_cultureData.IsWin32Installed)
- {
- types |= CultureTypes.InstalledWin32Cultures;
- }
-
- if (_cultureData.IsSupplementalCustomCulture)
- {
- types |= CultureTypes.UserCustomCulture;
- }
-
- if (_cultureData.IsReplacementCulture)
- {
- types |= CultureTypes.ReplacementCultures;
- }
-
- return types;
- }
- }
-
- public virtual NumberFormatInfo NumberFormat
- {
- get
- {
- if (_numInfo == null)
- {
- NumberFormatInfo temp = new NumberFormatInfo(_cultureData);
- temp._isReadOnly = _isReadOnly;
- Interlocked.CompareExchange(ref _numInfo, temp, null);
- }
- return _numInfo!;
- }
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _numInfo = value;
- }
- }
-
- /// <summary>
- /// Create a DateTimeFormatInfo, and fill in the properties according to
- /// the CultureID.
- /// </summary>
- public virtual DateTimeFormatInfo DateTimeFormat
- {
- get
- {
- if (_dateTimeInfo == null)
- {
- // Change the calendar of DTFI to the specified calendar of this CultureInfo.
- DateTimeFormatInfo temp = new DateTimeFormatInfo(_cultureData, this.Calendar);
- temp._isReadOnly = _isReadOnly;
- Interlocked.CompareExchange(ref _dateTimeInfo, temp, null);
- }
- return _dateTimeInfo!;
- }
-
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _dateTimeInfo = value;
- }
- }
-
- public void ClearCachedData()
- {
- // reset the default culture values
- s_userDefaultCulture = GetUserDefaultCulture();
- s_userDefaultUICulture = GetUserDefaultUICulture();
-
- RegionInfo.s_currentRegionInfo = null;
-#pragma warning disable 0618 // disable the obsolete warning
- TimeZone.ResetTimeZone();
-#pragma warning restore 0618
- TimeZoneInfo.ClearCachedData();
- s_cachedCulturesByLcid = null;
- s_cachedCulturesByName = null;
-
- CultureData.ClearCachedData();
- }
-
- /// <summary>
- /// Map a Win32 CALID to an instance of supported calendar.
- /// </summary>
- /// <remarks>
- /// Shouldn't throw exception since the calType value is from our data
- /// table or from Win32 registry.
- /// If we are in trouble (like getting a weird value from Win32
- /// registry), just return the GregorianCalendar.
- /// </remarks>
- internal static Calendar GetCalendarInstance(CalendarId calType)
- {
- if (calType == CalendarId.GREGORIAN)
- {
- return new GregorianCalendar();
- }
-
- return GetCalendarInstanceRare(calType);
- }
-
- /// <summary>
- /// This function exists as a shortcut to prevent us from loading all of the non-gregorian
- /// calendars unless they're required.
- /// </summary>
- internal static Calendar GetCalendarInstanceRare(CalendarId calType)
- {
- Debug.Assert(calType != CalendarId.GREGORIAN, "calType!=CalendarId.GREGORIAN");
-
- switch (calType)
- {
- case CalendarId.GREGORIAN_US: // Gregorian (U.S.) calendar
- case CalendarId.GREGORIAN_ME_FRENCH: // Gregorian Middle East French calendar
- case CalendarId.GREGORIAN_ARABIC: // Gregorian Arabic calendar
- case CalendarId.GREGORIAN_XLIT_ENGLISH: // Gregorian Transliterated English calendar
- case CalendarId.GREGORIAN_XLIT_FRENCH: // Gregorian Transliterated French calendar
- return new GregorianCalendar((GregorianCalendarTypes)calType);
- case CalendarId.TAIWAN: // Taiwan Era calendar
- return new TaiwanCalendar();
- case CalendarId.JAPAN: // Japanese Emperor Era calendar
- return new JapaneseCalendar();
- case CalendarId.KOREA: // Korean Tangun Era calendar
- return new KoreanCalendar();
- case CalendarId.THAI: // Thai calendar
- return new ThaiBuddhistCalendar();
- case CalendarId.HIJRI: // Hijri (Arabic Lunar) calendar
- return new HijriCalendar();
- case CalendarId.HEBREW: // Hebrew (Lunar) calendar
- return new HebrewCalendar();
- case CalendarId.UMALQURA:
- return new UmAlQuraCalendar();
- case CalendarId.PERSIAN:
- return new PersianCalendar();
- }
- return new GregorianCalendar();
- }
-
- /// <summary>
- /// Return/set the default calendar used by this culture.
- /// This value can be overridden by regional option if this is a current culture.
- /// </summary>
- public virtual Calendar Calendar
- {
- get
- {
- if (_calendar == null)
- {
- Debug.Assert(_cultureData.CalendarIds.Length > 0, "_cultureData.CalendarIds.Length > 0");
- // Get the default calendar for this culture. Note that the value can be
- // from registry if this is a user default culture.
- Calendar newObj = _cultureData.DefaultCalendar;
-
- Interlocked.MemoryBarrier();
- newObj.SetReadOnlyState(_isReadOnly);
- _calendar = newObj;
- }
- return _calendar;
- }
- }
-
- /// <summary>
- /// Return an array of the optional calendar for this culture.
- /// </summary>
- public virtual Calendar[] OptionalCalendars
- {
- get
- {
- // This property always returns a new copy of the calendar array.
- CalendarId[] calID = _cultureData.CalendarIds;
- Calendar[] cals = new Calendar[calID.Length];
- for (int i = 0; i < cals.Length; i++)
- {
- cals[i] = GetCalendarInstance(calID[i]);
- }
- return cals;
- }
- }
-
- public bool UseUserOverride => _cultureData.UseUserOverride;
-
- public CultureInfo GetConsoleFallbackUICulture()
- {
- CultureInfo? temp = _consoleFallbackCulture;
- if (temp == null)
- {
- temp = CreateSpecificCulture(_cultureData.SCONSOLEFALLBACKNAME);
- temp._isReadOnly = true;
- _consoleFallbackCulture = temp;
- }
- return temp;
- }
-
- public virtual object Clone()
- {
- CultureInfo ci = (CultureInfo)MemberwiseClone();
- ci._isReadOnly = false;
-
- // If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
- // they've already been allocated. If this is a derived type, we'll take a more generic codepath.
- if (!_isInherited)
- {
- if (_dateTimeInfo != null)
- {
- ci._dateTimeInfo = (DateTimeFormatInfo)_dateTimeInfo.Clone();
- }
- if (_numInfo != null)
- {
- ci._numInfo = (NumberFormatInfo)_numInfo.Clone();
- }
- }
- else
- {
- ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone();
- ci.NumberFormat = (NumberFormatInfo)this.NumberFormat.Clone();
- }
-
- if (_textInfo != null)
- {
- ci._textInfo = (TextInfo)_textInfo.Clone();
- }
-
- if (_dateTimeInfo != null && _dateTimeInfo.Calendar == _calendar)
- {
- // Usually when we access CultureInfo.DateTimeFormat first time, we create the DateTimeFormatInfo object
- // using CultureInfo.Calendar. i.e. CultureInfo.DateTimeInfo.Calendar == CultureInfo.calendar.
- // When cloning CultureInfo, if we know it's still the case that CultureInfo.DateTimeInfo.Calendar == CultureInfo.calendar
- // then we can keep the same behavior for the cloned object and no need to create another calendar object.
- ci._calendar = ci.DateTimeFormat.Calendar;
- }
- else if (_calendar != null)
- {
- ci._calendar = (Calendar)_calendar.Clone();
- }
-
- return ci;
- }
-
- public static CultureInfo ReadOnly(CultureInfo ci)
- {
- if (ci == null)
- {
- throw new ArgumentNullException(nameof(ci));
- }
-
- if (ci.IsReadOnly)
- {
- return ci;
- }
- CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone());
-
- if (!ci.IsNeutralCulture)
- {
- // If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
- // they've already been allocated. If this is a derived type, we'll take a more generic codepath.
- if (!ci._isInherited)
- {
- if (ci._dateTimeInfo != null)
- {
- newInfo._dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci._dateTimeInfo);
- }
- if (ci._numInfo != null)
- {
- newInfo._numInfo = NumberFormatInfo.ReadOnly(ci._numInfo);
- }
- }
- else
- {
- newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat);
- newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat);
- }
- }
-
- if (ci._textInfo != null)
- {
- newInfo._textInfo = TextInfo.ReadOnly(ci._textInfo);
- }
-
- if (ci._calendar != null)
- {
- newInfo._calendar = Calendar.ReadOnly(ci._calendar);
- }
-
- // Don't set the read-only flag too early.
- // We should set the read-only flag here. Otherwise, info.DateTimeFormat will not be able to set.
- newInfo._isReadOnly = true;
-
- return newInfo;
- }
-
- public bool IsReadOnly => _isReadOnly;
-
- private void VerifyWritable()
- {
- if (_isReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- }
-
- /// <summary>
- /// For resource lookup, we consider a culture the invariant culture by name equality.
- /// We perform this check frequently during resource lookup, so adding a property for
- /// improved readability.
- /// </summary>
- internal bool HasInvariantCultureName => Name == InvariantCulture.Name;
-
- /// <summary>
- /// Gets a cached copy of the specified culture from an internal
- /// hashtable (or creates it if not found). (LCID version)
- /// </summary>
- public static CultureInfo GetCultureInfo(int culture)
- {
- if (culture <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(culture), SR.ArgumentOutOfRange_NeedPosNum);
- }
-
- Dictionary<int, CultureInfo> lcidTable = CachedCulturesByLcid;
- CultureInfo? result;
-
- lock (lcidTable)
- {
- if (lcidTable.TryGetValue(culture, out result))
- {
- return result;
- }
- }
-
- try
- {
- result = new CultureInfo(culture, useUserOverride: false) { _isReadOnly = true };
- }
- catch (ArgumentException)
- {
- throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported);
- }
-
- lock (lcidTable)
- {
- lcidTable[culture] = result;
- }
-
- return result;
- }
-
- /// <summary>
- /// Gets a cached copy of the specified culture from an internal
- /// hashtable (or creates it if not found). (Named version)
- /// </summary>
- public static CultureInfo GetCultureInfo(string name)
- {
- // Make sure we have a valid, non-zero length string as name
- if (name is null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- name = CultureData.AnsiToLower(name);
- Dictionary<string, CultureInfo> nameTable = CachedCulturesByName;
- CultureInfo? result;
-
- lock (nameTable)
- {
- if (nameTable.TryGetValue(name, out result))
- {
- return result;
- }
- }
-
- result = CreateCultureInfoNoThrow(name, useUserOverride: false) ??
- throw new CultureNotFoundException(nameof(name), name, SR.Argument_CultureNotSupported);
- result._isReadOnly = true;
-
- // Remember our name as constructed. Do NOT use alternate sort name versions because
- // we have internal state representing the sort (so someone would get the wrong cached version).
- name = CultureData.AnsiToLower(result._name);
-
- lock (nameTable)
- {
- nameTable[name] = result;
- }
-
- return result;
- }
-
- /// <summary>
- /// Gets a cached copy of the specified culture from an internal
- /// hashtable (or creates it if not found).
- /// </summary>
- public static CultureInfo GetCultureInfo(string name, string altName)
- {
- if (name is null)
- {
- throw new ArgumentNullException(nameof(name));
- }
- if (altName is null)
- {
- throw new ArgumentNullException(nameof(altName));
- }
-
- name = CultureData.AnsiToLower(name);
- altName = CultureData.AnsiToLower(altName);
- string nameAndAltName = name + "\xfffd" + altName;
- Dictionary<string, CultureInfo> nameTable = CachedCulturesByName;
- CultureInfo? result;
-
- lock (nameTable)
- {
- if (nameTable.TryGetValue(nameAndAltName, out result))
- {
- return result;
- }
- }
-
- try
- {
- result = new CultureInfo(name, altName) { _isReadOnly = true };
- result.TextInfo.SetReadOnlyState(readOnly: true); // TextInfo object is already created; we need to set it as read only.
- }
- catch (ArgumentException)
- {
- throw new CultureNotFoundException("name/altName", SR.Format(SR.Argument_OneOfCulturesNotSupported, name, altName));
- }
-
- lock (nameTable)
- {
- nameTable[nameAndAltName] = result;
- }
-
- return result;
- }
-
- private static Dictionary<string, CultureInfo> CachedCulturesByName
- {
- get
- {
- Dictionary<string, CultureInfo>? cache = s_cachedCulturesByName;
- if (cache is null)
- {
- cache = new Dictionary<string, CultureInfo>();
- cache = Interlocked.CompareExchange(ref s_cachedCulturesByName, cache, null) ?? cache;
- }
-
- return cache;
- }
- }
-
- private static Dictionary<int, CultureInfo> CachedCulturesByLcid
- {
- get
- {
- Dictionary<int, CultureInfo>? cache = s_cachedCulturesByLcid;
- if (cache is null)
- {
- cache = new Dictionary<int, CultureInfo>();
- cache = Interlocked.CompareExchange(ref s_cachedCulturesByLcid, cache, null) ?? cache;
- }
-
- return cache;
- }
- }
-
- public static CultureInfo GetCultureInfoByIetfLanguageTag(string name)
- {
- // Disallow old zh-CHT/zh-CHS names
- if (name == "zh-CHT" || name == "zh-CHS")
- {
- throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name));
- }
-
- CultureInfo ci = GetCultureInfo(name);
-
- // Disallow alt sorts and es-es_TS
- if (ci.LCID > 0xffff || ci.LCID == 0x040a)
- {
- throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_CultureIetfNotSupported, name));
- }
-
- return ci;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
deleted file mode 100644
index 5869b6ae51d..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.Serialization;
-
-namespace System.Globalization
-{
- [Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public class CultureNotFoundException : ArgumentException
- {
- private readonly string? _invalidCultureName; // unrecognized culture name
- private readonly int? _invalidCultureId; // unrecognized culture Lcid
-
- public CultureNotFoundException()
- : base(DefaultMessage)
- {
- }
-
- public CultureNotFoundException(string? message)
- : base(message)
- {
- }
-
- public CultureNotFoundException(string? paramName, string? message)
- : base(message, paramName)
- {
- }
-
- public CultureNotFoundException(string? message, Exception? innerException)
- : base(message, innerException)
- {
- }
-
- public CultureNotFoundException(string? paramName, string? invalidCultureName, string? message)
- : base(message, paramName)
- {
- _invalidCultureName = invalidCultureName;
- }
-
- public CultureNotFoundException(string? message, string? invalidCultureName, Exception? innerException)
- : base(message, innerException)
- {
- _invalidCultureName = invalidCultureName;
- }
-
- public CultureNotFoundException(string? message, int invalidCultureId, Exception? innerException)
- : base(message, innerException)
- {
- _invalidCultureId = invalidCultureId;
- }
-
- public CultureNotFoundException(string? paramName, int invalidCultureId, string? message)
- : base(message, paramName)
- {
- _invalidCultureId = invalidCultureId;
- }
-
- protected CultureNotFoundException(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- _invalidCultureId = (int?)info.GetValue("InvalidCultureId", typeof(int?));
- _invalidCultureName = (string?)info.GetValue("InvalidCultureName", typeof(string));
- }
-
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("InvalidCultureId", _invalidCultureId, typeof(int?));
- info.AddValue("InvalidCultureName", _invalidCultureName, typeof(string));
- }
-
- public virtual int? InvalidCultureId => _invalidCultureId;
-
- public virtual string? InvalidCultureName => _invalidCultureName;
-
- private static string DefaultMessage => SR.Argument_CultureNotSupported;
-
- private string? FormattedInvalidCultureId =>
- InvalidCultureId != null ?
- string.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) :
- InvalidCultureName;
-
- public override string Message
- {
- get
- {
- string s = base.Message;
- if (_invalidCultureId != null || _invalidCultureName != null)
- {
- string valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormattedInvalidCultureId);
- if (s == null)
- {
- return valueMessage;
- }
-
- return s + Environment.NewLineConst + valueMessage;
- }
- return s;
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureTypes.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/CultureTypes.cs
deleted file mode 100644
index f780b1ce57c..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/CultureTypes.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// The enumeration constants used in CultureInfo.GetCultures().
-// On Linux platforms, the only enum values used there is NeutralCultures and SpecificCultures
-// the rest are obsolete or not valid on Linux
-
-namespace System.Globalization
-{
- [Flags]
- public enum CultureTypes
- {
- NeutralCultures = 0x0001, // Neutral cultures are cultures like "en", "de", "zh", etc, for enumeration this includes ALL neutrals regardless of other flags
- SpecificCultures = 0x0002, // Non-netural cultuers. Examples are "en-us", "zh-tw", etc., for enumeration this includes ALL specifics regardless of other flags
- InstalledWin32Cultures = 0x0004, // Win32 installed cultures in the system and exists in the framework too., this is effectively all cultures
-
- AllCultures = NeutralCultures | SpecificCultures | InstalledWin32Cultures,
-
- UserCustomCulture = 0x0008, // User defined custom culture
- ReplacementCultures = 0x0010, // User defined replacement custom culture.
- [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")]
- WindowsOnlyCultures = 0x0020, // this will always return empty list.
- [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")]
- FrameworkCultures = 0x0040, // will return only the v2 cultures marked as Framework culture.
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
deleted file mode 100644
index 8f8944bba2f..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
+++ /dev/null
@@ -1,1380 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-
-namespace System
-{
- /*
- Customized format patterns:
- P.S. Format in the table below is the internal number format used to display the pattern.
-
- Patterns Format Description Example
- ========= ========== ===================================== ========
- "h" "0" hour (12-hour clock)w/o leading zero 3
- "hh" "00" hour (12-hour clock)with leading zero 03
- "hh*" "00" hour (12-hour clock)with leading zero 03
-
- "H" "0" hour (24-hour clock)w/o leading zero 8
- "HH" "00" hour (24-hour clock)with leading zero 08
- "HH*" "00" hour (24-hour clock) 08
-
- "m" "0" minute w/o leading zero
- "mm" "00" minute with leading zero
- "mm*" "00" minute with leading zero
-
- "s" "0" second w/o leading zero
- "ss" "00" second with leading zero
- "ss*" "00" second with leading zero
-
- "f" "0" second fraction (1 digit)
- "ff" "00" second fraction (2 digit)
- "fff" "000" second fraction (3 digit)
- "ffff" "0000" second fraction (4 digit)
- "fffff" "00000" second fraction (5 digit)
- "ffffff" "000000" second fraction (6 digit)
- "fffffff" "0000000" second fraction (7 digit)
-
- "F" "0" second fraction (up to 1 digit)
- "FF" "00" second fraction (up to 2 digit)
- "FFF" "000" second fraction (up to 3 digit)
- "FFFF" "0000" second fraction (up to 4 digit)
- "FFFFF" "00000" second fraction (up to 5 digit)
- "FFFFFF" "000000" second fraction (up to 6 digit)
- "FFFFFFF" "0000000" second fraction (up to 7 digit)
-
- "t" first character of AM/PM designator A
- "tt" AM/PM designator AM
- "tt*" AM/PM designator PM
-
- "d" "0" day w/o leading zero 1
- "dd" "00" day with leading zero 01
- "ddd" short weekday name (abbreviation) Mon
- "dddd" full weekday name Monday
- "dddd*" full weekday name Monday
-
-
- "M" "0" month w/o leading zero 2
- "MM" "00" month with leading zero 02
- "MMM" short month name (abbreviation) Feb
- "MMMM" full month name Febuary
- "MMMM*" full month name Febuary
-
- "y" "0" two digit year (year % 100) w/o leading zero 0
- "yy" "00" two digit year (year % 100) with leading zero 00
- "yyy" "D3" year 2000
- "yyyy" "D4" year 2000
- "yyyyy" "D5" year 2000
- ...
-
- "z" "+0;-0" timezone offset w/o leading zero -8
- "zz" "+00;-00" timezone offset with leading zero -08
- "zzz" "+00;-00" for hour offset, "00" for minute offset full timezone offset -07:30
- "zzz*" "+00;-00" for hour offset, "00" for minute offset full timezone offset -08:00
-
- "K" -Local "zzz", e.g. -08:00
- -Utc "'Z'", representing UTC
- -Unspecified ""
- -DateTimeOffset "zzzzz" e.g -07:30:15
-
- "g*" the current era name A.D.
-
- ":" time separator : -- DEPRECATED - Insert separator directly into pattern (eg: "H.mm.ss")
- "/" date separator /-- DEPRECATED - Insert separator directly into pattern (eg: "M-dd-yyyy")
- "'" quoted string 'ABC' will insert ABC into the formatted string.
- '"' quoted string "ABC" will insert ABC into the formatted string.
- "%" used to quote a single pattern characters E.g.The format character "%y" is to print two digit year.
- "\" escaped character E.g. '\d' insert the character 'd' into the format string.
- other characters insert the character into the format string.
-
- Pre-defined format characters:
- (U) to indicate Universal time is used.
- (G) to indicate Gregorian calendar is used.
-
- Format Description Real format Example
- ========= ================================= ====================== =======================
- "d" short date culture-specific 10/31/1999
- "D" long data culture-specific Sunday, October 31, 1999
- "f" full date (long date + short time) culture-specific Sunday, October 31, 1999 2:00 AM
- "F" full date (long date + long time) culture-specific Sunday, October 31, 1999 2:00:00 AM
- "g" general date (short date + short time) culture-specific 10/31/1999 2:00 AM
- "G" general date (short date + long time) culture-specific 10/31/1999 2:00:00 AM
- "m"/"M" Month/Day date culture-specific October 31
-(G) "o"/"O" Round Trip XML "yyyy-MM-ddTHH:mm:ss.fffffffK" 1999-10-31 02:00:00.0000000Z
-(G) "r"/"R" RFC 1123 date, "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'" Sun, 31 Oct 1999 10:00:00 GMT
-(G) "s" Sortable format, based on ISO 8601. "yyyy-MM-dd'T'HH:mm:ss" 1999-10-31T02:00:00
- ('T' for local time)
- "t" short time culture-specific 2:00 AM
- "T" long time culture-specific 2:00:00 AM
-(G) "u" Universal time with sortable format, "yyyy'-'MM'-'dd HH':'mm':'ss'Z'" 1999-10-31 10:00:00Z
- based on ISO 8601.
-(U) "U" Universal time with full culture-specific Sunday, October 31, 1999 10:00:00 AM
- (long date + long time) format
- "y"/"Y" Year/Month day culture-specific October, 1999
-
- */
-
- // This class contains only static members and does not require the serializable attribute.
- internal static
- class DateTimeFormat
- {
- internal const int MaxSecondsFractionDigits = 7;
- internal static readonly TimeSpan NullOffset = TimeSpan.MinValue;
-
- internal static char[] allStandardFormats =
- {
- 'd', 'D', 'f', 'F', 'g', 'G',
- 'm', 'M', 'o', 'O', 'r', 'R',
- 's', 't', 'T', 'u', 'U', 'y', 'Y',
- };
-
- internal const string RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
- internal const string RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
-
- private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
-
- internal static readonly DateTimeFormatInfo InvariantFormatInfo = CultureInfo.InvariantCulture.DateTimeFormat;
- internal static readonly string[] InvariantAbbreviatedMonthNames = InvariantFormatInfo.AbbreviatedMonthNames;
- internal static readonly string[] InvariantAbbreviatedDayNames = InvariantFormatInfo.AbbreviatedDayNames;
- internal const string Gmt = "GMT";
-
- internal static string[] fixedNumberFormats = new string[] {
- "0",
- "00",
- "000",
- "0000",
- "00000",
- "000000",
- "0000000",
- };
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Format the positive integer value to a string and prefix with assigned
- // length of leading zero.
- //
- // Parameters:
- // value: The value to format
- // len: The maximum length for leading zero.
- // If the digits of the value is greater than len, no leading zero is added.
- //
- // Notes:
- // The function can format to int.MaxValue.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static void FormatDigits(StringBuilder outputBuffer, int value, int len)
- {
- Debug.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0");
- FormatDigits(outputBuffer, value, len, false);
- }
-
- internal static unsafe void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit)
- {
- Debug.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0");
-
- // Limit the use of this function to be two-digits, so that we have the same behavior
- // as RTM bits.
- if (!overrideLengthLimit && len > 2)
- {
- len = 2;
- }
-
- char* buffer = stackalloc char[16];
- char* p = buffer + 16;
- int n = value;
- do
- {
- *--p = (char)(n % 10 + '0');
- n /= 10;
- } while ((n != 0) && (p > buffer));
-
- int digits = (int)(buffer + 16 - p);
-
- // If the repeat count is greater than 0, we're trying
- // to emulate the "00" format, so we have to prepend
- // a zero if the string only has one character.
- while ((digits < len) && (p > buffer))
- {
- *--p = '0';
- digits++;
- }
- outputBuffer.Append(p, digits);
- }
-
- private static void HebrewFormatDigits(StringBuilder outputBuffer, int digits)
- {
- HebrewNumber.Append(outputBuffer, digits);
- }
-
- internal static int ParseRepeatPattern(ReadOnlySpan<char> format, int pos, char patternChar)
- {
- int len = format.Length;
- int index = pos + 1;
- while ((index < len) && (format[index] == patternChar))
- {
- index++;
- }
- return index - pos;
- }
-
- private static string FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi)
- {
- Debug.Assert(dayOfWeek >= 0 && dayOfWeek <= 6, "dayOfWeek >= 0 && dayOfWeek <= 6");
- if (repeat == 3)
- {
- return dtfi.GetAbbreviatedDayName((DayOfWeek)dayOfWeek);
- }
- // Call dtfi.GetDayName() here, instead of accessing DayNames property, because we don't
- // want a clone of DayNames, which will hurt perf.
- return dtfi.GetDayName((DayOfWeek)dayOfWeek);
- }
-
- private static string FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi)
- {
- Debug.Assert(month >= 1 && month <= 12, "month >=1 && month <= 12");
- if (repeatCount == 3)
- {
- return dtfi.GetAbbreviatedMonthName(month);
- }
- // Call GetMonthName() here, instead of accessing MonthNames property, because we don't
- // want a clone of MonthNames, which will hurt perf.
- return dtfi.GetMonthName(month);
- }
-
- //
- // FormatHebrewMonthName
- //
- // Action: Return the Hebrew month name for the specified DateTime.
- // Returns: The month name string for the specified DateTime.
- // Arguments:
- // time the time to format
- // month The month is the value of HebrewCalendar.GetMonth(time).
- // repeat Return abbreviated month name if repeat=3, or full month name if repeat=4
- // dtfi The DateTimeFormatInfo which uses the Hebrew calendars as its calendar.
- // Exceptions: None.
- //
-
- /* Note:
- If DTFI is using Hebrew calendar, GetMonthName()/GetAbbreviatedMonthName() will return month names like this:
- 1 Hebrew 1st Month
- 2 Hebrew 2nd Month
- .. ...
- 6 Hebrew 6th Month
- 7 Hebrew 6th Month II (used only in a leap year)
- 8 Hebrew 7th Month
- 9 Hebrew 8th Month
- 10 Hebrew 9th Month
- 11 Hebrew 10th Month
- 12 Hebrew 11th Month
- 13 Hebrew 12th Month
-
- Therefore, if we are in a regular year, we have to increment the month name if month is greater or equal to 7.
- */
- private static string FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi)
- {
- Debug.Assert(repeatCount != 3 || repeatCount != 4, "repeateCount should be 3 or 4");
- if (dtfi.Calendar.IsLeapYear(dtfi.Calendar.GetYear(time)))
- {
- // This month is in a leap year
- return dtfi.InternalGetMonthName(month, MonthNameStyles.LeapYear, repeatCount == 3);
- }
- // This is in a regular year.
- if (month >= 7)
- {
- month++;
- }
- if (repeatCount == 3)
- {
- return dtfi.GetAbbreviatedMonthName(month);
- }
- return dtfi.GetMonthName(month);
- }
-
- //
- // The pos should point to a quote character. This method will
- // append to the result StringBuilder the string enclosed by the quote character.
- //
- internal static int ParseQuoteString(ReadOnlySpan<char> format, int pos, StringBuilder result)
- {
- //
- // NOTE : pos will be the index of the quote character in the 'format' string.
- //
- int formatLen = format.Length;
- int beginPos = pos;
- char quoteChar = format[pos++]; // Get the character used to quote the following string.
-
- bool foundQuote = false;
- while (pos < formatLen)
- {
- char ch = format[pos++];
- if (ch == quoteChar)
- {
- foundQuote = true;
- break;
- }
- else if (ch == '\\')
- {
- // The following are used to support escaped character.
- // Escaped character is also supported in the quoted string.
- // Therefore, someone can use a format like "'minute:' mm\"" to display:
- // minute: 45"
- // because the second double quote is escaped.
- if (pos < formatLen)
- {
- result.Append(format[pos++]);
- }
- else
- {
- //
- // This means that '\' is at the end of the formatting string.
- //
- throw new FormatException(SR.Format_InvalidString);
- }
- }
- else
- {
- result.Append(ch);
- }
- }
-
- if (!foundQuote)
- {
- // Here we can't find the matching quote.
- throw new FormatException(SR.Format(SR.Format_BadQuote, quoteChar));
- }
-
- //
- // Return the character count including the begin/end quote characters and enclosed string.
- //
- return pos - beginPos;
- }
-
- //
- // Get the next character at the index of 'pos' in the 'format' string.
- // Return value of -1 means 'pos' is already at the end of the 'format' string.
- // Otherwise, return value is the int value of the next character.
- //
- internal static int ParseNextChar(ReadOnlySpan<char> format, int pos)
- {
- if (pos >= format.Length - 1)
- {
- return -1;
- }
- return (int)format[pos + 1];
- }
-
- //
- // IsUseGenitiveForm
- //
- // Actions: Check the format to see if we should use genitive month in the formatting.
- // Starting at the position (index) in the (format) string, look back and look ahead to
- // see if there is "d" or "dd". In the case like "d MMMM" or "MMMM dd", we can use
- // genitive form. Genitive form is not used if there is more than two "d".
- // Arguments:
- // format The format string to be scanned.
- // index Where we should start the scanning. This is generally where "M" starts.
- // tokenLen The len of the current pattern character. This indicates how many "M" that we have.
- // patternToMatch The pattern that we want to search. This generally uses "d"
- //
- private static bool IsUseGenitiveForm(ReadOnlySpan<char> format, int index, int tokenLen, char patternToMatch)
- {
- int i;
- int repeat = 0;
- //
- // Look back to see if we can find "d" or "ddd"
- //
-
- // Find first "d".
- for (i = index - 1; i >= 0 && format[i] != patternToMatch; i--) { /*Do nothing here */ }
-
- if (i >= 0)
- {
- // Find a "d", so look back to see how many "d" that we can find.
- while (--i >= 0 && format[i] == patternToMatch)
- {
- repeat++;
- }
- //
- // repeat == 0 means that we have one (patternToMatch)
- // repeat == 1 means that we have two (patternToMatch)
- //
- if (repeat <= 1)
- {
- return true;
- }
- // Note that we can't just stop here. We may find "ddd" while looking back, and we have to look
- // ahead to see if there is "d" or "dd".
- }
-
- //
- // If we can't find "d" or "dd" by looking back, try look ahead.
- //
-
- // Find first "d"
- for (i = index + tokenLen; i < format.Length && format[i] != patternToMatch; i++) { /* Do nothing here */ }
-
- if (i < format.Length)
- {
- repeat = 0;
- // Find a "d", so contine the walk to see how may "d" that we can find.
- while (++i < format.Length && format[i] == patternToMatch)
- {
- repeat++;
- }
- //
- // repeat == 0 means that we have one (patternToMatch)
- // repeat == 1 means that we have two (patternToMatch)
- //
- if (repeat <= 1)
- {
- return true;
- }
- }
- return false;
- }
-
- //
- // FormatCustomized
- //
- // Actions: Format the DateTime instance using the specified format.
- //
- private static StringBuilder FormatCustomized(
- DateTime dateTime, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset, StringBuilder? result)
- {
- Calendar cal = dtfi.Calendar;
-
- bool resultBuilderIsPooled = false;
- if (result == null)
- {
- resultBuilderIsPooled = true;
- result = StringBuilderCache.Acquire();
- }
-
- // This is a flag to indicate if we are formatting the dates using Hebrew calendar.
- bool isHebrewCalendar = (cal.ID == CalendarId.HEBREW);
- bool isJapaneseCalendar = (cal.ID == CalendarId.JAPAN);
- // This is a flag to indicate if we are formatting hour/minute/second only.
- bool bTimeOnly = true;
-
- int i = 0;
- int tokenLen, hour12;
-
- while (i < format.Length)
- {
- char ch = format[i];
- int nextChar;
- switch (ch)
- {
- case 'g':
- tokenLen = ParseRepeatPattern(format, i, ch);
- result.Append(dtfi.GetEraName(cal.GetEra(dateTime)));
- break;
- case 'h':
- tokenLen = ParseRepeatPattern(format, i, ch);
- hour12 = dateTime.Hour % 12;
- if (hour12 == 0)
- {
- hour12 = 12;
- }
- FormatDigits(result, hour12, tokenLen);
- break;
- case 'H':
- tokenLen = ParseRepeatPattern(format, i, ch);
- FormatDigits(result, dateTime.Hour, tokenLen);
- break;
- case 'm':
- tokenLen = ParseRepeatPattern(format, i, ch);
- FormatDigits(result, dateTime.Minute, tokenLen);
- break;
- case 's':
- tokenLen = ParseRepeatPattern(format, i, ch);
- FormatDigits(result, dateTime.Second, tokenLen);
- break;
- case 'f':
- case 'F':
- tokenLen = ParseRepeatPattern(format, i, ch);
- if (tokenLen <= MaxSecondsFractionDigits)
- {
- long fraction = (dateTime.Ticks % Calendar.TicksPerSecond);
- fraction /= (long)Math.Pow(10, 7 - tokenLen);
- if (ch == 'f')
- {
- result.AppendSpanFormattable((int)fraction, fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture);
- }
- else
- {
- int effectiveDigits = tokenLen;
- while (effectiveDigits > 0)
- {
- if (fraction % 10 == 0)
- {
- fraction /= 10;
- effectiveDigits--;
- }
- else
- {
- break;
- }
- }
- if (effectiveDigits > 0)
- {
- result.AppendSpanFormattable((int)fraction, fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture);
- }
- else
- {
- // No fraction to emit, so see if we should remove decimal also.
- if (result.Length > 0 && result[result.Length - 1] == '.')
- {
- result.Remove(result.Length - 1, 1);
- }
- }
- }
- }
- else
- {
- if (resultBuilderIsPooled)
- {
- StringBuilderCache.Release(result);
- }
- throw new FormatException(SR.Format_InvalidString);
- }
- break;
- case 't':
- tokenLen = ParseRepeatPattern(format, i, ch);
- if (tokenLen == 1)
- {
- if (dateTime.Hour < 12)
- {
- if (dtfi.AMDesignator.Length >= 1)
- {
- result.Append(dtfi.AMDesignator[0]);
- }
- }
- else
- {
- if (dtfi.PMDesignator.Length >= 1)
- {
- result.Append(dtfi.PMDesignator[0]);
- }
- }
- }
- else
- {
- result.Append(dateTime.Hour < 12 ? dtfi.AMDesignator : dtfi.PMDesignator);
- }
- break;
- case 'd':
- //
- // tokenLen == 1 : Day of month as digits with no leading zero.
- // tokenLen == 2 : Day of month as digits with leading zero for single-digit months.
- // tokenLen == 3 : Day of week as a three-letter abbreviation.
- // tokenLen >= 4 : Day of week as its full name.
- //
- tokenLen = ParseRepeatPattern(format, i, ch);
- if (tokenLen <= 2)
- {
- int day = cal.GetDayOfMonth(dateTime);
- if (isHebrewCalendar)
- {
- // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values.
- HebrewFormatDigits(result, day);
- }
- else
- {
- FormatDigits(result, day, tokenLen);
- }
- }
- else
- {
- int dayOfWeek = (int)cal.GetDayOfWeek(dateTime);
- result.Append(FormatDayOfWeek(dayOfWeek, tokenLen, dtfi));
- }
- bTimeOnly = false;
- break;
- case 'M':
- //
- // tokenLen == 1 : Month as digits with no leading zero.
- // tokenLen == 2 : Month as digits with leading zero for single-digit months.
- // tokenLen == 3 : Month as a three-letter abbreviation.
- // tokenLen >= 4 : Month as its full name.
- //
- tokenLen = ParseRepeatPattern(format, i, ch);
- int month = cal.GetMonth(dateTime);
- if (tokenLen <= 2)
- {
- if (isHebrewCalendar)
- {
- // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values.
- HebrewFormatDigits(result, month);
- }
- else
- {
- FormatDigits(result, month, tokenLen);
- }
- }
- else
- {
- if (isHebrewCalendar)
- {
- result.Append(FormatHebrewMonthName(dateTime, month, tokenLen, dtfi));
- }
- else
- {
- if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
- {
- result.Append(
- dtfi.InternalGetMonthName(
- month,
- IsUseGenitiveForm(format, i, tokenLen, 'd') ? MonthNameStyles.Genitive : MonthNameStyles.Regular,
- tokenLen == 3));
- }
- else
- {
- result.Append(FormatMonth(month, tokenLen, dtfi));
- }
- }
- }
- bTimeOnly = false;
- break;
- case 'y':
- // Notes about OS behavior:
- // y: Always print (year % 100). No leading zero.
- // yy: Always print (year % 100) with leading zero.
- // yyy/yyyy/yyyyy/... : Print year value. No leading zero.
-
- int year = cal.GetYear(dateTime);
- tokenLen = ParseRepeatPattern(format, i, ch);
- if (isJapaneseCalendar &&
- !LocalAppContextSwitches.FormatJapaneseFirstYearAsANumber &&
- year == 1 &&
- ((i + tokenLen < format.Length && format[i + tokenLen] == DateTimeFormatInfoScanner.CJKYearSuff[0]) ||
- (i + tokenLen < format.Length - 1 && format[i + tokenLen] == '\'' && format[i + tokenLen + 1] == DateTimeFormatInfoScanner.CJKYearSuff[0])))
- {
- // We are formatting a Japanese date with year equals 1 and the year number is followed by the year sign \u5e74
- // In Japanese dates, the first year in the era is not formatted as a number 1 instead it is formatted as \u5143 which means
- // first or beginning of the era.
- result.Append(DateTimeFormatInfo.JapaneseEraStart[0]);
- }
- else if (dtfi.HasForceTwoDigitYears)
- {
- FormatDigits(result, year, tokenLen <= 2 ? tokenLen : 2);
- }
- else if (cal.ID == CalendarId.HEBREW)
- {
- HebrewFormatDigits(result, year);
- }
- else
- {
- if (tokenLen <= 2)
- {
- FormatDigits(result, year % 100, tokenLen);
- }
- else if (tokenLen <= 16) // FormatDigits has an implicit 16-digit limit
- {
- FormatDigits(result, year, tokenLen, overrideLengthLimit: true);
- }
- else
- {
- result.Append(year.ToString("D" + tokenLen.ToString(), CultureInfo.InvariantCulture));
- }
- }
- bTimeOnly = false;
- break;
- case 'z':
- tokenLen = ParseRepeatPattern(format, i, ch);
- FormatCustomizedTimeZone(dateTime, offset, tokenLen, bTimeOnly, result);
- break;
- case 'K':
- tokenLen = 1;
- FormatCustomizedRoundripTimeZone(dateTime, offset, result);
- break;
- case ':':
- result.Append(dtfi.TimeSeparator);
- tokenLen = 1;
- break;
- case '/':
- result.Append(dtfi.DateSeparator);
- tokenLen = 1;
- break;
- case '\'':
- case '\"':
- tokenLen = ParseQuoteString(format, i, result);
- break;
- case '%':
- // Optional format character.
- // For example, format string "%d" will print day of month
- // without leading zero. Most of the cases, "%" can be ignored.
- nextChar = ParseNextChar(format, i);
- // nextChar will be -1 if we have already reached the end of the format string.
- // Besides, we will not allow "%%" to appear in the pattern.
- if (nextChar >= 0 && nextChar != '%')
- {
- char nextCharChar = (char)nextChar;
- StringBuilder origStringBuilder = FormatCustomized(dateTime, MemoryMarshal.CreateReadOnlySpan<char>(ref nextCharChar, 1), dtfi, offset, result);
- Debug.Assert(ReferenceEquals(origStringBuilder, result));
- tokenLen = 2;
- }
- else
- {
- //
- // This means that '%' is at the end of the format string or
- // "%%" appears in the format string.
- //
- if (resultBuilderIsPooled)
- {
- StringBuilderCache.Release(result);
- }
- throw new FormatException(SR.Format_InvalidString);
- }
- break;
- case '\\':
- // Escaped character. Can be used to insert a character into the format string.
- // For exmple, "\d" will insert the character 'd' into the string.
- //
- // NOTENOTE : we can remove this format character if we enforce the enforced quote
- // character rule.
- // That is, we ask everyone to use single quote or double quote to insert characters,
- // then we can remove this character.
- //
- nextChar = ParseNextChar(format, i);
- if (nextChar >= 0)
- {
- result.Append((char)nextChar);
- tokenLen = 2;
- }
- else
- {
- //
- // This means that '\' is at the end of the formatting string.
- //
- if (resultBuilderIsPooled)
- {
- StringBuilderCache.Release(result);
- }
- throw new FormatException(SR.Format_InvalidString);
- }
- break;
- default:
- // NOTENOTE : we can remove this rule if we enforce the enforced quote
- // character rule.
- // That is, if we ask everyone to use single quote or double quote to insert characters,
- // then we can remove this default block.
- result.Append(ch);
- tokenLen = 1;
- break;
- }
- i += tokenLen;
- }
- return result;
- }
-
- // output the 'z' family of formats, which output a the offset from UTC, e.g. "-07:30"
- private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset, int tokenLen, bool timeOnly, StringBuilder result)
- {
- // See if the instance already has an offset
- bool dateTimeFormat = (offset == NullOffset);
- if (dateTimeFormat)
- {
- // No offset. The instance is a DateTime and the output should be the local time zone
-
- if (timeOnly && dateTime.Ticks < Calendar.TicksPerDay)
- {
- // For time only format and a time only input, the time offset on 0001/01/01 is less
- // accurate than the system's current offset because of daylight saving time.
- offset = TimeZoneInfo.GetLocalUtcOffset(DateTime.Now, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- }
- else if (dateTime.Kind == DateTimeKind.Utc)
- {
- offset = TimeSpan.Zero;
- }
- else
- {
- offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- }
- }
- if (offset >= TimeSpan.Zero)
- {
- result.Append('+');
- }
- else
- {
- result.Append('-');
- // get a positive offset, so that you don't need a separate code path for the negative numbers.
- offset = offset.Negate();
- }
-
- if (tokenLen <= 1)
- {
- // 'z' format e.g "-7"
- result.AppendFormat(CultureInfo.InvariantCulture, "{0:0}", offset.Hours);
- }
- else
- {
- // 'zz' or longer format e.g "-07"
- result.AppendFormat(CultureInfo.InvariantCulture, "{0:00}", offset.Hours);
- if (tokenLen >= 3)
- {
- // 'zzz*' or longer format e.g "-07:30"
- result.AppendFormat(CultureInfo.InvariantCulture, ":{0:00}", offset.Minutes);
- }
- }
- }
-
- // output the 'K' format, which is for round-tripping the data
- private static void FormatCustomizedRoundripTimeZone(DateTime dateTime, TimeSpan offset, StringBuilder result)
- {
- // The objective of this format is to round trip the data in the type
- // For DateTime it should round-trip the Kind value and preserve the time zone.
- // DateTimeOffset instance, it should do so by using the internal time zone.
-
- if (offset == NullOffset)
- {
- // source is a date time, so behavior depends on the kind.
- switch (dateTime.Kind)
- {
- case DateTimeKind.Local:
- // This should output the local offset, e.g. "-07:30"
- offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- // fall through to shared time zone output code
- break;
- case DateTimeKind.Utc:
- // The 'Z' constant is a marker for a UTC date
- result.Append("Z");
- return;
- default:
- // If the kind is unspecified, we output nothing here
- return;
- }
- }
- if (offset >= TimeSpan.Zero)
- {
- result.Append('+');
- }
- else
- {
- result.Append('-');
- // get a positive offset, so that you don't need a separate code path for the negative numbers.
- offset = offset.Negate();
- }
-
- Append2DigitNumber(result, offset.Hours);
- result.Append(':');
- Append2DigitNumber(result, offset.Minutes);
- }
-
- private static void Append2DigitNumber(StringBuilder result, int val)
- {
- result.Append((char)('0' + (val / 10)));
- result.Append((char)('0' + (val % 10)));
- }
-
- internal static string GetRealFormat(ReadOnlySpan<char> format, DateTimeFormatInfo dtfi)
- {
- string realFormat;
-
- switch (format[0])
- {
- case 'd': // Short Date
- realFormat = dtfi.ShortDatePattern;
- break;
- case 'D': // Long Date
- realFormat = dtfi.LongDatePattern;
- break;
- case 'f': // Full (long date + short time)
- realFormat = dtfi.LongDatePattern + " " + dtfi.ShortTimePattern;
- break;
- case 'F': // Full (long date + long time)
- realFormat = dtfi.FullDateTimePattern;
- break;
- case 'g': // General (short date + short time)
- realFormat = dtfi.GeneralShortTimePattern;
- break;
- case 'G': // General (short date + long time)
- realFormat = dtfi.GeneralLongTimePattern;
- break;
- case 'm':
- case 'M': // Month/Day Date
- realFormat = dtfi.MonthDayPattern;
- break;
- case 'o':
- case 'O':
- realFormat = RoundtripFormat;
- break;
- case 'r':
- case 'R': // RFC 1123 Standard
- realFormat = dtfi.RFC1123Pattern;
- break;
- case 's': // Sortable without Time Zone Info
- realFormat = dtfi.SortableDateTimePattern;
- break;
- case 't': // Short Time
- realFormat = dtfi.ShortTimePattern;
- break;
- case 'T': // Long Time
- realFormat = dtfi.LongTimePattern;
- break;
- case 'u': // Universal with Sortable format
- realFormat = dtfi.UniversalSortableDateTimePattern;
- break;
- case 'U': // Universal with Full (long date + long time) format
- realFormat = dtfi.FullDateTimePattern;
- break;
- case 'y':
- case 'Y': // Year/Month Date
- realFormat = dtfi.YearMonthPattern;
- break;
- default:
- throw new FormatException(SR.Format_InvalidString);
- }
- return realFormat;
- }
-
- // Expand a pre-defined format string (like "D" for long date) to the real format that
- // we are going to use in the date time parsing.
- // This method also convert the dateTime if necessary (e.g. when the format is in Universal time),
- // and change dtfi if necessary (e.g. when the format should use invariant culture).
- //
- private static string ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTime dateTime, ref DateTimeFormatInfo dtfi, ref TimeSpan offset)
- {
- switch (format[0])
- {
- case 'o':
- case 'O': // Round trip format
- dtfi = DateTimeFormatInfo.InvariantInfo;
- break;
- case 'r':
- case 'R': // RFC 1123 Standard
- case 'u': // Universal time in sortable format.
- if (offset != NullOffset)
- {
- // Convert to UTC invariants mean this will be in range
- dateTime -= offset;
- }
- dtfi = DateTimeFormatInfo.InvariantInfo;
- break;
- case 's': // Sortable without Time Zone Info
- dtfi = DateTimeFormatInfo.InvariantInfo;
- break;
- case 'U': // Universal time in culture dependent format.
- if (offset != NullOffset)
- {
- // This format is not supported by DateTimeOffset
- throw new FormatException(SR.Format_InvalidString);
- }
- // Universal time is always in Greogrian calendar.
- //
- // Change the Calendar to be Gregorian Calendar.
- //
- dtfi = (DateTimeFormatInfo)dtfi.Clone();
- if (dtfi.Calendar.GetType() != typeof(GregorianCalendar))
- {
- dtfi.Calendar = GregorianCalendar.GetDefaultInstance();
- }
- dateTime = dateTime.ToUniversalTime();
- break;
- }
- return GetRealFormat(format, dtfi);
- }
-
- internal static string Format(DateTime dateTime, string? format, IFormatProvider? provider)
- {
- return Format(dateTime, format, provider, NullOffset);
- }
-
- internal static string Format(DateTime dateTime, string? format, IFormatProvider? provider, TimeSpan offset)
- {
- if (format != null && format.Length == 1)
- {
- // Optimize for these standard formats that are not affected by culture.
- switch (format[0])
- {
- // Round trip format
- case 'o':
- case 'O':
- const int MinFormatOLength = 27, MaxFormatOLength = 33;
- Span<char> span = stackalloc char[MaxFormatOLength];
- TryFormatO(dateTime, offset, span, out int ochars);
- Debug.Assert(ochars >= MinFormatOLength && ochars <= MaxFormatOLength);
- return span.Slice(0, ochars).ToString();
-
- // RFC1123
- case 'r':
- case 'R':
- const int FormatRLength = 29;
- string str = string.FastAllocateString(FormatRLength);
- TryFormatR(dateTime, offset, new Span<char>(ref str.GetRawStringData(), str.Length), out int rchars);
- Debug.Assert(rchars == str.Length);
- return str;
- }
- }
-
- DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(provider);
- return StringBuilderCache.GetStringAndRelease(FormatStringBuilder(dateTime, format, dtfi, offset));
- }
-
- internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) =>
- TryFormat(dateTime, destination, out charsWritten, format, provider, NullOffset);
-
- internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider, TimeSpan offset)
- {
- if (format.Length == 1)
- {
- // Optimize for these standard formats that are not affected by culture.
- switch (format[0])
- {
- // Round trip format
- case 'o':
- case 'O':
- return TryFormatO(dateTime, offset, destination, out charsWritten);
-
- // RFC1123
- case 'r':
- case 'R':
- return TryFormatR(dateTime, offset, destination, out charsWritten);
- }
- }
-
- DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(provider);
- StringBuilder sb = FormatStringBuilder(dateTime, format, dtfi, offset);
-
- bool success = sb.Length <= destination.Length;
- if (success)
- {
- sb.CopyTo(0, destination, sb.Length);
- charsWritten = sb.Length;
- }
- else
- {
- charsWritten = 0;
- }
-
- StringBuilderCache.Release(sb);
- return success;
- }
-
- private static StringBuilder FormatStringBuilder(DateTime dateTime, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
- {
- Debug.Assert(dtfi != null);
- if (format.Length == 0)
- {
- bool timeOnlySpecialCase = false;
- if (dateTime.Ticks < Calendar.TicksPerDay)
- {
- // If the time is less than 1 day, consider it as time of day.
- // Just print out the short time format.
- //
- // This is a workaround for VB, since they use ticks less then one day to be
- // time of day. In cultures which use calendar other than Gregorian calendar, these
- // alternative calendar may not support ticks less than a day.
- // For example, Japanese calendar only supports date after 1868/9/8.
- // This will pose a problem when people in VB get the time of day, and use it
- // to call ToString(), which will use the general format (short date + long time).
- // Since Japanese calendar does not support Gregorian year 0001, an exception will be
- // thrown when we try to get the Japanese year for Gregorian year 0001.
- // Therefore, the workaround allows them to call ToString() for time of day from a DateTime by
- // formatting as ISO 8601 format.
- switch (dtfi.Calendar.ID)
- {
- case CalendarId.JAPAN:
- case CalendarId.TAIWAN:
- case CalendarId.HIJRI:
- case CalendarId.HEBREW:
- case CalendarId.JULIAN:
- case CalendarId.UMALQURA:
- case CalendarId.PERSIAN:
- timeOnlySpecialCase = true;
- dtfi = DateTimeFormatInfo.InvariantInfo;
- break;
- }
- }
- if (offset == NullOffset)
- {
- // Default DateTime.ToString case.
- format = timeOnlySpecialCase ? "s" : "G";
- }
- else
- {
- // Default DateTimeOffset.ToString case.
- format = timeOnlySpecialCase ? RoundtripDateTimeUnfixed : dtfi.DateTimeOffsetPattern;
- }
- }
-
- if (format.Length == 1)
- {
- format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
- }
-
- return FormatCustomized(dateTime, format, dtfi, offset, result: null);
- }
-
- // Roundtrippable format. One of
- // 012345678901234567890123456789012
- // ---------------------------------
- // 2017-06-12T05:30:45.7680000-07:00
- // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
- // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
- private static bool TryFormatO(DateTime dateTime, TimeSpan offset, Span<char> destination, out int charsWritten)
- {
- const int MinimumBytesNeeded = 27;
-
- int charsRequired = MinimumBytesNeeded;
- DateTimeKind kind = DateTimeKind.Local;
-
- if (offset == NullOffset)
- {
- kind = dateTime.Kind;
- if (kind == DateTimeKind.Local)
- {
- offset = TimeZoneInfo.Local.GetUtcOffset(dateTime);
- charsRequired += 6;
- }
- else if (kind == DateTimeKind.Utc)
- {
- charsRequired++;
- }
- }
- else
- {
- charsRequired += 6;
- }
-
- if (destination.Length < charsRequired)
- {
- charsWritten = 0;
- return false;
- }
- charsWritten = charsRequired;
-
- // Hoist most of the bounds checks on destination.
- { _ = destination[MinimumBytesNeeded - 1]; }
-
- WriteFourDecimalDigits((uint)dateTime.Year, destination, 0);
- destination[4] = '-';
- WriteTwoDecimalDigits((uint)dateTime.Month, destination, 5);
- destination[7] = '-';
- WriteTwoDecimalDigits((uint)dateTime.Day, destination, 8);
- destination[10] = 'T';
- WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 11);
- destination[13] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 14);
- destination[16] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Second, destination, 17);
- destination[19] = '.';
- WriteDigits((uint)((ulong)dateTime.Ticks % (ulong)TimeSpan.TicksPerSecond), destination.Slice(20, 7));
-
- if (kind == DateTimeKind.Local)
- {
- char sign;
- if (offset < default(TimeSpan) /* a "const" version of TimeSpan.Zero */)
- {
- sign = '-';
- offset = TimeSpan.FromTicks(-offset.Ticks);
- }
- else
- {
- sign = '+';
- }
-
- // Writing the value backward allows the JIT to optimize by
- // performing a single bounds check against buffer.
- WriteTwoDecimalDigits((uint)offset.Minutes, destination, 31);
- destination[30] = ':';
- WriteTwoDecimalDigits((uint)offset.Hours, destination, 28);
- destination[27] = sign;
- }
- else if (kind == DateTimeKind.Utc)
- {
- destination[27] = 'Z';
- }
-
- return true;
- }
-
- // Rfc1123
- // 01234567890123456789012345678
- // -----------------------------
- // Tue, 03 Jan 2017 08:08:05 GMT
- private static bool TryFormatR(DateTime dateTime, TimeSpan offset, Span<char> destination, out int charsWritten)
- {
- // Writing the check in this fashion elides all bounds checks on 'destination'
- // for the remainder of the method.
- if (28 >= (uint)destination.Length)
- {
- charsWritten = 0;
- return false;
- }
-
- if (offset != NullOffset)
- {
- // Convert to UTC invariants.
- dateTime -= offset;
- }
-
- dateTime.GetDatePart(out int year, out int month, out int day);
-
- string dayAbbrev = InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek];
- Debug.Assert(dayAbbrev.Length == 3);
-
- string monthAbbrev = InvariantAbbreviatedMonthNames[month - 1];
- Debug.Assert(monthAbbrev.Length == 3);
-
- destination[0] = dayAbbrev[0];
- destination[1] = dayAbbrev[1];
- destination[2] = dayAbbrev[2];
- destination[3] = ',';
- destination[4] = ' ';
- WriteTwoDecimalDigits((uint)day, destination, 5);
- destination[7] = ' ';
- destination[8] = monthAbbrev[0];
- destination[9] = monthAbbrev[1];
- destination[10] = monthAbbrev[2];
- destination[11] = ' ';
- WriteFourDecimalDigits((uint)year, destination, 12);
- destination[16] = ' ';
- WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 17);
- destination[19] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 20);
- destination[22] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Second, destination, 23);
- destination[25] = ' ';
- destination[26] = 'G';
- destination[27] = 'M';
- destination[28] = 'T';
-
- charsWritten = 29;
- return true;
- }
-
- /// <summary>
- /// Writes a value [ 00 .. 99 ] to the buffer starting at the specified offset.
- /// This method performs best when the starting index is a constant literal.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void WriteTwoDecimalDigits(uint value, Span<char> destination, int offset)
- {
- Debug.Assert(value <= 99);
-
- uint temp = '0' + value;
- value /= 10;
- destination[offset + 1] = (char)(temp - (value * 10));
- destination[offset] = (char)('0' + value);
- }
-
- /// <summary>
- /// Writes a value [ 0000 .. 9999 ] to the buffer starting at the specified offset.
- /// This method performs best when the starting index is a constant literal.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void WriteFourDecimalDigits(uint value, Span<char> buffer, int startingIndex = 0)
- {
- Debug.Assert(value <= 9999);
-
- uint temp = '0' + value;
- value /= 10;
- buffer[startingIndex + 3] = (char)(temp - (value * 10));
-
- temp = '0' + value;
- value /= 10;
- buffer[startingIndex + 2] = (char)(temp - (value * 10));
-
- temp = '0' + value;
- value /= 10;
- buffer[startingIndex + 1] = (char)(temp - (value * 10));
-
- buffer[startingIndex] = (char)('0' + value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void WriteDigits(ulong value, Span<char> buffer)
- {
- // We can mutate the 'value' parameter since it's a copy-by-value local.
- // It'll be used to represent the value left over after each division by 10.
-
- for (int i = buffer.Length - 1; i >= 1; i--)
- {
- ulong temp = '0' + value;
- value /= 10;
- buffer[i] = (char)(temp - (value * 10));
- }
-
- Debug.Assert(value < 10);
- buffer[0] = (char)('0' + value);
- }
-
- internal static string[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi)
- {
- Debug.Assert(dtfi != null);
- string[] allFormats;
- string[] results;
-
- switch (format)
- {
- case 'd':
- case 'D':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- case 'm':
- case 'M':
- case 't':
- case 'T':
- case 'y':
- case 'Y':
- allFormats = dtfi.GetAllDateTimePatterns(format);
- results = new string[allFormats.Length];
- for (int i = 0; i < allFormats.Length; i++)
- {
- results[i] = Format(dateTime, allFormats[i], dtfi);
- }
- break;
- case 'U':
- DateTime universalTime = dateTime.ToUniversalTime();
- allFormats = dtfi.GetAllDateTimePatterns(format);
- results = new string[allFormats.Length];
- for (int i = 0; i < allFormats.Length; i++)
- {
- results[i] = Format(universalTime, allFormats[i], dtfi);
- }
- break;
- //
- // The following ones are special cases because these patterns are read-only in
- // DateTimeFormatInfo.
- //
- case 'r':
- case 'R':
- case 'o':
- case 'O':
- case 's':
- case 'u':
- results = new string[] { Format(dateTime, char.ToString(format), dtfi) };
- break;
- default:
- throw new FormatException(SR.Format_InvalidString);
- }
- return results;
- }
-
- internal static string[] GetAllDateTimes(DateTime dateTime, DateTimeFormatInfo dtfi)
- {
- List<string> results = new List<string>(DEFAULT_ALL_DATETIMES_SIZE);
-
- for (int i = 0; i < allStandardFormats.Length; i++)
- {
- string[] strings = GetAllDateTimes(dateTime, allStandardFormats[i], dtfi);
- for (int j = 0; j < strings.Length; j++)
- {
- results.Add(strings[j]);
- }
- }
-
- return results.ToArray();
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
deleted file mode 100644
index 2989153d62f..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
+++ /dev/null
@@ -1,2604 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- /// <summary>
- /// Flags used to indicate different styles of month names.
- /// This is an internal flag used by internalGetMonthName().
- /// Use flag here in case that we need to provide a combination of these styles
- /// (such as month name of a leap year in genitive form. Not likely for now,
- /// but would like to keep the option open).
- /// </summary>
-
- [Flags]
- internal enum MonthNameStyles
- {
- Regular = 0x00000000,
- Genitive = 0x00000001,
- LeapYear = 0x00000002,
- }
-
- /// <summary>
- /// Flags used to indicate special rule used in parsing/formatting
- /// for a specific DateTimeFormatInfo instance.
- /// This is an internal flag.
- ///
- /// This flag is different from MonthNameStyles because this flag
- /// can be expanded to accommodate parsing behaviors like CJK month names
- /// or alternative month names, etc.
- /// </summary>
- [Flags]
- internal enum DateTimeFormatFlags
- {
- None = 0x00000000,
- UseGenitiveMonth = 0x00000001,
- UseLeapYearMonth = 0x00000002,
- UseSpacesInMonthNames = 0x00000004, // Has spaces or non-breaking space in the month names.
- UseHebrewRule = 0x00000008, // Format/Parse using the Hebrew calendar rule.
- UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names.
- UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers.
-
- NotInitialized = -1,
- }
-
- public sealed class DateTimeFormatInfo : IFormatProvider, ICloneable
- {
- // cache for the invariant culture.
- // invariantInfo is constant irrespective of your current culture.
- private static volatile DateTimeFormatInfo? s_invariantInfo;
-
- // an index which points to a record in Culture Data Table.
- private readonly CultureData _cultureData;
-
- // The culture name used to create this DTFI.
- private string? _name = null;
-
- // The language name of the culture used to create this DTFI.
- private string? _langName = null;
-
- // CompareInfo usually used by the parser.
- private CompareInfo? _compareInfo = null;
-
- // Culture matches current DTFI. mainly used for string comparisons during parsing.
- private CultureInfo? _cultureInfo = null;
-
- private string? amDesignator = null;
- private string? pmDesignator = null;
-
- private string? dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
-
- private string? generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
-
- private string? generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
-
- private string? timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
- private string? monthDayPattern = null;
- private string? dateTimeOffsetPattern = null;
-
- private const string rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
-
- // The sortable pattern is based on ISO 8601.
- private const string sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
- private const string universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
-
- private Calendar calendar = null!; // initialized in helper called by ctors
-
- private int firstDayOfWeek = -1;
- private int calendarWeekRule = -1;
-
- private string? fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
-
- private string[]? abbreviatedDayNames = null;
-
- private string[]? m_superShortDayNames = null;
-
- private string[]? dayNames = null;
- private string[]? abbreviatedMonthNames = null;
- private string[]? monthNames = null;
-
- // Cache the genitive month names that we retrieve from the data table.
-
- private string[]? genitiveMonthNames = null;
-
- // Cache the abbreviated genitive month names that we retrieve from the data table.
-
- private string[]? m_genitiveAbbreviatedMonthNames = null;
-
- // Cache the month names of a leap year that we retrieve from the data table.
- private string[]? leapYearMonthNames = null;
-
- // For our "patterns" arrays we have 2 variables, a string and a string[]
- //
- // The string[] contains the list of patterns, EXCEPT the default may not be included.
- // The string contains the default pattern.
- // When we initially construct our string[], we set the string to string[0]
-
- // The "default" Date/time patterns
- private string? longDatePattern = null;
- private string? shortDatePattern = null;
- private string? yearMonthPattern = null;
- private string? longTimePattern = null;
- private string? shortTimePattern = null;
-
- private string[]? allYearMonthPatterns = null;
-
- private string[]? allShortDatePatterns = null;
- private string[]? allLongDatePatterns = null;
- private string[]? allShortTimePatterns = null;
- private string[]? allLongTimePatterns = null;
-
- // Cache the era names for this DateTimeFormatInfo instance.
- private string[]? m_eraNames = null;
- private string[]? m_abbrevEraNames = null;
- private string[]? m_abbrevEnglishEraNames = null;
-
- private CalendarId[]? optionalCalendars = null;
-
- private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
-
- // CultureInfo updates this
- internal bool _isReadOnly = false;
-
- // This flag gives hints about if formatting/parsing should perform special code path for things like
- // genitive form or leap year month names.
-
- private DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized;
-
- private string CultureName => _name ??= _cultureData.CultureName;
-
- private CultureInfo Culture => _cultureInfo ??= CultureInfo.GetCultureInfo(CultureName);
-
- private string LanguageName => _langName ??= _cultureData.TwoLetterISOLanguageName;
-
- /// <summary>
- /// Create an array of string which contains the abbreviated day names.
- /// </summary>
- private string[] InternalGetAbbreviatedDayOfWeekNames() => abbreviatedDayNames ?? InternalGetAbbreviatedDayOfWeekNamesCore();
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private string[] InternalGetAbbreviatedDayOfWeekNamesCore()
- {
- // Get the abbreviated day names for our current calendar
- abbreviatedDayNames = _cultureData.AbbreviatedDayNames(Calendar.ID);
- Debug.Assert(abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week");
- return abbreviatedDayNames;
- }
-
- /// <summary>
- /// Returns the string array of the one-letter day of week names.
- /// </summary>
- private string[] InternalGetSuperShortDayNames() => m_superShortDayNames ?? InternalGetSuperShortDayNamesCore();
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private string[] InternalGetSuperShortDayNamesCore()
- {
- // Get the super short day names for our current calendar
- m_superShortDayNames = _cultureData.SuperShortDayNames(Calendar.ID);
- Debug.Assert(m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.InternalGetSuperShortDayNames] Expected 7 day names in a week");
- return m_superShortDayNames;
- }
-
- /// <summary>
- /// Create an array of string which contains the day names.
- /// </summary>
- private string[] InternalGetDayOfWeekNames() => dayNames ?? InternalGetDayOfWeekNamesCore();
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private string[] InternalGetDayOfWeekNamesCore()
- {
- // Get the day names for our current calendar
- dayNames = _cultureData.DayNames(Calendar.ID);
- Debug.Assert(dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week");
- return dayNames;
- }
-
- /// <summary>
- /// Create an array of string which contains the abbreviated month names.
- /// </summary>
- private string[] InternalGetAbbreviatedMonthNames() => abbreviatedMonthNames ?? InternalGetAbbreviatedMonthNamesCore();
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private string[] InternalGetAbbreviatedMonthNamesCore()
- {
- // Get the month names for our current calendar
- abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID);
- Debug.Assert(abbreviatedMonthNames.Length == 12 || abbreviatedMonthNames.Length == 13,
- "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year");
- return abbreviatedMonthNames;
- }
-
- /// <summary>
- /// Create an array of string which contains the month names.
- /// </summary>
- private string[] InternalGetMonthNames() => monthNames ?? internalGetMonthNamesCore();
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private string[] internalGetMonthNamesCore()
- {
- // Get the month names for our current calendar
- monthNames = _cultureData.MonthNames(Calendar.ID);
- Debug.Assert(monthNames.Length == 12 || monthNames.Length == 13,
- "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year");
- return monthNames;
- }
-
- // Invariant DateTimeFormatInfo doesn't have user-overriden values
- // Default calendar is gregorian
- public DateTimeFormatInfo()
- : this(CultureInfo.InvariantCulture._cultureData, GregorianCalendar.GetDefaultInstance())
- {
- }
-
- internal DateTimeFormatInfo(CultureData cultureData, Calendar cal)
- {
- Debug.Assert(cultureData != null);
- Debug.Assert(cal != null);
-
- // Remember our culture
- _cultureData = cultureData;
-
- Calendar = cal;
- }
-
- private void InitializeOverridableProperties(CultureData cultureData, CalendarId calendarId)
- {
- Debug.Assert(cultureData != null);
- Debug.Assert(calendarId != CalendarId.UNINITIALIZED_VALUE, "[DateTimeFormatInfo.Populate] Expected initalized calendarId");
-
- if (firstDayOfWeek == -1)
- {
- firstDayOfWeek = cultureData.FirstDayOfWeek;
- }
- if (calendarWeekRule == -1)
- {
- calendarWeekRule = cultureData.CalendarWeekRule;
- }
-
- if (amDesignator == null)
- {
- amDesignator = cultureData.AMDesignator;
- }
- if (pmDesignator == null)
- {
- pmDesignator = cultureData.PMDesignator;
- }
- if (timeSeparator == null)
- {
- timeSeparator = cultureData.TimeSeparator;
- }
- if (dateSeparator == null)
- {
- dateSeparator = cultureData.DateSeparator(calendarId);
- }
-
- allLongTimePatterns = _cultureData.LongTimes;
- Debug.Assert(allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns");
-
- allShortTimePatterns = _cultureData.ShortTimes;
- Debug.Assert(allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns");
-
- allLongDatePatterns = cultureData.LongDates(calendarId);
- Debug.Assert(allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns");
-
- allShortDatePatterns = cultureData.ShortDates(calendarId);
- Debug.Assert(allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns");
-
- allYearMonthPatterns = cultureData.YearMonths(calendarId);
- Debug.Assert(allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns");
- }
-
- /// <summary>
- /// Returns a default DateTimeFormatInfo that will be universally
- /// supported and constant irrespective of the current culture.
- /// </summary>
- public static DateTimeFormatInfo InvariantInfo
- {
- get
- {
- if (s_invariantInfo == null)
- {
- DateTimeFormatInfo info = new DateTimeFormatInfo();
- info.Calendar.SetReadOnlyState(true);
- info._isReadOnly = true;
- s_invariantInfo = info;
- }
- return s_invariantInfo;
- }
- }
-
- /// <summary>
- /// Returns the current culture's DateTimeFormatInfo.
- /// </summary>
- public static DateTimeFormatInfo CurrentInfo
- {
- get
- {
- System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
- if (!culture._isInherited)
- {
- DateTimeFormatInfo? info = culture._dateTimeInfo;
- if (info != null)
- {
- return info;
- }
- }
- return (DateTimeFormatInfo)culture.GetFormat(typeof(DateTimeFormatInfo))!;
- }
- }
-
- public static DateTimeFormatInfo GetInstance(IFormatProvider? provider) =>
- provider == null ? CurrentInfo :
- provider is CultureInfo cultureProvider && !cultureProvider._isInherited ? cultureProvider.DateTimeFormat :
- provider is DateTimeFormatInfo info ? info :
- provider.GetFormat(typeof(DateTimeFormatInfo)) is DateTimeFormatInfo info2 ? info2 :
- CurrentInfo; // Couldn't get anything, just use currentInfo as fallback
-
- public object? GetFormat(Type? formatType)
- {
- return formatType == typeof(DateTimeFormatInfo) ? this : null;
- }
-
- public object Clone()
- {
- DateTimeFormatInfo n = (DateTimeFormatInfo)MemberwiseClone();
- // We can use the data member calendar in the setter, instead of the property Calendar,
- // since the cloned copy should have the same state as the original copy.
- n.calendar = (Calendar)Calendar.Clone();
- n._isReadOnly = false;
- return n;
- }
-
- public string AMDesignator
- {
- get
- {
- if (amDesignator == null)
- {
- amDesignator = _cultureData.AMDesignator;
- }
-
- Debug.Assert(amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null");
- return amDesignator;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- ClearTokenHashTable();
- amDesignator = value;
- }
- }
-
- public Calendar Calendar
- {
- get
- {
- Debug.Assert(calendar != null, "DateTimeFormatInfo.Calendar: calendar != null");
- return calendar;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- if (value == calendar)
- {
- return;
- }
-
- for (int i = 0; i < OptionalCalendars.Length; i++)
- {
- if (OptionalCalendars[i] == value.ID)
- {
- // We can use this one, so do so.
- // Clean related properties if we already had a calendar set
- if (calendar != null)
- {
- // clean related properties which are affected by the calendar setting,
- // so that they will be refreshed when they are accessed next time.
- // These properites are in the order as appearing in calendar.xml.
- m_eraNames = null;
- m_abbrevEraNames = null;
- m_abbrevEnglishEraNames = null;
-
- monthDayPattern = null;
-
- dayNames = null;
- abbreviatedDayNames = null;
- m_superShortDayNames = null;
- monthNames = null;
- abbreviatedMonthNames = null;
- genitiveMonthNames = null;
- m_genitiveAbbreviatedMonthNames = null;
- leapYearMonthNames = null;
- formatFlags = DateTimeFormatFlags.NotInitialized;
-
- allShortDatePatterns = null;
- allLongDatePatterns = null;
- allYearMonthPatterns = null;
- dateTimeOffsetPattern = null;
-
- // The defaults need reset as well:
- longDatePattern = null;
- shortDatePattern = null;
- yearMonthPattern = null;
-
- // These properies are not in the OS data, but they are dependent on the values like shortDatePattern.
- fullDateTimePattern = null; // Long date + long time
- generalShortTimePattern = null; // short date + short time
- generalLongTimePattern = null; // short date + long time
-
- // Derived item that changes
- dateSeparator = null;
-
- // We don't need to do these because they are not changed by changing calendar
- // amDesignator
- // pmDesignator
- // timeSeparator
- // longTimePattern
- // firstDayOfWeek
- // calendarWeekRule
-
- // remember to reload tokens
- ClearTokenHashTable();
- }
-
- // Remember the new calendar
- calendar = value;
- InitializeOverridableProperties(_cultureData, calendar.ID);
-
- // We succeeded, return
- return;
- }
- }
-
- // The assigned calendar is not a valid calendar for this culture, throw
- throw new ArgumentOutOfRangeException(nameof(value), value, SR.Argument_InvalidCalendar);
- }
- }
-
- private CalendarId[] OptionalCalendars => optionalCalendars ??= _cultureData.CalendarIds;
-
- /// <summary>
- /// Get the era value by parsing the name of the era.
- /// </summary>
- public int GetEra(string eraName)
- {
- if (eraName == null)
- {
- throw new ArgumentNullException(nameof(eraName));
- }
-
- // The Era Name and Abbreviated Era Name
- // for Taiwan Calendar on non-Taiwan SKU returns empty string (which
- // would be matched below) but we don't want the empty string to give
- // us an Era number
- // confer 85900 DTFI.GetEra("") should fail on all cultures
- if (eraName.Length == 0)
- {
- return -1;
- }
-
- // The following is based on the assumption that the era value is starting from 1, and has a
- // serial values.
- // If that ever changes, the code has to be changed.
-
- // The calls to String.Compare should use the current culture for the string comparisons, but the
- // invariant culture when comparing against the english names.
- for (int i = 0; i < EraNames.Length; i++)
- {
- // Compare the era name in a case-insensitive way for the appropriate culture.
- if (m_eraNames![i].Length > 0)
- {
- if (Culture.CompareInfo.Compare(eraName, m_eraNames[i], CompareOptions.IgnoreCase) == 0)
- {
- return i + 1;
- }
- }
- }
- for (int i = 0; i < AbbreviatedEraNames.Length; i++)
- {
- // Compare the abbreviated era name in a case-insensitive way for the appropriate culture.
- if (Culture.CompareInfo.Compare(eraName, m_abbrevEraNames![i], CompareOptions.IgnoreCase) == 0)
- {
- return i + 1;
- }
- }
- for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++)
- {
- // this comparison should use the InvariantCulture. The English name could have linguistically
- // interesting characters.
- if (CompareInfo.Invariant.Compare(eraName, m_abbrevEnglishEraNames![i], CompareOptions.IgnoreCase) == 0)
- {
- return i + 1;
- }
- }
- return -1;
- }
-
- internal string[] EraNames => m_eraNames ??= _cultureData.EraNames(Calendar.ID);
-
- /// <summary>
- /// Get the name of the era for the specified era value.
- /// Era names are 1 indexed
- /// </summary>
- public string GetEraName(int era)
- {
- if (era == Calendar.CurrentEra)
- {
- era = Calendar.CurrentEraValue;
- }
-
- // The following is based on the assumption that the era value is starting from 1, and has a
- // serial values.
- // If that ever changes, the code has to be changed.
- if ((--era) < EraNames.Length && (era >= 0))
- {
- return m_eraNames![era];
- }
-
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- internal string[] AbbreviatedEraNames => m_abbrevEraNames ??= _cultureData.AbbrevEraNames(Calendar.ID);
-
- /// <remarks>
- /// Era names are 1 indexed
- /// </remarks>
- public string GetAbbreviatedEraName(int era)
- {
- if (AbbreviatedEraNames.Length == 0)
- {
- // If abbreviation era name is not used in this culture,
- // return the full era name.
- return GetEraName(era);
- }
-
- if (era == Calendar.CurrentEra)
- {
- era = Calendar.CurrentEraValue;
- }
-
- if ((--era) < m_abbrevEraNames!.Length && (era >= 0))
- {
- return m_abbrevEraNames[era];
- }
-
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- internal string[] AbbreviatedEnglishEraNames
- {
- get
- {
- if (m_abbrevEnglishEraNames == null)
- {
- Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0");
- m_abbrevEnglishEraNames = _cultureData.AbbreviatedEnglishEraNames(Calendar.ID);
- }
- return m_abbrevEnglishEraNames;
- }
- }
-
- /// <remarks>
- /// Note that cultureData derives this from the short date format (unless someone's set this previously)
- /// Note that this property is quite undesirable.
- /// </remarks>
- public string DateSeparator
- {
- get
- {
- if (dateSeparator == null)
- {
- dateSeparator = _cultureData.DateSeparator(Calendar.ID);
- }
- Debug.Assert(dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null");
- return dateSeparator;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- ClearTokenHashTable();
- dateSeparator = value;
- }
- }
-
- public DayOfWeek FirstDayOfWeek
- {
- get
- {
- if (firstDayOfWeek == -1)
- {
- firstDayOfWeek = _cultureData.FirstDayOfWeek;
- }
- Debug.Assert(firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1");
-
- return (DayOfWeek)firstDayOfWeek;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
-
- if (value < DayOfWeek.Sunday || value > DayOfWeek.Saturday)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday));
- }
-
- firstDayOfWeek = (int)value;
- }
- }
-
- public CalendarWeekRule CalendarWeekRule
- {
- get
- {
- if (calendarWeekRule == -1)
- {
- calendarWeekRule = _cultureData.CalendarWeekRule;
- }
-
- Debug.Assert(calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1");
- return (CalendarWeekRule)calendarWeekRule;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value < CalendarWeekRule.FirstDay || value > CalendarWeekRule.FirstFourDayWeek)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
- }
-
- calendarWeekRule = (int)value;
- }
- }
-
- public string FullDateTimePattern
- {
- get => fullDateTimePattern ??= LongDatePattern + " " + LongTimePattern;
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- fullDateTimePattern = value;
- }
- }
-
- /// <summary>
- /// For our "patterns" arrays we have 2 variables, a string and a string[]
- /// The string[] contains the list of patterns, EXCEPT the default may not be included.
- /// The string contains the default pattern.
- /// When we initially construct our string[], we set the string to string[0]
- /// </summary>
- public string LongDatePattern
- {
- get => longDatePattern ??= UnclonedLongDatePatterns[0]; // initialize from the 1st array value if not set
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- // Remember the new string
- longDatePattern = value;
-
- // Clear the token hash table
- ClearTokenHashTable();
-
- // Clean up cached values that will be affected by this property.
- fullDateTimePattern = null;
- }
- }
-
- /// <summary>
- /// For our "patterns" arrays we have 2 variables, a string and a string[]
- ///
- /// The string[] contains the list of patterns, EXCEPT the default may not be included.
- /// The string contains the default pattern.
- /// When we initially construct our string[], we set the string to string[0]
- /// </summary>
- public string LongTimePattern
- {
- get => longTimePattern ??= UnclonedLongTimePatterns[0]; // initialize from the 1st array value if not set
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- // Remember the new string
- longTimePattern = value;
-
- // Clear the token hash table
- ClearTokenHashTable();
-
- // Clean up cached values that will be affected by this property.
- fullDateTimePattern = null; // Full date = long date + long Time
- generalLongTimePattern = null; // General long date = short date + long Time
- dateTimeOffsetPattern = null;
- }
- }
-
- /// <remarks>
- /// Just to be confusing there's only 1 month day pattern, not a whole list
- /// </remarks>
- public string MonthDayPattern
- {
- get
- {
- if (monthDayPattern == null)
- {
- Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0");
- monthDayPattern = _cultureData.MonthDay(Calendar.ID);
- }
-
- Debug.Assert(monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null");
- return monthDayPattern;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- monthDayPattern = value;
- }
- }
-
- public string PMDesignator
- {
- get
- {
- if (pmDesignator == null)
- {
- pmDesignator = _cultureData.PMDesignator;
- }
-
- Debug.Assert(pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null");
- return pmDesignator;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- ClearTokenHashTable();
- pmDesignator = value;
- }
- }
-
- public string RFC1123Pattern => rfc1123Pattern;
-
- /// <summary>
- /// For our "patterns" arrays we have 2 variables, a string and a string[]
- ///
- /// The string[] contains the list of patterns, EXCEPT the default may not be included.
- /// The string contains the default pattern.
- /// When we initially construct our string[], we set the string to string[0]
- /// </summary>
- public string ShortDatePattern
- {
- get
- {
- return shortDatePattern ??= UnclonedShortDatePatterns[0]; // initialize from the 1st array value if not set
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- // Remember the new string
- shortDatePattern = value;
-
- // Clear the token hash table, note that even short dates could require this
- ClearTokenHashTable();
-
- // Clean up cached values that will be affected by this property.
- generalLongTimePattern = null; // General long time = short date + long time
- generalShortTimePattern = null; // General short time = short date + short Time
- dateTimeOffsetPattern = null;
- }
- }
-
- /// <summary>
- /// For our "patterns" arrays we have 2 variables, a string and a string[]
- ///
- /// The string[] contains the list of patterns, EXCEPT the default may not be included.
- /// The string contains the default pattern.
- /// When we initially construct our string[], we set the string to string[0]
- /// </summary>
- public string ShortTimePattern
- {
- get => shortTimePattern ??= UnclonedShortTimePatterns[0]; // initialize from the 1st array value if not set
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- // Remember the new string
- shortTimePattern = value;
-
- // Clear the token hash table, note that even short times could require this
- ClearTokenHashTable();
-
- // Clean up cached values that will be affected by this property.
- generalShortTimePattern = null; // General short date = short date + short time.
- }
- }
-
- public string SortableDateTimePattern => sortableDateTimePattern;
-
- /// <summary>
- /// Return the pattern for 'g' general format: shortDate + short time
- /// This is used by DateTimeFormat.cs to get the pattern for 'g'.
- /// We put this internal property here so that we can avoid doing the
- /// concatation every time somebody asks for the general format.
- /// </summary>
- internal string GeneralShortTimePattern => generalShortTimePattern ??= ShortDatePattern + " " + ShortTimePattern;
-
- /// <summary>
- /// Return the pattern for 'g' general format: shortDate + Long time.
- /// We put this internal property here so that we can avoid doing the
- /// concatation every time somebody asks for the general format.
- /// </summary>
- internal string GeneralLongTimePattern => generalLongTimePattern ??= ShortDatePattern + " " + LongTimePattern;
-
- /// Return the default pattern DateTimeOffset : shortDate + long time + time zone offset.
- /// This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset
- /// We put this internal property here so that we can avoid doing the
- /// concatation every time somebody uses this form.
- internal string DateTimeOffsetPattern
- {
- get
- {
- if (dateTimeOffsetPattern == null)
- {
- /* LongTimePattern might contain a "z" as part of the format string in which case we don't want to append a time zone offset */
-
- bool foundZ = false;
- bool inQuote = false;
- char quote = '\'';
- for (int i = 0; !foundZ && i < LongTimePattern.Length; i++)
- {
- switch (LongTimePattern[i])
- {
- case 'z':
- /* if we aren't in a quote, we've found a z */
- foundZ = !inQuote;
- /* we'll fall out of the loop now because the test includes !foundZ */
- break;
- case '\'':
- case '\"':
- if (inQuote && (quote == LongTimePattern[i]))
- {
- /* we were in a quote and found a matching exit quote, so we are outside a quote now */
- inQuote = false;
- }
- else if (!inQuote)
- {
- quote = LongTimePattern[i];
- inQuote = true;
- }
- else
- {
- /* we were in a quote and saw the other type of quote character, so we are still in a quote */
- }
- break;
- case '%':
- case '\\':
- i++; /* skip next character that is escaped by this backslash */
- break;
- default:
- break;
- }
- }
-
- dateTimeOffsetPattern = foundZ ?
- ShortDatePattern + " " + LongTimePattern :
- ShortDatePattern + " " + LongTimePattern + " zzz";
- }
- return dateTimeOffsetPattern;
- }
- }
-
- /// <remarks>
- /// Note that cultureData derives this from the long time format (unless someone's set this previously)
- /// Note that this property is quite undesirable.
- /// </remarks>
- public string TimeSeparator
- {
- get
- {
- if (timeSeparator == null)
- {
- timeSeparator = _cultureData.TimeSeparator;
- }
- Debug.Assert(timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null");
- return timeSeparator;
- }
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- ClearTokenHashTable();
- timeSeparator = value;
- }
- }
-
- public string UniversalSortableDateTimePattern => universalSortableDateTimePattern;
-
- /// <summary>
- /// For our "patterns" arrays we have 2 variables, a string and a string[]
- ///
- /// The string[] contains the list of patterns, EXCEPT the default may not be included.
- /// The string contains the default pattern.
- /// When we initially construct our string[], we set the string to string[0]
- /// </summary>
- public string YearMonthPattern
- {
- get => yearMonthPattern ??= UnclonedYearMonthPatterns[0]; // initialize from the 1st array value if not set
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- // Remember the new string
- yearMonthPattern = value;
-
- // Clear the token hash table, note that even short times could require this
- ClearTokenHashTable();
- }
- }
-
- /// <summary>
- /// Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value"
- /// </summary>
- private static void CheckNullValue(string[] values, int length)
- {
- Debug.Assert(values != null, "value != null");
- Debug.Assert(values.Length >= length);
- for (int i = 0; i < length; i++)
- {
- if (values[i] == null)
- {
- throw new ArgumentNullException("value", SR.ArgumentNull_ArrayValue);
- }
- }
- }
-
- public string[] AbbreviatedDayNames
- {
- get => (string[])InternalGetAbbreviatedDayOfWeekNames().Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 7)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value));
- }
-
- CheckNullValue(value, value.Length);
- ClearTokenHashTable();
-
- abbreviatedDayNames = value;
- }
- }
-
- /// <summary>
- /// Returns the string array of the one-letter day of week names.
- /// </summary>
- public string[] ShortestDayNames
- {
- get => (string[])InternalGetSuperShortDayNames().Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 7)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value));
- }
-
- CheckNullValue(value, value.Length);
- m_superShortDayNames = value;
- }
- }
-
- public string[] DayNames
- {
- get => (string[])InternalGetDayOfWeekNames().Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 7)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), nameof(value));
- }
-
- CheckNullValue(value, value.Length);
- ClearTokenHashTable();
-
- dayNames = value;
- }
- }
-
- public string[] AbbreviatedMonthNames
- {
- get => (string[])InternalGetAbbreviatedMonthNames().Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 13)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value));
- }
-
- CheckNullValue(value, value.Length - 1);
- ClearTokenHashTable();
- abbreviatedMonthNames = value;
- }
- }
-
- public string[] MonthNames
- {
- get => (string[])InternalGetMonthNames().Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 13)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value));
- }
-
- CheckNullValue(value, value.Length - 1);
- monthNames = value;
- ClearTokenHashTable();
- }
- }
-
- internal bool HasSpacesInMonthNames => (FormatFlags & DateTimeFormatFlags.UseSpacesInMonthNames) != 0;
-
- internal bool HasSpacesInDayNames => (FormatFlags & DateTimeFormatFlags.UseSpacesInDayNames) != 0;
-
- /// <summary>
- /// Return the month name using the specified MonthNameStyles in either abbreviated form
- /// or full form.
- /// </summary>
- internal string InternalGetMonthName(int month, MonthNameStyles style, bool abbreviated)
- {
- string[] monthNamesArray = style switch
- {
- MonthNameStyles.Genitive => InternalGetGenitiveMonthNames(abbreviated),
- MonthNameStyles.LeapYear => InternalGetLeapYearMonthNames(),
- _ => (abbreviated ? InternalGetAbbreviatedMonthNames() : InternalGetMonthNames()),
- };
-
- // The month range is from 1 ~ m_monthNames.Length
- // (actually is 13 right now for all cases)
- if ((month < 1) || (month > monthNamesArray.Length))
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, monthNamesArray.Length));
- }
-
- return monthNamesArray[month - 1];
- }
-
- /// <summary>
- /// Retrieve the array which contains the month names in genitive form.
- /// If this culture does not use the genitive form, the normal month name is returned.
- /// </summary>
- private string[] InternalGetGenitiveMonthNames(bool abbreviated)
- {
- if (abbreviated)
- {
- if (m_genitiveAbbreviatedMonthNames == null)
- {
- m_genitiveAbbreviatedMonthNames = _cultureData.AbbreviatedGenitiveMonthNames(Calendar.ID);
- Debug.Assert(m_genitiveAbbreviatedMonthNames.Length == 13,
- "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year");
- }
-
- return m_genitiveAbbreviatedMonthNames;
- }
-
- if (genitiveMonthNames == null)
- {
- genitiveMonthNames = _cultureData.GenitiveMonthNames(Calendar.ID);
- Debug.Assert(genitiveMonthNames.Length == 13,
- "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year");
- }
-
- return genitiveMonthNames;
- }
-
- /// <summary>
- /// Retrieve the month names used in a leap year.
- /// If this culture does not have different month names in a leap year,
- /// the normal month name is returned.
- /// </summary>
- internal string[] InternalGetLeapYearMonthNames()
- {
- if (leapYearMonthNames == null)
- {
- Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.InternalGetLeapYearMonthNames] Expected Calendar.ID > 0");
- leapYearMonthNames = _cultureData.LeapYearMonthNames(Calendar.ID);
- Debug.Assert(leapYearMonthNames.Length == 13,
- "[DateTimeFormatInfo.InternalGetLeapYearMonthNames] Expepcted 13 leap year month names");
- }
-
- return leapYearMonthNames;
- }
-
- public string GetAbbreviatedDayName(DayOfWeek dayofweek)
- {
- if (dayofweek < DayOfWeek.Sunday || dayofweek > DayOfWeek.Saturday)
- {
- throw new ArgumentOutOfRangeException(
- nameof(dayofweek),
- dayofweek,
- SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday));
- }
-
- // Don't call the public property AbbreviatedDayNames here since a clone is needed in that
- // property, so it will be slower. Instead, use GetAbbreviatedDayOfWeekNames() directly.
- return InternalGetAbbreviatedDayOfWeekNames()[(int)dayofweek];
- }
-
- /// <summary>
- /// Returns the super short day of week names for the specified day of week.
- /// </summary>
- public string GetShortestDayName(DayOfWeek dayOfWeek)
- {
- if (dayOfWeek < DayOfWeek.Sunday || dayOfWeek > DayOfWeek.Saturday)
- {
- throw new ArgumentOutOfRangeException(
- nameof(dayOfWeek),
- dayOfWeek,
- SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday));
- }
-
- // Don't call the public property SuperShortDayNames here since a clone is needed in that
- // property, so it will be slower. Instead, use internalGetSuperShortDayNames() directly.
- return InternalGetSuperShortDayNames()[(int)dayOfWeek];
- }
-
- /// <summary>
- /// Get all possible combination of inputs
- /// </summary>
- private static string[] GetCombinedPatterns(string[] patterns1, string[] patterns2, string connectString)
- {
- Debug.Assert(patterns1 != null);
- Debug.Assert(patterns2 != null);
-
- // Get array size
- string[] result = new string[patterns1.Length * patterns2.Length];
-
- // Counter of actual results
- int k = 0;
- for (int i = 0; i < patterns1.Length; i++)
- {
- for (int j = 0; j < patterns2.Length; j++)
- {
- // Can't combine if null or empty
- result[k++] = patterns1[i] + connectString + patterns2[j];
- }
- }
-
- // Return the combinations
- return result;
- }
-
- public string[] GetAllDateTimePatterns()
- {
- List<string> results = new List<string>(DEFAULT_ALL_DATETIMES_SIZE);
-
- for (int i = 0; i < DateTimeFormat.allStandardFormats.Length; i++)
- {
- string[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]);
- for (int j = 0; j < strings.Length; j++)
- {
- results.Add(strings[j]);
- }
- }
- return results.ToArray();
- }
-
- public string[] GetAllDateTimePatterns(char format)
- {
- string[] result;
-
- switch (format)
- {
- case 'd':
- result = AllShortDatePatterns;
- break;
- case 'D':
- result = AllLongDatePatterns;
- break;
- case 'f':
- result = GetCombinedPatterns(AllLongDatePatterns, AllShortTimePatterns, " ");
- break;
- case 'F':
- case 'U':
- result = GetCombinedPatterns(AllLongDatePatterns, AllLongTimePatterns, " ");
- break;
- case 'g':
- result = GetCombinedPatterns(AllShortDatePatterns, AllShortTimePatterns, " ");
- break;
- case 'G':
- result = GetCombinedPatterns(AllShortDatePatterns, AllLongTimePatterns, " ");
- break;
- case 'm':
- case 'M':
- result = new string[] { MonthDayPattern };
- break;
- case 'o':
- case 'O':
- result = new string[] { RoundtripFormat };
- break;
- case 'r':
- case 'R':
- result = new string[] { rfc1123Pattern };
- break;
- case 's':
- result = new string[] { sortableDateTimePattern };
- break;
- case 't':
- result = AllShortTimePatterns;
- break;
- case 'T':
- result = AllLongTimePatterns;
- break;
- case 'u':
- result = new string[] { UniversalSortableDateTimePattern };
- break;
- case 'y':
- case 'Y':
- result = AllYearMonthPatterns;
- break;
- default:
- throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format));
- }
- return result;
- }
-
- public string GetDayName(DayOfWeek dayofweek)
- {
- if ((int)dayofweek < 0 || (int)dayofweek > 6)
- {
- throw new ArgumentOutOfRangeException(
- nameof(dayofweek),
- dayofweek,
- SR.Format(SR.ArgumentOutOfRange_Range, DayOfWeek.Sunday, DayOfWeek.Saturday));
- }
-
- // Use the internal one so that we don't clone the array unnecessarily
- return InternalGetDayOfWeekNames()[(int)dayofweek];
- }
-
- public string GetAbbreviatedMonthName(int month)
- {
- if (month < 1 || month > 13)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, 13));
- }
-
- // Use the internal one so we don't clone the array unnecessarily
- return InternalGetAbbreviatedMonthNames()[month - 1];
- }
-
- public string GetMonthName(int month)
- {
- if (month < 1 || month > 13)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, 13));
- }
-
- // Use the internal one so we don't clone the array unnecessarily
- return InternalGetMonthNames()[month - 1];
- }
-
- /// <summary>
- /// For our "patterns" arrays we have 2 variables, a string and a string[]
- ///
- /// The string[] contains the list of patterns, EXCEPT the default may not be included.
- /// The string contains the default pattern.
- /// When we initially construct our string[], we set the string to string[0]
- ///
- /// The resulting [] can get returned to the calling app, so clone it.
- /// </summary>
- private static string[] GetMergedPatterns(string[] patterns, string defaultPattern)
- {
- Debug.Assert(patterns != null && patterns.Length > 0,
- "[DateTimeFormatInfo.GetMergedPatterns]Expected array of at least one pattern");
- Debug.Assert(defaultPattern != null,
- "[DateTimeFormatInfo.GetMergedPatterns]Expected non null default string");
-
- // If the default happens to be the first in the list just return (a cloned) copy
- if (defaultPattern == patterns[0])
- {
- return (string[])patterns.Clone();
- }
-
- // We either need a bigger list, or the pattern from the list.
- int i;
- for (i = 0; i < patterns.Length; i++)
- {
- // Stop if we found it
- if (defaultPattern == patterns[i])
- break;
- }
-
- // Either way we're going to need a new array
- string[] newPatterns;
-
- // Did we find it
- if (i < patterns.Length)
- {
- // Found it, output will be same size
- newPatterns = (string[])patterns.Clone();
-
- // Have to move [0] item to [i] so we can re-write default at [0]
- // (remember defaultPattern == [i] so this is OK)
- newPatterns[i] = newPatterns[0];
- }
- else
- {
- // Not found, make room for it
- newPatterns = new string[patterns.Length + 1];
-
- // Copy existing array
- Array.Copy(patterns, 0, newPatterns, 1, patterns.Length);
- }
-
- // Remember the default
- newPatterns[0] = defaultPattern;
-
- // Return the reconstructed list
- return newPatterns;
- }
-
- // Needed by DateTimeFormatInfo and DateTimeFormat
- internal const string RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
- internal const string RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
-
- /// <summary>
- /// Default string isn't necessarily in our string array, so get the
- /// merged patterns of both
- /// </summary>
- private string[] AllYearMonthPatterns => GetMergedPatterns(UnclonedYearMonthPatterns, YearMonthPattern);
-
- private string[] AllShortDatePatterns => GetMergedPatterns(UnclonedShortDatePatterns, ShortDatePattern);
-
- private string[] AllShortTimePatterns => GetMergedPatterns(UnclonedShortTimePatterns, ShortTimePattern);
-
- private string[] AllLongDatePatterns => GetMergedPatterns(UnclonedLongDatePatterns, LongDatePattern);
-
- private string[] AllLongTimePatterns => GetMergedPatterns(UnclonedLongTimePatterns, LongTimePattern);
-
- /// <remarks>
- /// Clone this string array if you want to return it to user.
- /// Otherwise, you are returning a writable cache copy.
- /// This won't include default, call AllYearMonthPatterns
- /// </remarks>
- private string[] UnclonedYearMonthPatterns
- {
- get
- {
- if (allYearMonthPatterns == null)
- {
- Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0");
- allYearMonthPatterns = _cultureData.YearMonths(Calendar.ID);
- Debug.Assert(allYearMonthPatterns.Length > 0,
- "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns");
- }
-
- return allYearMonthPatterns;
- }
- }
-
- /// <remarks>
- /// Clone this string array if you want to return it to user.
- /// Otherwise, you are returning a writable cache copy.
- /// This won't include default, call AllShortDatePatterns
- /// </remarks>
- private string[] UnclonedShortDatePatterns
- {
- get
- {
- if (allShortDatePatterns == null)
- {
- Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0");
- allShortDatePatterns = _cultureData.ShortDates(Calendar.ID);
- Debug.Assert(allShortDatePatterns.Length > 0,
- "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns");
- }
-
- return allShortDatePatterns;
- }
- }
-
- /// <remarks>
- /// Clone this string array if you want to return it to user.
- /// Otherwise, you are returning a writable cache copy.
- /// This won't include default, call AllLongDatePatterns
- /// </remarks>
- private string[] UnclonedLongDatePatterns
- {
- get
- {
- if (allLongDatePatterns == null)
- {
- Debug.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0");
- allLongDatePatterns = _cultureData.LongDates(Calendar.ID);
- Debug.Assert(allLongDatePatterns.Length > 0,
- "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns");
- }
-
- return allLongDatePatterns;
- }
- }
-
- /// <remarks>
- /// Clone this string array if you want to return it to user.
- /// Otherwise, you are returning a writable cache copy.
- /// This won't include default, call AllShortTimePatterns
- /// </remarks>
- private string[] UnclonedShortTimePatterns
- {
- get
- {
- if (allShortTimePatterns == null)
- {
- allShortTimePatterns = _cultureData.ShortTimes;
- Debug.Assert(allShortTimePatterns.Length > 0,
- "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns");
- }
-
- return allShortTimePatterns;
- }
- }
-
- /// <remarks>
- /// Clone this string array if you want to return it to user.
- /// Otherwise, you are returning a writable cache copy.
- /// This won't include default, call AllLongTimePatterns
- /// </remarks>
- private string[] UnclonedLongTimePatterns
- {
- get
- {
- if (allLongTimePatterns == null)
- {
- allLongTimePatterns = _cultureData.LongTimes;
- Debug.Assert(allLongTimePatterns.Length > 0,
- "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns");
- }
-
- return allLongTimePatterns;
- }
- }
-
- public static DateTimeFormatInfo ReadOnly(DateTimeFormatInfo dtfi)
- {
- if (dtfi == null)
- {
- throw new ArgumentNullException(nameof(dtfi));
- }
-
- if (dtfi.IsReadOnly)
- {
- return dtfi;
- }
-
- DateTimeFormatInfo newInfo = (DateTimeFormatInfo)(dtfi.MemberwiseClone());
- // We can use the data member calendar in the setter, instead of the property Calendar,
- // since the cloned copy should have the same state as the original copy.
- newInfo.calendar = Calendar.ReadOnly(dtfi.Calendar);
- newInfo._isReadOnly = true;
- return newInfo;
- }
-
- public bool IsReadOnly => _isReadOnly;
-
- /// <summary>
- /// Return the native name for the calendar in DTFI.Calendar. The native name is referred to
- /// the culture used to create the DTFI. E.g. in the following example, the native language is Japanese.
- /// DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new JapaneseCalendar();
- /// String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Japanese calendar.
- /// DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new GregorianCalendar(GregorianCalendarTypes.Localized);
- /// String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Gregorian calendar.
- /// </summary>
- public string NativeCalendarName => _cultureData.CalendarName(Calendar.ID);
-
- /// <summary>
- /// Used by custom cultures and others to set the list of available formats. Note that none of them are
- /// explicitly used unless someone calls GetAllDateTimePatterns and subsequently uses one of the items
- /// from the list.
- ///
- /// Most of the format characters that can be used in GetAllDateTimePatterns are
- /// not really needed since they are one of the following:
- ///
- /// r/R/s/u locale-independent constants -- cannot be changed!
- /// m/M/y/Y fields with a single string in them -- that can be set through props directly
- /// f/F/g/G/U derived fields based on combinations of various of the below formats
- ///
- /// NOTE: No special validation is done here beyond what is done when the actual respective fields
- /// are used (what would be the point of disallowing here what we allow in the appropriate property?)
- ///
- /// WARNING: If more validation is ever done in one place, it should be done in the other.
- /// </summary>
- public void SetAllDateTimePatterns(string[] patterns, char format)
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (patterns == null)
- {
- throw new ArgumentNullException(nameof(patterns));
- }
-
- if (patterns.Length == 0)
- {
- throw new ArgumentException(SR.Arg_ArrayZeroError, nameof(patterns));
- }
-
- for (int i = 0; i < patterns.Length; i++)
- {
- if (patterns[i] == null)
- {
- throw new ArgumentNullException("patterns[" + i + "]", SR.ArgumentNull_ArrayValue);
- }
- }
-
- // Remember the patterns, and use the 1st as default
- switch (format)
- {
- case 'd':
- allShortDatePatterns = patterns;
- shortDatePattern = allShortDatePatterns[0];
- break;
-
- case 'D':
- allLongDatePatterns = patterns;
- longDatePattern = allLongDatePatterns[0];
- break;
-
- case 't':
- allShortTimePatterns = patterns;
- shortTimePattern = allShortTimePatterns[0];
- break;
-
- case 'T':
- allLongTimePatterns = patterns;
- longTimePattern = allLongTimePatterns[0];
- break;
-
- case 'y':
- case 'Y':
- allYearMonthPatterns = patterns;
- yearMonthPattern = allYearMonthPatterns[0];
- break;
-
- default:
- throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format));
- }
-
- // Clear the token hash table, note that even short dates could require this
- ClearTokenHashTable();
- }
-
- public string[] AbbreviatedMonthGenitiveNames
- {
- get => (string[])InternalGetGenitiveMonthNames(true).Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 13)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value));
- }
-
- CheckNullValue(value, value.Length - 1);
- ClearTokenHashTable();
- m_genitiveAbbreviatedMonthNames = value;
- }
- }
-
- public string[] MonthGenitiveNames
- {
- get => (string[])InternalGetGenitiveMonthNames(false).Clone();
- set
- {
- if (IsReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if (value.Length != 13)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), nameof(value));
- }
-
- CheckNullValue(value, value.Length - 1);
- genitiveMonthNames = value;
- ClearTokenHashTable();
- }
- }
-
- // Decimal separator used by positive TimeSpan pattern
- private string? _decimalSeparator;
- internal string DecimalSeparator =>
- _decimalSeparator ??=
- new NumberFormatInfo(_cultureData.UseUserOverride ? CultureData.GetCultureData(_cultureData.CultureName, false) : _cultureData).NumberDecimalSeparator;
-
- // Positive TimeSpan Pattern
- private string? _fullTimeSpanPositivePattern;
- internal string FullTimeSpanPositivePattern =>
- _fullTimeSpanPositivePattern ??= "d':'h':'mm':'ss'" + DecimalSeparator + "'FFFFFFF";
-
- // Negative TimeSpan Pattern
- private string? _fullTimeSpanNegativePattern;
- internal string FullTimeSpanNegativePattern =>
- _fullTimeSpanNegativePattern ??= "'-'" + FullTimeSpanPositivePattern;
-
- // Get suitable CompareInfo from current DTFI object.
- internal CompareInfo CompareInfo =>
- // We use the regular GetCompareInfo here to make sure the created CompareInfo object is stored in the
- // CompareInfo cache. otherwise we would just create CompareInfo using _cultureData.
- _compareInfo ??= CompareInfo.GetCompareInfo(_cultureData.SortName);
-
- internal const DateTimeStyles InvalidDateTimeStyles = ~(DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite
- | DateTimeStyles.AllowInnerWhite | DateTimeStyles.NoCurrentDateDefault
- | DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal
- | DateTimeStyles.AssumeUniversal | DateTimeStyles.RoundtripKind);
-
- internal static void ValidateStyles(DateTimeStyles style, string parameterName)
- {
- if ((style & InvalidDateTimeStyles) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidDateTimeStyles, parameterName);
- }
- if (((style & (DateTimeStyles.AssumeLocal)) != 0) && ((style & (DateTimeStyles.AssumeUniversal)) != 0))
- {
- throw new ArgumentException(SR.Argument_ConflictingDateTimeStyles, parameterName);
- }
- if (((style & DateTimeStyles.RoundtripKind) != 0)
- && ((style & (DateTimeStyles.AssumeLocal | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)) != 0))
- {
- throw new ArgumentException(SR.Argument_ConflictingDateTimeRoundtripStyles, parameterName);
- }
- }
-
- /// <summary>
- /// Return the internal flag used in formatting and parsing.
- /// The flag can be used to indicate things like if genitive forms is used in
- /// this DTFi, or if leap year gets different month names.
- /// </summary>
- internal DateTimeFormatFlags FormatFlags => formatFlags != DateTimeFormatFlags.NotInitialized ? formatFlags : InitializeFormatFlags();
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private DateTimeFormatFlags InitializeFormatFlags()
- {
- // Build the format flags from the data in this DTFI
- formatFlags =
- (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagGenitiveMonth(
- MonthNames, InternalGetGenitiveMonthNames(false), AbbreviatedMonthNames, InternalGetGenitiveMonthNames(true)) |
- (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseSpaceInMonthNames(
- MonthNames, InternalGetGenitiveMonthNames(false), AbbreviatedMonthNames, InternalGetGenitiveMonthNames(true)) |
- (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseSpaceInDayNames(DayNames, AbbreviatedDayNames) |
- (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseHebrewCalendar((int)Calendar.ID);
- return formatFlags;
- }
-
- internal bool HasForceTwoDigitYears
- {
- get
- {
- switch (calendar.ID)
- {
- // Handle Japanese and Taiwan cases.
- // If is y/yy, do not get (year % 100). "y" will print
- // year without leading zero. "yy" will print year with two-digit in leading zero.
- // If pattern is yyy/yyyy/..., print year value with two-digit in leading zero.
- // So year 5 is "05", and year 125 is "125".
- // The reason for not doing (year % 100) is for Taiwan calendar.
- // If year 125, then output 125 and not 25.
- // Note: OS uses "yyyy" for Taiwan calendar by default.
- case (CalendarId.JAPAN):
- case (CalendarId.TAIWAN):
- return true;
- }
- return false;
- }
- }
-
- /// <summary>
- /// Returns whether the YearMonthAdjustment function has any fix-up work to do for this culture/calendar.
- /// </summary>
- internal bool HasYearMonthAdjustment => (FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0;
-
- /// <summary>
- /// This is a callback that the parser can make back into the DTFI to let it fiddle with special
- /// cases associated with that culture or calendar. Currently this only has special cases for
- /// the Hebrew calendar, but this could be extended to other cultures.
- ///
- /// The return value is whether the year and month are actually valid for this calendar.
- /// </summary>
- internal bool YearMonthAdjustment(ref int year, ref int month, bool parsedMonthName)
- {
- if ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0)
- {
- // Special rules to fix up the Hebrew year/month
-
- // When formatting, we only format up to the hundred digit of the Hebrew year, although Hebrew year is now over 5000.
- // E.g. if the year is 5763, we only format as 763.
- if (year < 1000)
- {
- year += 5000;
- }
-
- // Because we need to calculate leap year, we should fall out now for an invalid year.
- if (year < Calendar.GetYear(Calendar.MinSupportedDateTime) || year > Calendar.GetYear(Calendar.MaxSupportedDateTime))
- {
- return false;
- }
-
- // To handle leap months, the set of month names in the symbol table does not always correspond to the numbers.
- // For non-leap years, month 7 (Adar Bet) is not present, so we need to make using this month invalid and
- // shuffle the other months down.
- if (parsedMonthName)
- {
- if (!Calendar.IsLeapYear(year))
- {
- if (month >= 8)
- {
- month--;
- }
- else if (month == 7)
- {
- return false;
- }
- }
- }
- }
- return true;
- }
-
- // DateTimeFormatInfo tokenizer. This is used by DateTime.Parse() to break input string into tokens.
- private TokenHashValue[]? _dtfiTokenHash;
-
- private const int TOKEN_HASH_SIZE = 199;
- private const int SECOND_PRIME = 197;
- private const string dateSeparatorOrTimeZoneOffset = "-";
- private const string invariantDateSeparator = "/";
- private const string invariantTimeSeparator = ":";
-
- // Common Ignorable Symbols
- internal const string IgnorablePeriod = ".";
- internal const string IgnorableComma = ",";
-
- // Year/Month/Day suffixes
- internal const string CJKYearSuff = "\u5e74";
- internal const string CJKMonthSuff = "\u6708";
- internal const string CJKDaySuff = "\u65e5";
-
- internal const string KoreanYearSuff = "\ub144";
- internal const string KoreanMonthSuff = "\uc6d4";
- internal const string KoreanDaySuff = "\uc77c";
-
- internal const string KoreanHourSuff = "\uc2dc";
- internal const string KoreanMinuteSuff = "\ubd84";
- internal const string KoreanSecondSuff = "\ucd08";
-
- internal const string CJKHourSuff = "\u6642";
- internal const string ChineseHourSuff = "\u65f6";
-
- internal const string CJKMinuteSuff = "\u5206";
- internal const string CJKSecondSuff = "\u79d2";
-
- internal const string JapaneseEraStart = "\u5143";
-
- internal const string LocalTimeMark = "T";
-
- internal const string GMTName = "GMT";
- internal const string ZuluName = "Z";
-
- internal const string KoreanLangName = "ko";
- internal const string JapaneseLangName = "ja";
- internal const string EnglishLangName = "en";
-
- private static volatile DateTimeFormatInfo? s_jajpDTFI;
- private static volatile DateTimeFormatInfo? s_zhtwDTFI;
-
- /// <summary>
- /// Create a Japanese DTFI which uses JapaneseCalendar. This is used to parse
- /// date string with Japanese era name correctly even when the supplied DTFI
- /// does not use Japanese calendar.
- /// The created instance is stored in global s_jajpDTFI.
- /// </summary>
- internal static DateTimeFormatInfo GetJapaneseCalendarDTFI()
- {
- DateTimeFormatInfo? temp = s_jajpDTFI;
- if (temp == null)
- {
- temp = new CultureInfo("ja-JP", false).DateTimeFormat;
- temp.Calendar = JapaneseCalendar.GetDefaultInstance();
- s_jajpDTFI = temp;
- }
- return temp;
- }
-
- /// <summary>
- /// Create a Taiwan DTFI which uses TaiwanCalendar. This is used to parse
- /// date string with era name correctly even when the supplied DTFI
- /// does not use Taiwan calendar.
- /// The created instance is stored in global s_zhtwDTFI.
- /// </summary>
- internal static DateTimeFormatInfo GetTaiwanCalendarDTFI()
- {
- DateTimeFormatInfo? temp = s_zhtwDTFI;
- if (temp == null)
- {
- temp = new CultureInfo("zh-TW", false).DateTimeFormat;
- temp.Calendar = TaiwanCalendar.GetDefaultInstance();
- s_zhtwDTFI = temp;
- }
- return temp;
- }
-
- /// <summary>
- /// DTFI properties should call this when the setter are called.
- /// </summary>
- private void ClearTokenHashTable()
- {
- _dtfiTokenHash = null;
- formatFlags = DateTimeFormatFlags.NotInitialized;
- }
-
- internal TokenHashValue[] CreateTokenHashTable()
- {
- TokenHashValue[]? temp = _dtfiTokenHash;
- if (temp == null)
- {
- temp = new TokenHashValue[TOKEN_HASH_SIZE];
-
- bool koreanLanguage = LanguageName.Equals(KoreanLangName);
-
- string sep = TimeSeparator.Trim();
- if (IgnorableComma != sep) InsertHash(temp, IgnorableComma, TokenType.IgnorableSymbol, 0);
- if (IgnorablePeriod != sep) InsertHash(temp, IgnorablePeriod, TokenType.IgnorableSymbol, 0);
-
- if (KoreanHourSuff != sep && CJKHourSuff != sep && ChineseHourSuff != sep)
- {
- //
- // On the Macintosh, the default TimeSeparator is identical to the KoreanHourSuff, CJKHourSuff, or ChineseHourSuff for some cultures like
- // ja-JP and ko-KR. In these cases having the same symbol inserted into the hash table with multiple TokenTypes causes undesirable
- // DateTime.Parse behavior. For instance, the DateTimeFormatInfo.Tokenize() method might return SEP_DateOrOffset for KoreanHourSuff
- // instead of SEP_HourSuff.
- //
- InsertHash(temp, TimeSeparator, TokenType.SEP_Time, 0);
- }
-
- InsertHash(temp, AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
- InsertHash(temp, PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
-
- if (LanguageName.Equals("sq"))
- {
- // Albanian allows time formats like "12:00.PD"
- InsertHash(temp, IgnorablePeriod + AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
- InsertHash(temp, IgnorablePeriod + PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
- }
-
- // CJK suffix
- InsertHash(temp, CJKYearSuff, TokenType.SEP_YearSuff, 0);
- InsertHash(temp, KoreanYearSuff, TokenType.SEP_YearSuff, 0);
- InsertHash(temp, CJKMonthSuff, TokenType.SEP_MonthSuff, 0);
- InsertHash(temp, KoreanMonthSuff, TokenType.SEP_MonthSuff, 0);
- InsertHash(temp, CJKDaySuff, TokenType.SEP_DaySuff, 0);
- InsertHash(temp, KoreanDaySuff, TokenType.SEP_DaySuff, 0);
-
- InsertHash(temp, CJKHourSuff, TokenType.SEP_HourSuff, 0);
- InsertHash(temp, ChineseHourSuff, TokenType.SEP_HourSuff, 0);
- InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0);
- InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0);
-
- if (!LocalAppContextSwitches.EnforceLegacyJapaneseDateParsing && Calendar.ID == CalendarId.JAPAN)
- {
- // We need to support parsing the dates has the start of era symbol which means it is year 1 in the era.
- // The start of era symbol has to be followed by the year symbol suffix, otherwise it would be invalid date.
- InsertHash(temp, JapaneseEraStart, TokenType.YearNumberToken, 1);
- InsertHash(temp, "(", TokenType.IgnorableSymbol, 0);
- InsertHash(temp, ")", TokenType.IgnorableSymbol, 0);
- }
-
- // TODO: This ignores other custom cultures that might want to do something similar
- if (koreanLanguage)
- {
- // Korean suffix
- InsertHash(temp, KoreanHourSuff, TokenType.SEP_HourSuff, 0);
- InsertHash(temp, KoreanMinuteSuff, TokenType.SEP_MinuteSuff, 0);
- InsertHash(temp, KoreanSecondSuff, TokenType.SEP_SecondSuff, 0);
- }
-
- if (LanguageName.Equals("ky"))
- {
- // For some cultures, the date separator works more like a comma, being allowed before or after any date part
- InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.IgnorableSymbol, 0);
- }
- else
- {
- InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0);
- }
-
- // We need to rescan the date words since we're always synthetic
- DateTimeFormatInfoScanner scanner = new DateTimeFormatInfoScanner();
- string[]? dateWords = scanner.GetDateWordsOfDTFI(this);
-
- // Ensure the formatflags is initialized.
- _ = FormatFlags;
-
- // For some cultures, the date separator works more like a comma, being allowed before or after any date part.
- // In these cultures, we do not use normal date separator since we disallow date separator after a date terminal state.
- // This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol.
- bool useDateSepAsIgnorableSymbol = false;
-
- if (dateWords != null)
- {
- // There are DateWords. It could be a real date word (such as "de"), or a monthPostfix.
- // The monthPostfix starts with '\xfffe' (MonthPostfixChar), followed by the real monthPostfix.
- for (int i = 0; i < dateWords.Length; i++)
- {
- switch (dateWords[i][0])
- {
- // This is a month postfix
- case DateTimeFormatInfoScanner.MonthPostfixChar:
- // Get the real month postfix.
- ReadOnlySpan<char> monthPostfix = dateWords[i].AsSpan(1);
- // Add the month name + postfix into the token.
- AddMonthNames(temp, monthPostfix);
- break;
- case DateTimeFormatInfoScanner.IgnorableSymbolChar:
- string symbol = dateWords[i].Substring(1);
- InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0);
- if (DateSeparator.Trim(null).Equals(symbol))
- {
- // The date separator is the same as the ignorable symbol.
- useDateSepAsIgnorableSymbol = true;
- }
- break;
- default:
- InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0);
- // TODO: This ignores similar custom cultures
- if (LanguageName.Equals("eu"))
- {
- // Basque has date words with leading dots
- InsertHash(temp, IgnorablePeriod + dateWords[i], TokenType.DateWordToken, 0);
- }
- break;
- }
- }
- }
-
- if (!useDateSepAsIgnorableSymbol)
- {
- // Use the normal date separator.
- InsertHash(temp, DateSeparator, TokenType.SEP_Date, 0);
- }
- // Add the regular month names.
- AddMonthNames(temp);
-
- // Add the abbreviated month names.
- for (int i = 1; i <= 13; i++)
- {
- InsertHash(temp, GetAbbreviatedMonthName(i), TokenType.MonthToken, i);
- }
-
- if ((FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
- {
- string [] genitiveMonthNames = InternalGetGenitiveMonthNames(abbreviated: false);
- string [] abbreviatedGenitiveMonthNames = InternalGetGenitiveMonthNames(abbreviated: true);
-
- for (int i = 1; i <= 13; i++)
- {
- InsertHash(temp, genitiveMonthNames[i - 1], TokenType.MonthToken, i);
- InsertHash(temp, abbreviatedGenitiveMonthNames[i - 1], TokenType.MonthToken, i);
- }
- }
-
- if ((FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0)
- {
- for (int i = 1; i <= 13; i++)
- {
- string str = InternalGetMonthName(i, MonthNameStyles.LeapYear, false);
- InsertHash(temp, str, TokenType.MonthToken, i);
- }
- }
-
- for (int i = 0; i < 7; i++)
- {
- // We have to call public methods here to work with inherited DTFI.
- string str = GetDayName((DayOfWeek)i);
- InsertHash(temp, str, TokenType.DayOfWeekToken, i);
-
- str = GetAbbreviatedDayName((DayOfWeek)i);
- InsertHash(temp, str, TokenType.DayOfWeekToken, i);
- }
-
- int[] eras = calendar.Eras;
- for (int i = 1; i <= eras.Length; i++)
- {
- InsertHash(temp, GetEraName(i), TokenType.EraToken, i);
- InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i);
- }
-
- if (LanguageName.Equals(JapaneseLangName))
- {
- // Japanese allows day of week forms like: "(Tue)"
- for (int i = 0; i < 7; i++)
- {
- string specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
- InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i);
- }
- if (Calendar.GetType() != typeof(JapaneseCalendar))
- {
- // Special case for Japanese. If this is a Japanese DTFI, and the calendar is not Japanese calendar,
- // we will check Japanese Era name as well when the calendar is Gregorian.
- DateTimeFormatInfo jaDtfi = GetJapaneseCalendarDTFI();
- for (int i = 1; i <= jaDtfi.Calendar.Eras.Length; i++)
- {
- InsertHash(temp, jaDtfi.GetEraName(i), TokenType.JapaneseEraToken, i);
- InsertHash(temp, jaDtfi.GetAbbreviatedEraName(i), TokenType.JapaneseEraToken, i);
- // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1.
- InsertHash(temp, jaDtfi.AbbreviatedEnglishEraNames[i - 1], TokenType.JapaneseEraToken, i);
- }
- }
- }
- // TODO: This prohibits similar custom cultures, but we hard coded the name
- else if (CultureName.Equals("zh-TW"))
- {
- DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI();
- for (int i = 1; i <= twDtfi.Calendar.Eras.Length; i++)
- {
- if (twDtfi.GetEraName(i).Length > 0)
- {
- InsertHash(temp, twDtfi.GetEraName(i), TokenType.TEraToken, i);
- }
- }
- }
-
- InsertHash(temp, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
- InsertHash(temp, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
-
- // Add invariant month names and day names.
- for (int i = 1; i <= 12; i++)
- {
- // We have to call public methods here to work with inherited DTFI.
- // Insert the month name first, so that they are at the front of abbreviated
- // month names.
- string str = InvariantInfo.GetMonthName(i);
- InsertHash(temp, str, TokenType.MonthToken, i);
- str = InvariantInfo.GetAbbreviatedMonthName(i);
- InsertHash(temp, str, TokenType.MonthToken, i);
- }
-
- for (int i = 0; i < 7; i++)
- {
- // We have to call public methods here to work with inherited DTFI.
- string str = InvariantInfo.GetDayName((DayOfWeek)i);
- InsertHash(temp, str, TokenType.DayOfWeekToken, i);
-
- str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i);
- InsertHash(temp, str, TokenType.DayOfWeekToken, i);
- }
-
- for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++)
- {
- // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1.
- InsertHash(temp, AbbreviatedEnglishEraNames[i], TokenType.EraToken, i + 1);
- }
-
- InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0);
- InsertHash(temp, GMTName, TokenType.TimeZoneToken, 0);
- InsertHash(temp, ZuluName, TokenType.TimeZoneToken, 0);
-
- InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0);
- InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0);
-
- _dtfiTokenHash = temp;
- }
- return temp;
- }
-
- private void AddMonthNames(TokenHashValue[] temp, ReadOnlySpan<char> monthPostfix = default)
- {
- for (int i = 1; i <= 13; i++)
- {
- // We have to call public methods here to work with inherited DTFI.
- // Insert the month name first, so that they are at the front of abbreviated
- // month names.
- string str = GetMonthName(i);
- if (str.Length > 0)
- {
- if (!monthPostfix.IsEmpty)
- {
- // Insert the month name with the postfix first, so it can be matched first.
- InsertHash(temp, string.Concat(str, monthPostfix), TokenType.MonthToken, i);
- }
- else
- {
- InsertHash(temp, str, TokenType.MonthToken, i);
- }
- }
- str = GetAbbreviatedMonthName(i);
- InsertHash(temp, str, TokenType.MonthToken, i);
- }
- }
-
- /// <summary>
- /// Try to parse the current word to see if it is a Hebrew number.
- /// Tokens will be updated accordingly.
- /// This is called by the Lexer of DateTime.Parse().
- ///
- /// Unlike most of the functions in this class, the return value indicates
- /// whether or not it started to parse. The badFormat parameter indicates
- /// if parsing began, but the format was bad.
- /// </summary>
- private static bool TryParseHebrewNumber(
- ref __DTString str,
- out bool badFormat,
- out int number)
- {
- number = -1;
- badFormat = false;
-
- int i = str.Index;
- if (!HebrewNumber.IsDigit(str.Value[i]))
- {
- // If the current character is not a Hebrew digit, just return false.
- // There is no chance that we can parse a valid Hebrew number from here.
- return false;
- }
- // The current character is a Hebrew digit. Try to parse this word as a Hebrew number.
- HebrewNumberParsingContext context = new HebrewNumberParsingContext(0);
- HebrewNumberParsingState state;
-
- do
- {
- state = HebrewNumber.ParseByChar(str.Value[i++], ref context);
- switch (state)
- {
- case HebrewNumberParsingState.InvalidHebrewNumber: // Not a valid Hebrew number.
- case HebrewNumberParsingState.NotHebrewDigit: // The current character is not a Hebrew digit character.
- // Break out so that we don't continue to try parse this as a Hebrew number.
- return false;
- }
- } while (i < str.Value.Length && (state != HebrewNumberParsingState.FoundEndOfHebrewNumber));
-
- // When we are here, we are either at the end of the string, or we find a valid Hebrew number.
- Debug.Assert(state == HebrewNumberParsingState.ContinueParsing || state == HebrewNumberParsingState.FoundEndOfHebrewNumber,
- "Invalid returned state from HebrewNumber.ParseByChar()");
-
- if (state != HebrewNumberParsingState.FoundEndOfHebrewNumber)
- {
- // We reach end of the string but we can't find a terminal state in parsing Hebrew number.
- return false;
- }
-
- // We have found a valid Hebrew number. Update the index.
- str.Advance(i - str.Index);
-
- // Get the final Hebrew number value from the HebrewNumberParsingContext.
- number = context.result;
-
- return true;
- }
-
- private static bool IsHebrewChar(char ch)
- {
- return ch >= '\x0590' && ch <= '\x05ff';
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private bool IsAllowedJapaneseTokenFollowedByNonSpaceLetter(string tokenString, char nextCh)
- {
- // Allow the parser to recognize the case when having some date part followed by JapaneseEraStart "\u5143"
- // without spaces in between. e.g. Era name followed by \u5143 in the date formats ggy.
- // Also, allow recognizing the year suffix symbol "\u5e74" followed the JapaneseEraStart "\u5143"
- if (!LocalAppContextSwitches.EnforceLegacyJapaneseDateParsing && Calendar.ID == CalendarId.JAPAN &&
- (
- // something like ggy, era followed by year and the year is specified using the JapaneseEraStart "\u5143"
- nextCh == JapaneseEraStart[0] ||
- // JapaneseEraStart followed by year suffix "\u5143"
- (tokenString == JapaneseEraStart && nextCh == CJKYearSuff[0])
- ))
- {
- return true;
- }
- return false;
- }
-
- internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue,
- ref __DTString str)
- {
- tokenType = TokenType.UnknownToken;
- tokenValue = 0;
-
- TokenHashValue value;
- Debug.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length");
-
- char ch = str.m_current;
- bool isLetter = char.IsLetter(ch);
- if (isLetter)
- {
- ch = Culture.TextInfo.ToLower(ch);
- if (IsHebrewChar(ch) && TokenMask == TokenType.RegularTokenMask)
- {
- bool badFormat;
- if (TryParseHebrewNumber(ref str, out badFormat, out tokenValue))
- {
- if (badFormat)
- {
- tokenType = TokenType.UnknownToken;
- return false;
- }
- // This is a Hebrew number.
- // Do nothing here. TryParseHebrewNumber() will update token accordingly.
- tokenType = TokenType.HebrewNumber;
- return true;
- }
- }
- }
-
- int hashcode = ch % TOKEN_HASH_SIZE;
- int hashProbe = 1 + ch % SECOND_PRIME;
- int remaining = str.Length - str.Index;
- int i = 0;
-
- TokenHashValue[] hashTable = _dtfiTokenHash ?? CreateTokenHashTable();
- do
- {
- value = hashTable[hashcode];
- if (value == null)
- {
- // Not found.
- break;
- }
- // Check this value has the right category (regular token or separator token) that we are looking for.
- if (((int)value.tokenType & (int)TokenMask) > 0 && value.tokenString.Length <= remaining)
- {
- bool compareStrings = true;
- if (isLetter)
- {
- // If this token starts with a letter, make sure that we won't allow partial match. So you can't tokenize "MarchWed" separately.
- // Also an optimization to avoid string comparison
- int nextCharIndex = str.Index + value.tokenString.Length;
- if (nextCharIndex > str.Length)
- {
- compareStrings = false;
- }
- else if (nextCharIndex < str.Length)
- {
- // Check word boundary. The next character should NOT be a letter.
- char nextCh = str.Value[nextCharIndex];
- compareStrings = !char.IsLetter(nextCh) || IsAllowedJapaneseTokenFollowedByNonSpaceLetter(value.tokenString, nextCh);
- }
- }
-
- if (compareStrings &&
- ((value.tokenString.Length == 1 && str.Value[str.Index] == value.tokenString[0]) ||
- Culture.CompareInfo.Compare(str.Value.Slice(str.Index, value.tokenString.Length), value.tokenString, CompareOptions.IgnoreCase) == 0))
- {
- tokenType = value.tokenType & TokenMask;
- tokenValue = value.tokenValue;
- str.Advance(value.tokenString.Length);
- return true;
- }
- else if ((value.tokenType == TokenType.MonthToken && HasSpacesInMonthNames) ||
- (value.tokenType == TokenType.DayOfWeekToken && HasSpacesInDayNames))
- {
- // For month or day token, we will match the names which have spaces.
- int matchStrLen = 0;
- if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen))
- {
- tokenType = value.tokenType & TokenMask;
- tokenValue = value.tokenValue;
- str.Advance(matchStrLen);
- return true;
- }
- }
- }
- i++;
- hashcode += hashProbe;
- if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
- } while (i < TOKEN_HASH_SIZE);
-
- return false;
- }
-
- private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, string str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe)
- {
- // Remember the current slot.
- TokenHashValue previousNode = hashTable[hashcode];
-
- // Insert the new node into the current slot.
- hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue);
-
- while (++pos < TOKEN_HASH_SIZE)
- {
- hashcode += hashProbe;
- if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
- // Remember this slot
- TokenHashValue temp = hashTable[hashcode];
-
- if (temp != null && Culture.TextInfo.ToLower(temp.tokenString[0]) != ch)
- {
- continue;
- }
- // Put the previous slot into this slot.
- hashTable[hashcode] = previousNode;
- if (temp == null)
- {
- // Done
- return;
- }
- previousNode = temp;
- }
- Debug.Fail("The hashtable is full. This should not happen.");
- }
-
- private void InsertHash(TokenHashValue[] hashTable, string str, TokenType tokenType, int tokenValue)
- {
- // The month of the 13th month is allowed to be null, so make sure that we ignore null value here.
- if (string.IsNullOrEmpty(str))
- {
- return;
- }
-
- TokenHashValue value;
- int i = 0;
- // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by
- // DateTime.Parse().
- if (char.IsWhiteSpace(str[0]) || char.IsWhiteSpace(str[^1]))
- {
- str = str.Trim(null); // Trim white space characters.
- // Could have space for separators
- if (str.Length == 0)
- {
- return;
- }
- }
-
- char ch = Culture.TextInfo.ToLower(str[0]);
- int hashcode = ch % TOKEN_HASH_SIZE;
- int hashProbe = 1 + ch % SECOND_PRIME;
- do
- {
- value = hashTable[hashcode];
- if (value == null)
- {
- hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue);
- return;
- }
- else
- {
- // Collision happens. Find another slot.
- if (str.Length >= value.tokenString.Length)
- {
- // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of
- // the shorter ones.
- if (CompareStringIgnoreCaseOptimized(str, 0, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length))
- {
- if (str.Length > value.tokenString.Length)
- {
- // The str to be inserted has the same prefix as the current token, and str is longer.
- // Insert str into this node, and shift every node behind it.
- InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe);
- return;
- }
- else
- {
- // Same token. If they have different types (regular token vs separator token). Add them.
- // If we have the same regular token or separator token in the hash already, do NOT update the hash.
- // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash.
-
- // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet.
- // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet.
-
- int nTokenType = (int)tokenType;
- int nCurrentTokenTypeInHash = (int)value.tokenType;
-
- // The folowing is the fix for the issue of throwing FormatException when "mar" is passed in string of the short date format dd/MMM/yyyy for es-MX
- if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) ||
- ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0))
- {
- value.tokenType |= tokenType;
- if (tokenValue != 0)
- {
- value.tokenValue = tokenValue;
- }
- }
- // The token to be inserted is already in the table. Skip it.
- return;
- }
- }
- }
- }
- i++;
- hashcode += hashProbe;
- if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
- } while (i < TOKEN_HASH_SIZE);
- Debug.Fail("The hashtable is full. This should not happen.");
- }
-
- private bool CompareStringIgnoreCaseOptimized(string string1, int offset1, int length1, string string2, int offset2, int length2)
- {
- // Optimize for one character cases which are common due to date and time separators (/ and :)
- if (length1 == 1 && length2 == 1 && string1[offset1] == string2[offset2])
- {
- return true;
- }
-
- return Culture.CompareInfo.Compare(string1, offset1, length1, string2, offset2, length2, CompareOptions.IgnoreCase) == 0;
- }
-
- internal class TokenHashValue
- {
- internal string tokenString;
- internal TokenType tokenType;
- internal int tokenValue;
-
- internal TokenHashValue(string tokenString, TokenType tokenType, int tokenValue)
- {
- this.tokenString = tokenString;
- this.tokenType = tokenType;
- this.tokenValue = tokenValue;
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
deleted file mode 100644
index 1ecdc35eac9..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
+++ /dev/null
@@ -1,712 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-////////////////////////////////////////////////////////////////////////////
-//
-// DateTimeFormatInfoScanner
-//
-// Scan a specified DateTimeFormatInfo to search for data used in DateTime.Parse()
-//
-// The data includes:
-//
-// DateWords: such as "de" used in es-ES (Spanish) LongDatePattern.
-// Postfix: such as "ta" used in fi-FI after the month name.
-//
-// This class is shared among mscorlib.dll and sysglobl.dll.
-// Use conditional CULTURE_AND_REGIONINFO_BUILDER_ONLY to differentiate between
-// methods for mscorlib.dll and sysglobl.dll.
-//
-////////////////////////////////////////////////////////////////////////////
-
-using System.Collections.Generic;
-using System.Text;
-
-namespace System.Globalization
-{
- // from LocaleEx.txt header
- // IFORMATFLAGS
- internal enum FORMATFLAGS
- {
- None = 0x00000000,
- UseGenitiveMonth = 0x00000001,
- UseLeapYearMonth = 0x00000002,
- UseSpacesInMonthNames = 0x00000004,
- UseHebrewParsing = 0x00000008,
- UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names.
- UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers.
- }
-
- internal enum CalendarId : ushort
- {
- UNINITIALIZED_VALUE = 0,
- GREGORIAN = 1, // Gregorian (localized) calendar
- GREGORIAN_US = 2, // Gregorian (U.S.) calendar
- JAPAN = 3, // Japanese Emperor Era calendar
- /* SSS_WARNINGS_OFF */
- TAIWAN = 4, // Taiwan Era calendar /* SSS_WARNINGS_ON */
- KOREA = 5, // Korean Tangun Era calendar
- HIJRI = 6, // Hijri (Arabic Lunar) calendar
- THAI = 7, // Thai calendar
- HEBREW = 8, // Hebrew (Lunar) calendar
- GREGORIAN_ME_FRENCH = 9, // Gregorian Middle East French calendar
- GREGORIAN_ARABIC = 10, // Gregorian Arabic calendar
- GREGORIAN_XLIT_ENGLISH = 11, // Gregorian Transliterated English calendar
- GREGORIAN_XLIT_FRENCH = 12,
- // Note that all calendars after this point are MANAGED ONLY for now.
- JULIAN = 13,
- JAPANESELUNISOLAR = 14,
- CHINESELUNISOLAR = 15,
- SAKA = 16, // reserved to match Office but not implemented in our code
- LUNAR_ETO_CHN = 17, // reserved to match Office but not implemented in our code
- LUNAR_ETO_KOR = 18, // reserved to match Office but not implemented in our code
- LUNAR_ETO_ROKUYOU = 19, // reserved to match Office but not implemented in our code
- KOREANLUNISOLAR = 20,
- TAIWANLUNISOLAR = 21,
- PERSIAN = 22,
- UMALQURA = 23,
- LAST_CALENDAR = 23 // Last calendar ID
- }
-
- internal class DateTimeFormatInfoScanner
- {
- // Special prefix-like flag char in DateWord array.
-
- // Use char in PUA area since we won't be using them in real data.
- // The char used to tell a read date word or a month postfix. A month postfix
- // is "ta" in the long date pattern like "d. MMMM'ta 'yyyy" for fi-FI.
- // In this case, it will be stored as "\xfffeta" in the date word array.
- internal const char MonthPostfixChar = '\xe000';
-
- // Add ignorable symbol in a DateWord array.
-
- // hu-HU has:
- // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd
- // long date pattern: yyyy. MMMM d.
- // Here, "." is the date separator (derived from short date pattern). However,
- // "." also appear at the end of long date pattern. In this case, we just
- // "." as ignorable symbol so that the DateTime.Parse() state machine will not
- // treat the additional date separator at the end of y,m,d pattern as an error
- // condition.
- internal const char IgnorableSymbolChar = '\xe001';
-
- // Known CJK suffix
- internal const string CJKYearSuff = "\u5e74";
- internal const string CJKMonthSuff = "\u6708";
- internal const string CJKDaySuff = "\u65e5";
-
- internal const string KoreanYearSuff = "\ub144";
- internal const string KoreanMonthSuff = "\uc6d4";
- internal const string KoreanDaySuff = "\uc77c";
-
- internal const string KoreanHourSuff = "\uc2dc";
- internal const string KoreanMinuteSuff = "\ubd84";
- internal const string KoreanSecondSuff = "\ucd08";
-
- internal const string CJKHourSuff = "\u6642";
- internal const string ChineseHourSuff = "\u65f6";
-
- internal const string CJKMinuteSuff = "\u5206";
- internal const string CJKSecondSuff = "\u79d2";
-
- // The collection fo date words & postfix.
- internal List<string> m_dateWords = new List<string>();
- // Hashtable for the known words.
- private static volatile Dictionary<string, string>? s_knownWords;
-
- private static Dictionary<string, string> KnownWords =>
- s_knownWords ??=
- new Dictionary<string, string>(16)
- {
- // Add known words into the hash table.
-
- // Skip these special symbols.
- { "/", string.Empty },
- { "-", string.Empty },
- { ".", string.Empty },
-
- // Skip known CJK suffixes.
- { CJKYearSuff, string.Empty },
- { CJKMonthSuff, string.Empty },
- { CJKDaySuff, string.Empty },
- { KoreanYearSuff, string.Empty },
- { KoreanMonthSuff, string.Empty },
- { KoreanDaySuff, string.Empty },
- { KoreanHourSuff, string.Empty },
- { KoreanMinuteSuff, string.Empty },
- { KoreanSecondSuff, string.Empty },
- { CJKHourSuff, string.Empty },
- { ChineseHourSuff, string.Empty },
- { CJKMinuteSuff, string.Empty },
- { CJKSecondSuff, string.Empty }
- };
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Parameters:
- // pattern: The pattern to be scanned.
- // currentIndex: the current index to start the scan.
- //
- // Returns:
- // Return the index with the first character that is a letter, which will
- // be the start of a date word.
- // Note that the index can be pattern.Length if we reach the end of the string.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static int SkipWhiteSpacesAndNonLetter(string pattern, int currentIndex)
- {
- while (currentIndex < pattern.Length)
- {
- char ch = pattern[currentIndex];
- if (ch == '\\')
- {
- // Escaped character. Look ahead one character.
- currentIndex++;
- if (currentIndex < pattern.Length)
- {
- ch = pattern[currentIndex];
- if (ch == '\'')
- {
- // Skip the leading single quote. We will
- // stop at the first letter.
- continue;
- }
- // Fall thru to check if this is a letter.
- }
- else
- {
- // End of string
- break;
- }
- }
- if (char.IsLetter(ch) || ch == '\'' || ch == '.')
- {
- break;
- }
- // Skip the current char since it is not a letter.
- currentIndex++;
- }
- return currentIndex;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // A helper to add the found date word or month postfix into ArrayList for date words.
- //
- // Parameters:
- // formatPostfix: What kind of postfix this is.
- // Possible values:
- // null: This is a regular date word
- // "MMMM": month postfix
- // word: The date word or postfix to be added.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal void AddDateWordOrPostfix(string? formatPostfix, string str)
- {
- if (str.Length > 0)
- {
- // Some cultures use . like an abbreviation
- if (str.Equals("."))
- {
- AddIgnorableSymbols(".");
- return;
- }
-
- if (!KnownWords.TryGetValue(str, out _))
- {
- m_dateWords ??= new List<string>();
-
- if (formatPostfix == "MMMM")
- {
- // Add the word into the ArrayList as "\xfffe" + real month postfix.
- string temp = MonthPostfixChar + str;
- if (!m_dateWords.Contains(temp))
- {
- m_dateWords.Add(temp);
- }
- }
- else
- {
- if (!m_dateWords.Contains(str))
- {
- m_dateWords.Add(str);
- }
- if (str[^1] == '.')
- {
- // Old version ignore the trailing dot in the date words. Support this as well.
- string strWithoutDot = str[0..^1];
- if (!m_dateWords.Contains(strWithoutDot))
- {
- m_dateWords.Add(strWithoutDot);
- }
- }
- }
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Scan the pattern from the specified index and add the date word/postfix
- // when appropriate.
- //
- // Parameters:
- // pattern: The pattern to be scanned.
- // index: The starting index to be scanned.
- // formatPostfix: The kind of postfix to be scanned.
- // Possible values:
- // null: This is a regular date word
- // "MMMM": month postfix
- //
- //
- ////////////////////////////////////////////////////////////////////////////
- internal int AddDateWords(string pattern, int index, string? formatPostfix)
- {
- // Skip any whitespaces so we will start from a letter.
- int newIndex = SkipWhiteSpacesAndNonLetter(pattern, index);
- if (newIndex != index && formatPostfix != null)
- {
- // There are whitespaces. This will not be a postfix.
- formatPostfix = null;
- }
- index = newIndex;
-
- // This is the first char added into dateWord.
- // Skip all non-letter character. We will add the first letter into DateWord.
- StringBuilder dateWord = new StringBuilder();
- // We assume that date words should start with a letter.
- // Skip anything until we see a letter.
-
- while (index < pattern.Length)
- {
- char ch = pattern[index];
- if (ch == '\'')
- {
- // We have seen the end of quote. Add the word if we do not see it before,
- // and break the while loop.
- AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
- index++;
- break;
- }
- else if (ch == '\\')
- {
- //
- // Escaped character. Look ahead one character
- //
-
- // Skip escaped backslash.
- index++;
- if (index < pattern.Length)
- {
- dateWord.Append(pattern[index]);
- index++;
- }
- }
- else if (char.IsWhiteSpace(ch))
- {
- // Found a whitespace. We have to add the current date word/postfix.
- AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
- if (formatPostfix != null)
- {
- // Done with postfix. The rest will be regular date word.
- formatPostfix = null;
- }
- // Reset the dateWord.
- dateWord.Length = 0;
- index++;
- }
- else
- {
- dateWord.Append(ch);
- index++;
- }
- }
- return index;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // A simple helper to find the repeat count for a specified char.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static int ScanRepeatChar(string pattern, char ch, int index, out int count)
- {
- count = 1;
- while (++index < pattern.Length && pattern[index] == ch)
- {
- count++;
- }
- // Return the updated position.
- return index;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Add the text that is a date separator but is treated like ignorable symbol.
- // E.g.
- // hu-HU has:
- // short date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd
- // long date pattern: yyyy. MMMM d.
- // Here, "." is the date separator (derived from short date pattern). However,
- // "." also appear at the end of long date pattern. In this case, we just
- // "." as ignorable symbol so that the DateTime.Parse() state machine will not
- // treat the additional date separator at the end of y,m,d pattern as an error
- // condition.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal void AddIgnorableSymbols(string? text)
- {
- if (m_dateWords == null)
- {
- // Create the date word array.
- m_dateWords = new List<string>();
- }
- // Add the ignorable symbol into the ArrayList.
- string temp = IgnorableSymbolChar + text;
- if (!m_dateWords.Contains(temp))
- {
- m_dateWords.Add(temp);
- }
- }
-
- //
- // Flag used to trace the date patterns (yy/yyyyy/M/MM/MMM/MMM/d/dd) that we have seen.
- //
- private enum FoundDatePattern
- {
- None = 0x0000,
- FoundYearPatternFlag = 0x0001,
- FoundMonthPatternFlag = 0x0002,
- FoundDayPatternFlag = 0x0004,
- FoundYMDPatternFlag = 0x0007, // FoundYearPatternFlag | FoundMonthPatternFlag | FoundDayPatternFlag;
- }
-
- // Check if we have found all of the year/month/day pattern.
- private FoundDatePattern _ymdFlags = FoundDatePattern.None;
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Given a date format pattern, scan for date word or postfix.
- //
- // A date word should be always put in a single quoted string. And it will
- // start from a letter, so whitespace and symbols will be ignored before
- // the first letter.
- //
- // Examples of date word:
- // 'de' in es-SP: dddd, dd' de 'MMMM' de 'yyyy
- // "\x0443." in bg-BG: dd.M.yyyy '\x0433.'
- //
- // Example of postfix:
- // month postfix:
- // "ta" in fi-FI: d. MMMM'ta 'yyyy
- // Currently, only month postfix is supported.
- //
- // Usage:
- // Always call this with Framework-style pattern, instead of Windows style pattern.
- // Windows style pattern uses '' for single quote, while .NET uses \'
- //
- ////////////////////////////////////////////////////////////////////////////
- internal void ScanDateWord(string pattern)
- {
- // Check if we have found all of the year/month/day pattern.
- _ymdFlags = FoundDatePattern.None;
-
- int i = 0;
- while (i < pattern.Length)
- {
- char ch = pattern[i];
- int chCount;
-
- switch (ch)
- {
- case '\'':
- // Find a beginning quote. Search until the end quote.
- i = AddDateWords(pattern, i + 1, null);
- break;
- case 'M':
- i = ScanRepeatChar(pattern, 'M', i, out chCount);
- if (chCount >= 4)
- {
- if (i < pattern.Length && pattern[i] == '\'')
- {
- i = AddDateWords(pattern, i + 1, "MMMM");
- }
- }
- _ymdFlags |= FoundDatePattern.FoundMonthPatternFlag;
- break;
- case 'y':
- i = ScanRepeatChar(pattern, 'y', i, out chCount);
- _ymdFlags |= FoundDatePattern.FoundYearPatternFlag;
- break;
- case 'd':
- i = ScanRepeatChar(pattern, 'd', i, out chCount);
- if (chCount <= 2)
- {
- // Only count "d" & "dd".
- // ddd, dddd are day names. Do not count them.
- _ymdFlags |= FoundDatePattern.FoundDayPatternFlag;
- }
- break;
- case '\\':
- // Found a escaped char not in a quoted string. Skip the current backslash
- // and its next character.
- i += 2;
- break;
- case '.':
- if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag)
- {
- // If we find a dot immediately after the we have seen all of the y, m, d pattern.
- // treat it as a ignroable symbol. Check for comments in AddIgnorableSymbols for
- // more details.
- AddIgnorableSymbols(".");
- _ymdFlags = FoundDatePattern.None;
- }
- i++;
- break;
- default:
- if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !char.IsWhiteSpace(ch))
- {
- // We are not seeing "." after YMD. Clear the flag.
- _ymdFlags = FoundDatePattern.None;
- }
- // We are not in quote. Skip the current character.
- i++;
- break;
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Given a DTFI, get all of the date words from date patterns and time patterns.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal string[]? GetDateWordsOfDTFI(DateTimeFormatInfo dtfi)
- {
- // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix.
- string[] datePatterns = dtfi.GetAllDateTimePatterns('D');
- int i;
-
- // Scan the long date patterns
- for (i = 0; i < datePatterns.Length; i++)
- {
- ScanDateWord(datePatterns[i]);
- }
-
- // Scan the short date patterns
- datePatterns = dtfi.GetAllDateTimePatterns('d');
- for (i = 0; i < datePatterns.Length; i++)
- {
- ScanDateWord(datePatterns[i]);
- }
- // Scan the YearMonth patterns.
- datePatterns = dtfi.GetAllDateTimePatterns('y');
- for (i = 0; i < datePatterns.Length; i++)
- {
- ScanDateWord(datePatterns[i]);
- }
-
- // Scan the month/day pattern
- ScanDateWord(dtfi.MonthDayPattern);
-
- // Scan the long time patterns.
- datePatterns = dtfi.GetAllDateTimePatterns('T');
- for (i = 0; i < datePatterns.Length; i++)
- {
- ScanDateWord(datePatterns[i]);
- }
-
- // Scan the short time patterns.
- datePatterns = dtfi.GetAllDateTimePatterns('t');
- for (i = 0; i < datePatterns.Length; i++)
- {
- ScanDateWord(datePatterns[i]);
- }
-
- string[]? result = null;
- if (m_dateWords != null && m_dateWords.Count > 0)
- {
- result = new string[m_dateWords.Count];
- for (i = 0; i < m_dateWords.Count; i++)
- {
- result[i] = m_dateWords[i];
- }
- }
- return result;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Scan the month names to see if genitive month names are used, and return
- // the format flag.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagGenitiveMonth(string[] monthNames, string[] genitveMonthNames, string[] abbrevMonthNames, string[] genetiveAbbrevMonthNames)
- {
- // If we have different names in regular and genitive month names, use genitive month flag.
- return (!EqualStringArrays(monthNames, genitveMonthNames) || !EqualStringArrays(abbrevMonthNames, genetiveAbbrevMonthNames))
- ? FORMATFLAGS.UseGenitiveMonth : 0;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Scan the month names to see if spaces are used or start with a digit, and return the format flag
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(string[] monthNames, string[] genitveMonthNames, string[] abbrevMonthNames, string[] genetiveAbbrevMonthNames)
- {
- FORMATFLAGS formatFlags = 0;
- formatFlags |= (ArrayElementsBeginWithDigit(monthNames) ||
- ArrayElementsBeginWithDigit(genitveMonthNames) ||
- ArrayElementsBeginWithDigit(abbrevMonthNames) ||
- ArrayElementsBeginWithDigit(genetiveAbbrevMonthNames)
- ? FORMATFLAGS.UseDigitPrefixInTokens : 0);
-
- formatFlags |= (ArrayElementsHaveSpace(monthNames) ||
- ArrayElementsHaveSpace(genitveMonthNames) ||
- ArrayElementsHaveSpace(abbrevMonthNames) ||
- ArrayElementsHaveSpace(genetiveAbbrevMonthNames)
- ? FORMATFLAGS.UseSpacesInMonthNames : 0);
- return formatFlags;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Scan the day names and set the correct format flag.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(string[] dayNames, string[] abbrevDayNames)
- {
- return (ArrayElementsHaveSpace(dayNames) ||
- ArrayElementsHaveSpace(abbrevDayNames))
- ? FORMATFLAGS.UseSpacesInDayNames : 0;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Check the calendar to see if it is HebrewCalendar and set the Hebrew format flag if necessary.
- //
- ////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseHebrewCalendar(int calID)
- {
- return calID == (int)CalendarId.HEBREW ?
- FORMATFLAGS.UseHebrewParsing | FORMATFLAGS.UseLeapYearMonth : 0;
- }
-
- //-----------------------------------------------------------------------------
- // EqualStringArrays
- // compares two string arrays and return true if all elements of the first
- // array equals to all elements of the second array.
- // otherwise it returns false.
- //-----------------------------------------------------------------------------
-
- private static bool EqualStringArrays(string[] array1, string[] array2)
- {
- // Shortcut if they're the same array
- if (array1 == array2)
- {
- return true;
- }
-
- // This is effectively impossible
- if (array1.Length != array2.Length)
- {
- return false;
- }
-
- // Check each string
- for (int i = 0; i < array1.Length; i++)
- {
- if (array1[i] != array2[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- //-----------------------------------------------------------------------------
- // ArrayElementsHaveSpace
- // It checks all input array elements if any of them has space character
- // returns true if found space character in one of the array elements.
- // otherwise returns false.
- //-----------------------------------------------------------------------------
-
- private static bool ArrayElementsHaveSpace(string[] array)
- {
- for (int i = 0; i < array.Length; i++)
- {
- // it is faster to check for space character manually instead of calling IndexOf
- // so we don't have to go to native code side.
- for (int j = 0; j < array[i].Length; j++)
- {
- if (char.IsWhiteSpace(array[i][j]))
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Check if any element of the array start with a digit.
- //
- ////////////////////////////////////////////////////////////////////////////
- private static bool ArrayElementsBeginWithDigit(string[] array)
- {
- for (int i = 0; i < array.Length; i++)
- {
- // it is faster to check for space character manually instead of calling IndexOf
- // so we don't have to go to native code side.
- if (array[i].Length > 0 &&
- array[i][0] >= '0' && array[i][0] <= '9')
- {
- int index = 1;
- while (index < array[i].Length && array[i][index] >= '0' && array[i][index] <= '9')
- {
- // Skip other digits.
- index++;
- }
- if (index == array[i].Length)
- {
- return false;
- }
-
- if (index == array[i].Length - 1)
- {
- // Skip known CJK month suffix.
- // CJK uses month name like "1\x6708", since \x6708 is a known month suffix,
- // we don't need the UseDigitPrefixInTokens since it is slower.
- switch (array[i][index])
- {
- case '\x6708': // CJKMonthSuff
- case '\xc6d4': // KoreanMonthSuff
- return false;
- }
- }
-
- if (index == array[i].Length - 4)
- {
- // Skip known CJK month suffix.
- // Starting with Windows 8, the CJK months for some cultures looks like: "1' \x6708'"
- // instead of just "1\x6708"
- if (array[i][index] == '\'' && array[i][index + 1] == ' ' &&
- array[i][index + 2] == '\x6708' && array[i][index + 3] == '\'')
- {
- return false;
- }
- }
- return true;
- }
- }
-
- return false;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
deleted file mode 100644
index 50002e6e04e..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
+++ /dev/null
@@ -1,6106 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Text;
-
-namespace System
-{
- internal static class DateTimeParse
- {
- internal const int MaxDateTimeNumberDigits = 8;
-
- internal delegate bool MatchNumberDelegate(ref __DTString str, int digitLen, out int result);
-
- internal static MatchNumberDelegate m_hebrewNumberParser = new MatchNumberDelegate(DateTimeParse.MatchHebrewDigits);
-
- internal static DateTime ParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style)
- {
- DateTimeResult result = default; // The buffer to store the parsing result.
- result.Init(s);
- if (TryParseExact(s, format, dtfi, style, ref result))
- {
- return result.parsedDate;
- }
- else
- {
- throw GetDateTimeParseException(ref result);
- }
- }
-
- internal static DateTime ParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
- {
- DateTimeResult result = default; // The buffer to store the parsing result.
- result.Init(s);
- result.flags |= ParseFlags.CaptureOffset;
- if (TryParseExact(s, format, dtfi, style, ref result))
- {
- offset = result.timeZoneOffset;
- return result.parsedDate;
- }
- else
- {
- throw GetDateTimeParseException(ref result);
- }
- }
-
- internal static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
- {
- DateTimeResult resultData = default; // The buffer to store the parsing result.
- resultData.Init(s);
-
- if (TryParseExact(s, format, dtfi, style, ref resultData))
- {
- result = resultData.parsedDate;
- return true;
- }
-
- result = DateTime.MinValue;
- return false;
- }
-
- internal static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
- {
- DateTimeResult resultData = default; // The buffer to store the parsing result.
- resultData.Init(s);
- resultData.flags |= ParseFlags.CaptureOffset;
-
- if (TryParseExact(s, format, dtfi, style, ref resultData))
- {
- result = resultData.parsedDate;
- offset = resultData.timeZoneOffset;
- return true;
- }
-
- result = DateTime.MinValue;
- offset = TimeSpan.Zero;
- return false;
- }
-
- internal static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
- {
- if (s.Length == 0)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDateTime));
- return false;
- }
-
- if (format.Length == 0)
- {
- result.SetBadFormatSpecifierFailure();
- return false;
- }
-
- Debug.Assert(dtfi != null, "dtfi == null");
-
- return DoStrictParse(s, format, style, dtfi, ref result);
- }
-
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
- DateTimeFormatInfo dtfi, DateTimeStyles style)
- {
- DateTimeResult result = default; // The buffer to store the parsing result.
- result.Init(s);
- if (TryParseExactMultiple(s, formats, dtfi, style, ref result))
- {
- return result.parsedDate;
- }
- else
- {
- throw GetDateTimeParseException(ref result);
- }
- }
-
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
- DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
- {
- DateTimeResult result = default; // The buffer to store the parsing result.
- result.Init(s);
- result.flags |= ParseFlags.CaptureOffset;
- if (TryParseExactMultiple(s, formats, dtfi, style, ref result))
- {
- offset = result.timeZoneOffset;
- return result.parsedDate;
- }
- else
- {
- throw GetDateTimeParseException(ref result);
- }
- }
-
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string?[]? formats,
- DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
- {
- DateTimeResult resultData = default; // The buffer to store the parsing result.
- resultData.Init(s);
- resultData.flags |= ParseFlags.CaptureOffset;
-
- if (TryParseExactMultiple(s, formats, dtfi, style, ref resultData))
- {
- result = resultData.parsedDate;
- offset = resultData.timeZoneOffset;
- return true;
- }
-
- result = DateTime.MinValue;
- offset = TimeSpan.Zero;
- return false;
- }
-
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string?[]? formats,
- DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
- {
- DateTimeResult resultData = default; // The buffer to store the parsing result.
- resultData.Init(s);
-
- if (TryParseExactMultiple(s, formats, dtfi, style, ref resultData))
- {
- result = resultData.parsedDate;
- return true;
- }
-
- result = DateTime.MinValue;
- return false;
- }
-
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string?[]? formats,
- DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
- {
- if (formats == null)
- {
- result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(formats));
- return false;
- }
-
- if (s.Length == 0)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDateTime));
- return false;
- }
-
- if (formats.Length == 0)
- {
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_NoFormatSpecifier));
- return false;
- }
-
- Debug.Assert(dtfi != null, "dtfi == null");
-
- //
- // Do a loop through the provided formats and see if we can parse successfully in
- // one of the formats.
- //
- for (int i = 0; i < formats.Length; i++)
- {
- if (formats[i] == null || formats[i]!.Length == 0) // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
- {
- result.SetBadFormatSpecifierFailure();
- return false;
- }
- // Create a new result each time to ensure the runs are independent. Carry through
- // flags from the caller and return the result.
- DateTimeResult innerResult = default; // The buffer to store the parsing result.
- innerResult.Init(s);
- innerResult.flags = result.flags;
- if (TryParseExact(s, formats[i], dtfi, style, ref innerResult))
- {
- result.parsedDate = innerResult.parsedDate;
- result.timeZoneOffset = innerResult.timeZoneOffset;
- return true;
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Date Token Types
- //
- // Following is the set of tokens that can be generated from a date
- // string. Notice that the legal set of trailing separators have been
- // folded in with the date number, and month name tokens. This set
- // of tokens is chosen to reduce the number of date parse states.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal enum DTT : int
- {
- End = 0, // '\0'
- NumEnd = 1, // Num[ ]*[\0]
- NumAmpm = 2, // Num[ ]+AmPm
- NumSpace = 3, // Num[ ]+^[Dsep|Tsep|'0\']
- NumDatesep = 4, // Num[ ]*Dsep
- NumTimesep = 5, // Num[ ]*Tsep
- MonthEnd = 6, // Month[ ]*'\0'
- MonthSpace = 7, // Month[ ]+^[Dsep|Tsep|'\0']
- MonthDatesep = 8, // Month[ ]*Dsep
- NumDatesuff = 9, // Month[ ]*DSuff
- NumTimesuff = 10, // Month[ ]*TSuff
- DayOfWeek = 11, // Day of week name
- YearSpace = 12, // Year+^[Dsep|Tsep|'0\']
- YearDateSep = 13, // Year+Dsep
- YearEnd = 14, // Year+['\0']
- TimeZone = 15, // timezone name
- Era = 16, // era name
- NumUTCTimeMark = 17, // Num + 'Z'
- // When you add a new token which will be in the
- // state table, add it after NumLocalTimeMark.
- Unk = 18, // unknown
- NumLocalTimeMark = 19, // Num + 'T'
- Max = 20, // marker
- }
-
- internal enum TM
- {
- NotSet = -1,
- AM = 0,
- PM = 1,
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // DateTime parsing state enumeration (DS.*)
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal enum DS
- {
- BEGIN = 0,
- N = 1, // have one number
- NN = 2, // have two numbers
-
- // The following are known to be part of a date
-
- D_Nd = 3, // date string: have number followed by date separator
- D_NN = 4, // date string: have two numbers
- D_NNd = 5, // date string: have two numbers followed by date separator
-
- D_M = 6, // date string: have a month
- D_MN = 7, // date string: have a month and a number
- D_NM = 8, // date string: have a number and a month
- D_MNd = 9, // date string: have a month and number followed by date separator
- D_NDS = 10, // date string: have one number followed a date suffix.
-
- D_Y = 11, // date string: have a year.
- D_YN = 12, // date string: have a year and a number
- D_YNd = 13, // date string: have a year and a number and a date separator
- D_YM = 14, // date string: have a year and a month
- D_YMd = 15, // date string: have a year and a month and a date separator
- D_S = 16, // have numbers followed by a date suffix.
- T_S = 17, // have numbers followed by a time suffix.
-
- // The following are known to be part of a time
-
- T_Nt = 18, // have num followed by time separator
- T_NNt = 19, // have two numbers followed by time separator
-
- ERROR = 20,
-
- // The following are terminal states. These all have an action
- // associated with them; and transition back to BEGIN.
-
- DX_NN = 21, // day from two numbers
- DX_NNN = 22, // day from three numbers
- DX_MN = 23, // day from month and one number
- DX_NM = 24, // day from month and one number
- DX_MNN = 25, // day from month and two numbers
- DX_DS = 26, // a set of date suffixed numbers.
- DX_DSN = 27, // day from date suffixes and one number.
- DX_NDS = 28, // day from one number and date suffixes .
- DX_NNDS = 29, // day from one number and date suffixes .
-
- DX_YNN = 30, // date string: have a year and two number
- DX_YMN = 31, // date string: have a year, a month, and a number.
- DX_YN = 32, // date string: have a year and one number
- DX_YM = 33, // date string: have a year, a month.
- TX_N = 34, // time from one number (must have ampm)
- TX_NN = 35, // time from two numbers
- TX_NNN = 36, // time from three numbers
- TX_TS = 37, // a set of time suffixed numbers.
- DX_NNY = 38,
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // NOTE: The following state machine table is dependent on the order of the
- // DS and DTT enumerations.
- //
- // For each non terminal state, the following table defines the next state
- // for each given date token type.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
- private static readonly DS[][] dateParsingStates = {
-// DS.BEGIN // DS.BEGIN
-new DS[] { DS.BEGIN, DS.ERROR, DS.TX_N, DS.N, DS.D_Nd, DS.T_Nt, DS.ERROR, DS.D_M, DS.D_M, DS.D_S, DS.T_S, DS.BEGIN, DS.D_Y, DS.D_Y, DS.ERROR, DS.BEGIN, DS.BEGIN, DS.ERROR },
-
-// DS.N // DS.N
-new DS[] { DS.ERROR, DS.DX_NN, DS.ERROR, DS.NN, DS.D_NNd, DS.ERROR, DS.DX_NM, DS.D_NM, DS.D_MNd, DS.D_NDS, DS.ERROR, DS.N, DS.D_YN, DS.D_YNd, DS.DX_YN, DS.N, DS.N, DS.ERROR },
-
-// DS.NN // DS.NN
-new DS[] { DS.DX_NN, DS.DX_NNN, DS.TX_N, DS.DX_NNN, DS.ERROR, DS.T_Nt, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.ERROR, DS.T_S, DS.NN, DS.DX_NNY, DS.ERROR, DS.DX_NNY, DS.NN, DS.NN, DS.ERROR },
-
-// DS.D_Nd // DS.D_Nd
-new DS[] { DS.ERROR, DS.DX_NN, DS.ERROR, DS.D_NN, DS.D_NNd, DS.ERROR, DS.DX_NM, DS.D_MN, DS.D_MNd, DS.ERROR, DS.ERROR, DS.D_Nd, DS.D_YN, DS.D_YNd, DS.DX_YN, DS.ERROR, DS.D_Nd, DS.ERROR },
-
-// DS.D_NN // DS.D_NN
-new DS[] { DS.DX_NN, DS.DX_NNN, DS.TX_N, DS.DX_NNN, DS.ERROR, DS.T_Nt, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.DX_DS, DS.T_S, DS.D_NN, DS.DX_NNY, DS.ERROR, DS.DX_NNY, DS.ERROR, DS.D_NN, DS.ERROR },
-
-// DS.D_NNd // DS.D_NNd
-new DS[] { DS.ERROR, DS.DX_NNN, DS.DX_NNN, DS.DX_NNN, DS.ERROR, DS.ERROR, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.DX_DS, DS.ERROR, DS.D_NNd, DS.DX_NNY, DS.ERROR, DS.DX_NNY, DS.ERROR, DS.D_NNd, DS.ERROR },
-
-// DS.D_M // DS.D_M
-new DS[] { DS.ERROR, DS.DX_MN, DS.ERROR, DS.D_MN, DS.D_MNd, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_M, DS.D_YM, DS.D_YMd, DS.DX_YM, DS.ERROR, DS.D_M, DS.ERROR },
-
-// DS.D_MN // DS.D_MN
-new DS[] { DS.DX_MN, DS.DX_MNN, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.DX_DS, DS.T_S, DS.D_MN, DS.DX_YMN, DS.ERROR, DS.DX_YMN, DS.ERROR, DS.D_MN, DS.ERROR },
-
-// DS.D_NM // DS.D_NM
-new DS[] { DS.DX_NM, DS.DX_MNN, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.DX_DS, DS.T_S, DS.D_NM, DS.DX_YMN, DS.ERROR, DS.DX_YMN, DS.ERROR, DS.D_NM, DS.ERROR },
-
-// DS.D_MNd // DS.D_MNd
-new DS[] { DS.ERROR, DS.DX_MNN, DS.ERROR, DS.DX_MNN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_MNd, DS.DX_YMN, DS.ERROR, DS.DX_YMN, DS.ERROR, DS.D_MNd, DS.ERROR },
-
-// DS.D_NDS, // DS.D_NDS,
-new DS[] { DS.DX_NDS, DS.DX_NNDS, DS.DX_NNDS, DS.DX_NNDS, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_NDS, DS.T_S, DS.D_NDS, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_NDS, DS.ERROR },
-
-// DS.D_Y // DS.D_Y
-new DS[] { DS.ERROR, DS.DX_YN, DS.ERROR, DS.D_YN, DS.D_YNd, DS.ERROR, DS.DX_YM, DS.D_YM, DS.D_YMd, DS.D_YM, DS.ERROR, DS.D_Y, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_Y, DS.ERROR },
-
-// DS.D_YN // DS.D_YN
-new DS[] { DS.DX_YN, DS.DX_YNN, DS.DX_YNN, DS.DX_YNN, DS.ERROR, DS.ERROR, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR },
-
-// DS.D_YNd // DS.D_YNd
-new DS[] { DS.ERROR, DS.DX_YNN, DS.DX_YNN, DS.DX_YNN, DS.ERROR, DS.ERROR, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR },
-
-// DS.D_YM // DS.D_YM
-new DS[] { DS.DX_YM, DS.DX_YMN, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR },
-
-// DS.D_YMd // DS.D_YMd
-new DS[] { DS.ERROR, DS.DX_YMN, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR },
-
-// DS.D_S // DS.D_S
-new DS[] { DS.DX_DS, DS.DX_DSN, DS.TX_N, DS.T_Nt, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_S, DS.T_S, DS.D_S, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_S, DS.ERROR },
-
-// DS.T_S // DS.T_S
-new DS[] { DS.TX_TS, DS.TX_TS, DS.TX_TS, DS.T_Nt, DS.D_Nd, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_S, DS.T_S, DS.T_S, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_S, DS.T_S, DS.ERROR },
-
-// DS.T_Nt // DS.T_Nt
-new DS[] { DS.ERROR, DS.TX_NN, DS.TX_NN, DS.TX_NN, DS.ERROR, DS.T_NNt, DS.DX_NM, DS.D_NM, DS.ERROR, DS.ERROR, DS.T_S, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_Nt, DS.T_Nt, DS.TX_NN },
-
-// DS.T_NNt // DS.T_NNt
-new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_S, DS.T_NNt, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_NNt, DS.T_NNt, DS.TX_NNN },
-};
- // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCMark
-
- internal const string GMTName = "GMT";
- internal const string ZuluName = "Z";
-
- //
- // Search from the index of str at str.Index to see if the target string exists in the str.
- //
- private static bool MatchWord(ref __DTString str, string target)
- {
- if (target.Length > (str.Value.Length - str.Index))
- {
- return false;
- }
-
- if (str.CompareInfo.Compare(str.Value.Slice(str.Index, target.Length), target, CompareOptions.IgnoreCase) != 0)
- {
- return false;
- }
-
- int nextCharIndex = str.Index + target.Length;
-
- if (nextCharIndex < str.Value.Length)
- {
- char nextCh = str.Value[nextCharIndex];
- if (char.IsLetter(nextCh))
- {
- return false;
- }
- }
- str.Index = nextCharIndex;
- if (str.Index < str.Length)
- {
- str.m_current = str.Value[str.Index];
- }
-
- return true;
- }
-
- //
- // Check the word at the current index to see if it matches GMT name or Zulu name.
- //
- private static bool GetTimeZoneName(ref __DTString str)
- {
- if (MatchWord(ref str, GMTName))
- {
- return true;
- }
-
- if (MatchWord(ref str, ZuluName))
- {
- return true;
- }
-
- return false;
- }
-
- internal static bool IsDigit(char ch) => (uint)(ch - '0') <= 9;
-
- /*=================================ParseFraction==========================
- **Action: Starting at the str.Index, which should be a decimal symbol.
- ** if the current character is a digit, parse the remaining
- ** numbers as fraction. For example, if the sub-string starting at str.Index is "123", then
- ** the method will return 0.123
- **Returns: The fraction number.
- **Arguments:
- ** str the parsing string
- **Exceptions:
- ============================================================================*/
-
- private static bool ParseFraction(ref __DTString str, out double result)
- {
- result = 0;
- double decimalBase = 0.1;
- int digits = 0;
- char ch;
- while (str.GetNext()
- && IsDigit(ch = str.m_current))
- {
- result += (ch - '0') * decimalBase;
- decimalBase *= 0.1;
- digits++;
- }
- return digits > 0;
- }
-
- /*=================================ParseTimeZone==========================
- **Action: Parse the timezone offset in the following format:
- ** "+8", "+08", "+0800", "+0800"
- ** This method is used by DateTime.Parse().
- **Returns: The TimeZone offset.
- **Arguments:
- ** str the parsing string
- **Exceptions:
- ** FormatException if invalid timezone format is found.
- ============================================================================*/
-
- private static bool ParseTimeZone(ref __DTString str, ref TimeSpan result)
- {
- // The hour/minute offset for timezone.
- int hourOffset;
- int minuteOffset = 0;
-
- // Consume the +/- character that has already been read
- DTSubString sub = str.GetSubString();
- if (sub.length != 1)
- {
- return false;
- }
- char offsetChar = sub[0];
- if (offsetChar != '+' && offsetChar != '-')
- {
- return false;
- }
- str.ConsumeSubString(sub);
-
- sub = str.GetSubString();
- if (sub.type != DTSubStringType.Number)
- {
- return false;
- }
- int value = sub.value;
- int length = sub.length;
- if (length == 1 || length == 2)
- {
- // Parsing "+8" or "+08"
- hourOffset = value;
- str.ConsumeSubString(sub);
- // See if we have minutes
- sub = str.GetSubString();
- if (sub.length == 1 && sub[0] == ':')
- {
- // Parsing "+8:00" or "+08:00"
- str.ConsumeSubString(sub);
- sub = str.GetSubString();
- if (sub.type != DTSubStringType.Number || sub.length < 1 || sub.length > 2)
- {
- return false;
- }
- minuteOffset = sub.value;
- str.ConsumeSubString(sub);
- }
- }
- else if (length == 3 || length == 4)
- {
- // Parsing "+800" or "+0800"
- hourOffset = value / 100;
- minuteOffset = value % 100;
- str.ConsumeSubString(sub);
- }
- else
- {
- // Wrong number of digits
- return false;
- }
- Debug.Assert(hourOffset >= 0 && hourOffset <= 99, "hourOffset >= 0 && hourOffset <= 99");
- Debug.Assert(minuteOffset >= 0 && minuteOffset <= 99, "minuteOffset >= 0 && minuteOffset <= 99");
- if (minuteOffset < 0 || minuteOffset >= 60)
- {
- return false;
- }
-
- result = new TimeSpan(hourOffset, minuteOffset, 0);
- if (offsetChar == '-')
- {
- result = result.Negate();
- }
- return true;
- }
-
- // This is the helper function to handle timezone in string in the format like +/-0800
- private static bool HandleTimeZone(ref __DTString str, ref DateTimeResult result)
- {
- if (str.Index < str.Length - 1)
- {
- char nextCh = str.Value[str.Index];
- // Skip whitespace, but don't update the index unless we find a time zone marker
- int whitespaceCount = 0;
- while (char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
- {
- whitespaceCount++;
- nextCh = str.Value[str.Index + whitespaceCount];
- }
- if (nextCh == '+' || nextCh == '-')
- {
- str.Index += whitespaceCount;
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
- {
- // Should not have two timezone offsets.
- result.SetBadDateTimeFailure();
- return false;
- }
- result.flags |= ParseFlags.TimeZoneUsed;
- if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- }
- return true;
- }
-
- //
- // This is the lexer. Check the character at the current index, and put the found token in dtok and
- // some raw date/time information in raw.
- //
- private static bool Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
- {
- TokenType tokenType;
- int tokenValue;
- int indexBeforeSeparator;
- char charBeforeSeparator;
-
- TokenType sep;
- dtok.dtt = DTT.Unk; // Assume the token is unkown.
-
- str.GetRegularToken(out tokenType, out tokenValue, dtfi);
-
-#if _LOGGING
- if (_tracingEnabled)
- {
- Trace($"Lex({Hex(str.Value)})\tpos:{str.Index}({Hex(str.m_current)}), {tokenType}, DS.{dps}");
- }
-#endif // _LOGGING
-
- // Look at the regular token.
- switch (tokenType)
- {
- case TokenType.NumberToken:
- case TokenType.YearNumberToken:
- if (raw.numCount == 3 || tokenValue == -1)
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0010", dps);
- return false;
- }
- //
- // This is a digit.
- //
- // If the previous parsing state is DS.T_NNt (like 12:01), and we got another number,
- // so we will have a terminal state DS.TX_NNN (like 12:01:02).
- // If the previous parsing state is DS.T_Nt (like 12:), and we got another number,
- // so we will have a terminal state DS.TX_NN (like 12:01).
- //
- // Look ahead to see if the following character is a decimal point or timezone offset.
- // This enables us to parse time in the forms of:
- // "11:22:33.1234" or "11:22:33-08".
- if (dps == DS.T_NNt)
- {
- if (str.Index < str.Length - 1)
- {
- char nextCh = str.Value[str.Index];
- if (nextCh == '.')
- {
- // While ParseFraction can fail, it just means that there were no digits after
- // the dot. In this case ParseFraction just removes the dot. This is actually
- // valid for cultures like Albanian, that join the time marker to the time with
- // with a dot: e.g. "9:03.MD"
- ParseFraction(ref str, out raw.fraction);
- }
- }
- }
- if (dps == DS.T_NNt || dps == DS.T_Nt)
- {
- if (str.Index < str.Length - 1)
- {
- if (!HandleTimeZone(ref str, ref result))
- {
- LexTraceExit("0020 (value like \"12:01\" or \"12:\" followed by a non-TZ number", dps);
- return false;
- }
- }
- }
-
- dtok.num = tokenValue;
- if (tokenType == TokenType.YearNumberToken)
- {
- if (raw.year == -1)
- {
- raw.year = tokenValue;
- //
- // If we have number which has 3 or more digits (like "001" or "0001"),
- // we assume this number is a year. Save the current raw.numCount in
- // raw.year.
- //
- switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
- {
- case TokenType.SEP_End:
- dtok.dtt = DTT.YearEnd;
- break;
- case TokenType.SEP_Am:
- case TokenType.SEP_Pm:
- if (raw.timeMark == TM.NotSet)
- {
- raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
- dtok.dtt = DTT.YearSpace;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0030 (TM.AM/TM.PM Happened more than 1x)", dps);
- }
- break;
- case TokenType.SEP_Space:
- dtok.dtt = DTT.YearSpace;
- break;
- case TokenType.SEP_Date:
- dtok.dtt = DTT.YearDateSep;
- break;
- case TokenType.SEP_Time:
- if (!raw.hasSameDateAndTimeSeparators)
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0040 (Invalid separator after number)", dps);
- return false;
- }
-
- // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
- // we are sure we are not parsing time.
- dtok.dtt = DTT.YearDateSep;
- break;
- case TokenType.SEP_DateOrOffset:
- // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
- // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
- if ((dateParsingStates[(int)dps][(int)DTT.YearDateSep] == DS.ERROR)
- && (dateParsingStates[(int)dps][(int)DTT.YearSpace] > DS.ERROR))
- {
- str.Index = indexBeforeSeparator;
- str.m_current = charBeforeSeparator;
- dtok.dtt = DTT.YearSpace;
- }
- else
- {
- dtok.dtt = DTT.YearDateSep;
- }
- break;
- case TokenType.SEP_YearSuff:
- case TokenType.SEP_MonthSuff:
- case TokenType.SEP_DaySuff:
- dtok.dtt = DTT.NumDatesuff;
- dtok.suffix = sep;
- break;
- case TokenType.SEP_HourSuff:
- case TokenType.SEP_MinuteSuff:
- case TokenType.SEP_SecondSuff:
- dtok.dtt = DTT.NumTimesuff;
- dtok.suffix = sep;
- break;
- default:
- // Invalid separator after number number.
- result.SetBadDateTimeFailure();
- LexTraceExit("0040 (Invalid separator after number)", dps);
- return false;
- }
- //
- // Found the token already. Return now.
- //
- LexTraceExit("0050 (success)", dps);
- return true;
- }
- result.SetBadDateTimeFailure();
- LexTraceExit("0060", dps);
- return false;
- }
- switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
- {
- //
- // Note here we check if the numCount is less than three.
- // When we have more than three numbers, it will be caught as error in the state machine.
- //
- case TokenType.SEP_End:
- dtok.dtt = DTT.NumEnd;
- raw.AddNumber(dtok.num);
- break;
- case TokenType.SEP_Am:
- case TokenType.SEP_Pm:
- if (raw.timeMark == TM.NotSet)
- {
- raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
- dtok.dtt = DTT.NumAmpm;
- // Fix AM/PM parsing case, e.g. "1/10 5 AM"
- if (dps == DS.D_NN)
- {
- if (!ProcessTerminalState(DS.DX_NN, ref str, ref result, ref styles, ref raw, dtfi))
- {
- return false;
- }
- }
-
- raw.AddNumber(dtok.num);
- }
- else
- {
- result.SetBadDateTimeFailure();
- break;
- }
- if (dps == DS.T_NNt || dps == DS.T_Nt)
- {
- if (!HandleTimeZone(ref str, ref result))
- {
- LexTraceExit("0070 (HandleTimeZone returned false)", dps);
- return false;
- }
- }
- break;
- case TokenType.SEP_Space:
- dtok.dtt = DTT.NumSpace;
- raw.AddNumber(dtok.num);
- break;
- case TokenType.SEP_Date:
- dtok.dtt = DTT.NumDatesep;
- raw.AddNumber(dtok.num);
- break;
- case TokenType.SEP_DateOrOffset:
- // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
- // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
- if ((dateParsingStates[(int)dps][(int)DTT.NumDatesep] == DS.ERROR)
- && (dateParsingStates[(int)dps][(int)DTT.NumSpace] > DS.ERROR))
- {
- str.Index = indexBeforeSeparator;
- str.m_current = charBeforeSeparator;
- dtok.dtt = DTT.NumSpace;
- }
- else
- {
- dtok.dtt = DTT.NumDatesep;
- }
- raw.AddNumber(dtok.num);
- break;
- case TokenType.SEP_Time:
- if (raw.hasSameDateAndTimeSeparators &&
- (dps == DS.D_Y || dps == DS.D_YN || dps == DS.D_YNd || dps == DS.D_YM || dps == DS.D_YMd))
- {
- // we are parsing a date and we have the time separator same as date separator, so we mark the token as date separator
- dtok.dtt = DTT.NumDatesep;
- raw.AddNumber(dtok.num);
- break;
- }
- dtok.dtt = DTT.NumTimesep;
- raw.AddNumber(dtok.num);
- break;
- case TokenType.SEP_YearSuff:
- try
- {
- dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue);
- }
- catch (ArgumentOutOfRangeException)
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0075 (Calendar.ToFourDigitYear failed)", dps);
- return false;
- }
- dtok.dtt = DTT.NumDatesuff;
- dtok.suffix = sep;
- break;
- case TokenType.SEP_MonthSuff:
- case TokenType.SEP_DaySuff:
- dtok.dtt = DTT.NumDatesuff;
- dtok.suffix = sep;
- break;
- case TokenType.SEP_HourSuff:
- case TokenType.SEP_MinuteSuff:
- case TokenType.SEP_SecondSuff:
- dtok.dtt = DTT.NumTimesuff;
- dtok.suffix = sep;
- break;
- case TokenType.SEP_LocalTimeMark:
- dtok.dtt = DTT.NumLocalTimeMark;
- raw.AddNumber(dtok.num);
- break;
- default:
- // Invalid separator after number number.
- result.SetBadDateTimeFailure();
- LexTraceExit("0080", dps);
- return false;
- }
- break;
- case TokenType.HebrewNumber:
- if (tokenValue >= 100)
- {
- // This is a year number
- if (raw.year == -1)
- {
- raw.year = tokenValue;
- //
- // If we have number which has 3 or more digits (like "001" or "0001"),
- // we assume this number is a year. Save the current raw.numCount in
- // raw.year.
- //
- switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
- {
- case TokenType.SEP_End:
- dtok.dtt = DTT.YearEnd;
- break;
- case TokenType.SEP_Space:
- dtok.dtt = DTT.YearSpace;
- break;
- case TokenType.SEP_DateOrOffset:
- // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
- // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
- if (dateParsingStates[(int)dps][(int)DTT.YearSpace] > DS.ERROR)
- {
- str.Index = indexBeforeSeparator;
- str.m_current = charBeforeSeparator;
- dtok.dtt = DTT.YearSpace;
- break;
- }
- goto default;
- default:
- // Invalid separator after number number.
- result.SetBadDateTimeFailure();
- LexTraceExit("0090", dps);
- return false;
- }
- }
- else
- {
- // Invalid separator after number number.
- result.SetBadDateTimeFailure();
- LexTraceExit("0100", dps);
- return false;
- }
- }
- else
- {
- // This is a day number
- dtok.num = tokenValue;
- raw.AddNumber(dtok.num);
-
- switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
- {
- //
- // Note here we check if the numCount is less than three.
- // When we have more than three numbers, it will be caught as error in the state machine.
- //
- case TokenType.SEP_End:
- dtok.dtt = DTT.NumEnd;
- break;
- case TokenType.SEP_Space:
- case TokenType.SEP_Date:
- dtok.dtt = DTT.NumDatesep;
- break;
- case TokenType.SEP_DateOrOffset:
- // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
- // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
- if ((dateParsingStates[(int)dps][(int)DTT.NumDatesep] == DS.ERROR)
- && (dateParsingStates[(int)dps][(int)DTT.NumSpace] > DS.ERROR))
- {
- str.Index = indexBeforeSeparator;
- str.m_current = charBeforeSeparator;
- dtok.dtt = DTT.NumSpace;
- }
- else
- {
- dtok.dtt = DTT.NumDatesep;
- }
- break;
- default:
- // Invalid separator after number number.
- result.SetBadDateTimeFailure();
- LexTraceExit("0110", dps);
- return false;
- }
- }
- break;
- case TokenType.DayOfWeekToken:
- if (raw.dayOfWeek == -1)
- {
- //
- // This is a day of week name.
- //
- raw.dayOfWeek = tokenValue;
- dtok.dtt = DTT.DayOfWeek;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0120 (DayOfWeek seen more than 1x)", dps);
- return false;
- }
- break;
- case TokenType.MonthToken:
- if (raw.month == -1)
- {
- //
- // This is a month name
- //
- switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
- {
- case TokenType.SEP_End:
- dtok.dtt = DTT.MonthEnd;
- break;
- case TokenType.SEP_Space:
- dtok.dtt = DTT.MonthSpace;
- break;
- case TokenType.SEP_Date:
- dtok.dtt = DTT.MonthDatesep;
- break;
- case TokenType.SEP_Time:
- if (!raw.hasSameDateAndTimeSeparators)
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0130 (Invalid separator after month name)", dps);
- return false;
- }
-
- // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
- // we are sure we are not parsing time.
- dtok.dtt = DTT.MonthDatesep;
- break;
- case TokenType.SEP_DateOrOffset:
- // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
- // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
- if ((dateParsingStates[(int)dps][(int)DTT.MonthDatesep] == DS.ERROR)
- && (dateParsingStates[(int)dps][(int)DTT.MonthSpace] > DS.ERROR))
- {
- str.Index = indexBeforeSeparator;
- str.m_current = charBeforeSeparator;
- dtok.dtt = DTT.MonthSpace;
- }
- else
- {
- dtok.dtt = DTT.MonthDatesep;
- }
- break;
- default:
- // Invalid separator after month name
- result.SetBadDateTimeFailure();
- LexTraceExit("0130 (Invalid separator after month name)", dps);
- return false;
- }
- raw.month = tokenValue;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0140 (MonthToken seen more than 1x)", dps);
- return false;
- }
- break;
- case TokenType.EraToken:
- if (result.era != -1)
- {
- result.era = tokenValue;
- dtok.dtt = DTT.Era;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0150 (EraToken seen when result.era already set)", dps);
- return false;
- }
- break;
- case TokenType.JapaneseEraToken:
- // Special case for Japanese. We allow Japanese era name to be used even if the calendar is not Japanese Calendar.
- result.calendar = JapaneseCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI();
- if (result.era != -1)
- {
- result.era = tokenValue;
- dtok.dtt = DTT.Era;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0160 (JapaneseEraToken seen when result.era already set)", dps);
- return false;
- }
- break;
- case TokenType.TEraToken:
- result.calendar = TaiwanCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI();
- if (result.era != -1)
- {
- result.era = tokenValue;
- dtok.dtt = DTT.Era;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0170 (TEraToken seen when result.era already set)", dps);
- return false;
- }
- break;
- case TokenType.TimeZoneToken:
- //
- // This is a timezone designator
- //
- // NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).
- //
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
- {
- // Should not have two timezone offsets.
- result.SetBadDateTimeFailure();
- LexTraceExit("0180 (seen GMT or Z more than 1x)", dps);
- return false;
- }
- dtok.dtt = DTT.TimeZone;
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = new TimeSpan(0);
- result.flags |= ParseFlags.TimeZoneUtc;
- break;
- case TokenType.EndOfString:
- dtok.dtt = DTT.End;
- break;
- case TokenType.DateWordToken:
- case TokenType.IgnorableSymbol:
- // Date words and ignorable symbols can just be skipped over
- break;
- case TokenType.Am:
- case TokenType.Pm:
- if (raw.timeMark == TM.NotSet)
- {
- raw.timeMark = (TM)tokenValue;
- }
- else
- {
- result.SetBadDateTimeFailure();
- LexTraceExit("0190 (AM/PM timeMark already set)", dps);
- return false;
- }
- break;
- case TokenType.UnknownToken:
- if (char.IsLetter(str.m_current))
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTimeAndParameter, nameof(SR.Format_UnknownDateTimeWord), str.Index);
- LexTraceExit("0200", dps);
- return false;
- }
-
- if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0))
- {
- int originalIndex = str.Index;
- if (ParseTimeZone(ref str, ref result.timeZoneOffset))
- {
- result.flags |= ParseFlags.TimeZoneUsed;
- LexTraceExit("0220 (success)", dps);
- return true;
- }
- else
- {
- // Time zone parse attempt failed. Fall through to punctuation handling.
- str.Index = originalIndex;
- }
- }
-
- // Visual Basic implements string to date conversions on top of DateTime.Parse:
- // CDate("#10/10/95#")
- //
- if (VerifyValidPunctuation(ref str))
- {
- LexTraceExit("0230 (success)", dps);
- return true;
- }
-
- result.SetBadDateTimeFailure();
- LexTraceExit("0240", dps);
- return false;
- }
-
- LexTraceExit("0250 (success)", dps);
- return true;
- }
-
- private static bool VerifyValidPunctuation(ref __DTString str)
- {
- // Compatability Behavior. Allow trailing nulls and surrounding hashes
- char ch = str.Value[str.Index];
- if (ch == '#')
- {
- bool foundStart = false;
- bool foundEnd = false;
- for (int i = 0; i < str.Length; i++)
- {
- ch = str.Value[i];
- if (ch == '#')
- {
- if (foundStart)
- {
- if (foundEnd)
- {
- // Having more than two hashes is invalid
- return false;
- }
- else
- {
- foundEnd = true;
- }
- }
- else
- {
- foundStart = true;
- }
- }
- else if (ch == '\0')
- {
- // Allow nulls only at the end
- if (!foundEnd)
- {
- return false;
- }
- }
- else if (!char.IsWhiteSpace(ch))
- {
- // Anything other than whitespace outside hashes is invalid
- if (!foundStart || foundEnd)
- {
- return false;
- }
- }
- }
- if (!foundEnd)
- {
- // The has was un-paired
- return false;
- }
- // Valid Hash usage: eat the hash and continue.
- str.GetNext();
- return true;
- }
- else if (ch == '\0')
- {
- for (int i = str.Index; i < str.Length; i++)
- {
- if (str.Value[i] != '\0')
- {
- // Nulls are only valid if they are the only trailing character
- return false;
- }
- }
- // Move to the end of the string
- str.Index = str.Length;
- return true;
- }
- return false;
- }
-
- private const int ORDER_YMD = 0; // The order of date is Year/Month/Day.
- private const int ORDER_MDY = 1; // The order of date is Month/Day/Year.
- private const int ORDER_DMY = 2; // The order of date is Day/Month/Year.
- private const int ORDER_YDM = 3; // The order of date is Year/Day/Month
- private const int ORDER_YM = 4; // Year/Month order.
- private const int ORDER_MY = 5; // Month/Year order.
- private const int ORDER_MD = 6; // Month/Day order.
- private const int ORDER_DM = 7; // Day/Month order.
-
- //
- // Decide the year/month/day order from the datePattern.
- //
- // Return 0 for YMD, 1 for MDY, 2 for DMY, otherwise -1.
- //
- private static bool GetYearMonthDayOrder(string datePattern, out int order)
- {
- int yearOrder = -1;
- int monthOrder = -1;
- int dayOrder = -1;
- int orderCount = 0;
-
- bool inQuote = false;
-
- for (int i = 0; i < datePattern.Length && orderCount < 3; i++)
- {
- char ch = datePattern[i];
- if (ch == '\\' || ch == '%')
- {
- i++;
- continue; // Skip next character that is escaped by this backslash
- }
-
- if (ch == '\'' || ch == '"')
- {
- inQuote = !inQuote;
- }
-
- if (!inQuote)
- {
- if (ch == 'y')
- {
- yearOrder = orderCount++;
-
- //
- // Skip all year pattern charaters.
- //
- for (; i + 1 < datePattern.Length && datePattern[i + 1] == 'y'; i++)
- {
- // Do nothing here.
- }
- }
- else if (ch == 'M')
- {
- monthOrder = orderCount++;
- //
- // Skip all month pattern characters.
- //
- for (; i + 1 < datePattern.Length && datePattern[i + 1] == 'M'; i++)
- {
- // Do nothing here.
- }
- }
- else if (ch == 'd')
- {
- int patternCount = 1;
- //
- // Skip all day pattern characters.
- //
- for (; i + 1 < datePattern.Length && datePattern[i + 1] == 'd'; i++)
- {
- patternCount++;
- }
- //
- // Make sure this is not "ddd" or "dddd", which means day of week.
- //
- if (patternCount <= 2)
- {
- dayOrder = orderCount++;
- }
- }
- }
- }
-
- if (yearOrder == 0 && monthOrder == 1 && dayOrder == 2)
- {
- order = ORDER_YMD;
- return true;
- }
- if (monthOrder == 0 && dayOrder == 1 && yearOrder == 2)
- {
- order = ORDER_MDY;
- return true;
- }
- if (dayOrder == 0 && monthOrder == 1 && yearOrder == 2)
- {
- order = ORDER_DMY;
- return true;
- }
- if (yearOrder == 0 && dayOrder == 1 && monthOrder == 2)
- {
- order = ORDER_YDM;
- return true;
- }
- order = -1;
- return false;
- }
-
- //
- // Decide the year/month order from the pattern.
- //
- // Return 0 for YM, 1 for MY, otherwise -1.
- //
- private static bool GetYearMonthOrder(string pattern, out int order)
- {
- int yearOrder = -1;
- int monthOrder = -1;
- int orderCount = 0;
-
- bool inQuote = false;
- for (int i = 0; i < pattern.Length && orderCount < 2; i++)
- {
- char ch = pattern[i];
- if (ch == '\\' || ch == '%')
- {
- i++;
- continue; // Skip next character that is escaped by this backslash
- }
-
- if (ch == '\'' || ch == '"')
- {
- inQuote = !inQuote;
- }
-
- if (!inQuote)
- {
- if (ch == 'y')
- {
- yearOrder = orderCount++;
-
- //
- // Skip all year pattern charaters.
- //
- for (; i + 1 < pattern.Length && pattern[i + 1] == 'y'; i++)
- {
- }
- }
- else if (ch == 'M')
- {
- monthOrder = orderCount++;
- //
- // Skip all month pattern characters.
- //
- for (; i + 1 < pattern.Length && pattern[i + 1] == 'M'; i++)
- {
- }
- }
- }
- }
-
- if (yearOrder == 0 && monthOrder == 1)
- {
- order = ORDER_YM;
- return true;
- }
- if (monthOrder == 0 && yearOrder == 1)
- {
- order = ORDER_MY;
- return true;
- }
- order = -1;
- return false;
- }
-
- //
- // Decide the month/day order from the pattern.
- //
- // Return 0 for MD, 1 for DM, otherwise -1.
- //
- private static bool GetMonthDayOrder(string pattern, out int order)
- {
- int monthOrder = -1;
- int dayOrder = -1;
- int orderCount = 0;
-
- bool inQuote = false;
- for (int i = 0; i < pattern.Length && orderCount < 2; i++)
- {
- char ch = pattern[i];
- if (ch == '\\' || ch == '%')
- {
- i++;
- continue; // Skip next character that is escaped by this backslash
- }
-
- if (ch == '\'' || ch == '"')
- {
- inQuote = !inQuote;
- }
-
- if (!inQuote)
- {
- if (ch == 'd')
- {
- int patternCount = 1;
- //
- // Skip all day pattern charaters.
- //
- for (; i + 1 < pattern.Length && pattern[i + 1] == 'd'; i++)
- {
- patternCount++;
- }
-
- //
- // Make sure this is not "ddd" or "dddd", which means day of week.
- //
- if (patternCount <= 2)
- {
- dayOrder = orderCount++;
- }
- }
- else if (ch == 'M')
- {
- monthOrder = orderCount++;
- //
- // Skip all month pattern characters.
- //
- for (; i + 1 < pattern.Length && pattern[i + 1] == 'M'; i++)
- {
- }
- }
- }
- }
-
- if (monthOrder == 0 && dayOrder == 1)
- {
- order = ORDER_MD;
- return true;
- }
- if (dayOrder == 0 && monthOrder == 1)
- {
- order = ORDER_DM;
- return true;
- }
- order = -1;
- return false;
- }
-
- //
- // Adjust the two-digit year if necessary.
- //
- private static bool TryAdjustYear(ref DateTimeResult result, int year, out int adjustedYear)
- {
- if (year < 100)
- {
- try
- {
- // the Calendar classes need some real work. Many of the calendars that throw
- // don't implement a fast/non-allocating (and non-throwing) IsValid{Year|Day|Month} method.
- // we are making a targeted try/catch fix in the in-place release but will revisit this code
- // in the next side-by-side release.
- year = result.calendar.ToFourDigitYear(year);
- }
- catch (ArgumentOutOfRangeException)
- {
- adjustedYear = -1;
- return false;
- }
- }
- adjustedYear = year;
- return true;
- }
-
- private static bool SetDateYMD(ref DateTimeResult result, int year, int month, int day)
- {
- // Note, longer term these checks should be done at the end of the parse. This current
- // way of checking creates order dependence with parsing the era name.
- if (result.calendar.IsValidDay(year, month, day, result.era))
- {
- result.SetDate(year, month, day); // YMD
- return true;
- }
- return false;
- }
-
- private static bool SetDateMDY(ref DateTimeResult result, int month, int day, int year)
- {
- return SetDateYMD(ref result, year, month, day);
- }
-
- private static bool SetDateDMY(ref DateTimeResult result, int day, int month, int year)
- {
- return SetDateYMD(ref result, year, month, day);
- }
-
- private static bool SetDateYDM(ref DateTimeResult result, int year, int day, int month)
- {
- return SetDateYMD(ref result, year, month, day);
- }
-
- private static void GetDefaultYear(ref DateTimeResult result, ref DateTimeStyles styles)
- {
- result.Year = result.calendar.GetYear(GetDateTimeNow(ref result, ref styles));
- result.flags |= ParseFlags.YearDefault;
- }
-
- // Processing teriminal case: DS.DX_NN
- private static bool GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int n1 = raw.GetNumber(0);
- int n2 = raw.GetNumber(1);
-
- GetDefaultYear(ref result, ref styles);
-
- int order;
- if (!GetMonthDayOrder(dtfi.MonthDayPattern, out order))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
- return false;
- }
-
- if (order == ORDER_MD)
- {
- if (SetDateYMD(ref result, result.Year, n1, n2)) // MD
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- else
- {
- // ORDER_DM
- if (SetDateYMD(ref result, result.Year, n2, n1)) // DM
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Processing teriminal case: DS.DX_NNN
- private static bool GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int n1 = raw.GetNumber(0);
- int n2 = raw.GetNumber(1);
- int n3 = raw.GetNumber(2);
-
- int order;
- if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, out order))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
- return false;
- }
- int year;
-
- if (order == ORDER_YMD)
- {
- if (TryAdjustYear(ref result, n1, out year) && SetDateYMD(ref result, year, n2, n3)) // YMD
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- else if (order == ORDER_MDY)
- {
- if (TryAdjustYear(ref result, n3, out year) && SetDateMDY(ref result, n1, n2, year)) // MDY
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- else if (order == ORDER_DMY)
- {
- if (TryAdjustYear(ref result, n3, out year) && SetDateDMY(ref result, n1, n2, year)) // DMY
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- else if (order == ORDER_YDM)
- {
- if (TryAdjustYear(ref result, n1, out year) && SetDateYDM(ref result, year, n2, n3)) // YDM
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // The interpretation is based on the MonthDayPattern and YearMonthPattern
- //
- // MonthDayPattern YearMonthPattern Interpretation
- // --------------- ---------------- ---------------
- // MMMM dd MMMM yyyy Day
- // MMMM dd yyyy MMMM Day
- // dd MMMM MMMM yyyy Year
- // dd MMMM yyyy MMMM Day
- //
- // In the first and last cases, it could be either or neither, but a day is a better default interpretation
- // than a 2 digit year.
-
- int monthDayOrder;
- if (!GetMonthDayOrder(dtfi.MonthDayPattern, out monthDayOrder))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
- return false;
- }
- if (monthDayOrder == ORDER_DM)
- {
- int yearMonthOrder;
- if (!GetYearMonthOrder(dtfi.YearMonthPattern, out yearMonthOrder))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.YearMonthPattern);
- return false;
- }
- if (yearMonthOrder == ORDER_MY)
- {
- int year;
- if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- return true;
- }
- }
-
- GetDefaultYear(ref result, ref styles);
- if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0)))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Actions:
- // Deal with the terminal state for Hebrew Month/Day pattern
- //
- ////////////////////////////////////////////////////////////////////////
-
- private static bool GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- int monthDayOrder;
- if (!GetMonthDayOrder(dtfi.MonthDayPattern, out monthDayOrder))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
- return false;
- }
- result.Month = raw.month;
- if (monthDayOrder == ORDER_DM || monthDayOrder == ORDER_MD)
- {
- if (result.calendar.IsValidDay(result.Year, result.Month, raw.GetNumber(0), result.era))
- {
- result.Day = raw.GetNumber(0);
- return true;
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // The interpretation is based on the MonthDayPattern and YearMonthPattern
- //
- // MonthDayPattern YearMonthPattern Interpretation
- // --------------- ---------------- ---------------
- // MMMM dd MMMM yyyy Day
- // MMMM dd yyyy MMMM Year
- // dd MMMM MMMM yyyy Day
- // dd MMMM yyyy MMMM Day
- //
- // In the first and last cases, it could be either or neither, but a day is a better default interpretation
- // than a 2 digit year.
-
- int monthDayOrder;
- if (!GetMonthDayOrder(dtfi.MonthDayPattern, out monthDayOrder))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.MonthDayPattern);
- return false;
- }
- if (monthDayOrder == ORDER_MD)
- {
- int yearMonthOrder;
- if (!GetYearMonthOrder(dtfi.YearMonthPattern, out yearMonthOrder))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.YearMonthPattern);
- return false;
- }
- if (yearMonthOrder == ORDER_YM)
- {
- int year;
- if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- return true;
- }
- }
-
- GetDefaultYear(ref result, ref styles);
- if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0)))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- return true;
- }
-
- private static bool GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int n1 = raw.GetNumber(0);
- int n2 = raw.GetNumber(1);
-
- int order;
- if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, out order))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
- return false;
- }
- int year;
-
- if (order == ORDER_MDY)
- {
- if (TryAdjustYear(ref result, n2, out year) && result.calendar.IsValidDay(year, raw.month, n1, result.era))
- {
- result.SetDate(year, raw.month, n1); // MDY
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- else if (TryAdjustYear(ref result, n1, out year) && result.calendar.IsValidDay(year, raw.month, n2, result.era))
- {
- result.SetDate(year, raw.month, n2); // YMD
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- else if (order == ORDER_YMD)
- {
- if (TryAdjustYear(ref result, n1, out year) && result.calendar.IsValidDay(year, raw.month, n2, result.era))
- {
- result.SetDate(year, raw.month, n2); // YMD
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- else if (TryAdjustYear(ref result, n2, out year) && result.calendar.IsValidDay(year, raw.month, n1, result.era))
- {
- result.SetDate(year, raw.month, n1); // DMY
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
- else if (order == ORDER_DMY)
- {
- if (TryAdjustYear(ref result, n2, out year) && result.calendar.IsValidDay(year, raw.month, n1, result.era))
- {
- result.SetDate(year, raw.month, n1); // DMY
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- else if (TryAdjustYear(ref result, n1, out year) && result.calendar.IsValidDay(year, raw.month, n2, result.era))
- {
- result.SetDate(year, raw.month, n2); // YMD
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- }
-
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int n1 = raw.GetNumber(0);
- int n2 = raw.GetNumber(1);
- string pattern = dtfi.ShortDatePattern;
-
- // For compatibility, don't throw if we can't determine the order, but default to YMD instead
- int order;
- if (GetYearMonthDayOrder(pattern, out order) && order == ORDER_YDM)
- {
- if (SetDateYMD(ref result, raw.year, n2, n1))
- {
- result.flags |= ParseFlags.HaveDate;
- return true; // Year + DM
- }
- }
- else
- {
- if (SetDateYMD(ref result, raw.year, n1, n2))
- {
- result.flags |= ParseFlags.HaveDate;
- return true; // Year + MD
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int n1 = raw.GetNumber(0);
- int n2 = raw.GetNumber(1);
-
- int order;
- if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, out order))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
- return false;
- }
-
- if (order == ORDER_MDY || order == ORDER_YMD)
- {
- if (SetDateYMD(ref result, raw.year, n1, n2))
- {
- result.flags |= ParseFlags.HaveDate;
- return true; // MD + Year
- }
- }
- else
- {
- if (SetDateYMD(ref result, raw.year, n2, n1))
- {
- result.flags |= ParseFlags.HaveDate;
- return true; // DM + Year
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if (SetDateYMD(ref result, raw.year, raw.month, raw.GetNumber(0)))
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if (SetDateYMD(ref result, raw.year, raw.GetNumber(0), 1))
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static bool GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if ((result.flags & ParseFlags.HaveDate) != 0)
- {
- // Multiple dates in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if (SetDateYMD(ref result, raw.year, raw.month, 1))
- {
- result.flags |= ParseFlags.HaveDate;
- return true;
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- private static void AdjustTimeMark(DateTimeFormatInfo dtfi, ref DateTimeRawInfo raw)
- {
- // Specail case for culture which uses AM as empty string.
- // E.g. af-ZA (0x0436)
- // S1159 \x0000
- // S2359 nm
- // In this case, if we are parsing a string like "2005/09/14 12:23", we will assume this is in AM.
-
- if (raw.timeMark == TM.NotSet)
- {
- if (dtfi.AMDesignator != null && dtfi.PMDesignator != null)
- {
- if (dtfi.AMDesignator.Length == 0 && dtfi.PMDesignator.Length != 0)
- {
- raw.timeMark = TM.AM;
- }
- if (dtfi.PMDesignator.Length == 0 && dtfi.AMDesignator.Length != 0)
- {
- raw.timeMark = TM.PM;
- }
- }
- }
- }
-
- //
- // Adjust hour according to the time mark.
- //
- private static bool AdjustHour(ref int hour, TM timeMark)
- {
- if (timeMark != TM.NotSet)
- {
- if (timeMark == TM.AM)
- {
- if (hour < 0 || hour > 12)
- {
- return false;
- }
- hour = (hour == 12) ? 0 : hour;
- }
- else
- {
- if (hour < 0 || hour > 23)
- {
- return false;
- }
- if (hour < 12)
- {
- hour += 12;
- }
- }
- }
- return true;
- }
-
- private static bool GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if ((result.flags & ParseFlags.HaveTime) != 0)
- {
- // Multiple times in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
- //
- // In this case, we need a time mark. Check if so.
- //
- if (raw.timeMark == TM.NotSet)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- result.Hour = raw.GetNumber(0);
- result.flags |= ParseFlags.HaveTime;
- return true;
- }
-
- private static bool GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- Debug.Assert(raw.numCount >= 2, "raw.numCount >= 2");
- if ((result.flags & ParseFlags.HaveTime) != 0)
- {
- // Multiple times in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
-
- result.Hour = raw.GetNumber(0);
- result.Minute = raw.GetNumber(1);
- result.flags |= ParseFlags.HaveTime;
- return true;
- }
-
- private static bool GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if ((result.flags & ParseFlags.HaveTime) != 0)
- {
- // Multiple times in the input string
- result.SetBadDateTimeFailure();
- return false;
- }
- Debug.Assert(raw.numCount >= 3, "raw.numCount >= 3");
- result.Hour = raw.GetNumber(0);
- result.Minute = raw.GetNumber(1);
- result.Second = raw.GetNumber(2);
- result.flags |= ParseFlags.HaveTime;
- return true;
- }
-
- //
- // Processing terminal state: A Date suffix followed by one number.
- //
- private static bool GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if (raw.numCount != 1 || result.Day != -1)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- result.Day = raw.GetNumber(0);
- return true;
- }
-
- private static bool GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
- {
- if (result.Month == -1)
- {
- // Should have a month suffix
- result.SetBadDateTimeFailure();
- return false;
- }
- if (result.Year != -1)
- {
- // Already has a year suffix
- result.SetBadDateTimeFailure();
- return false;
- }
- if (!TryAdjustYear(ref result, raw.GetNumber(0), out result.Year))
- {
- // the year value is out of range
- result.SetBadDateTimeFailure();
- return false;
- }
- result.Day = 1;
- return true;
- }
-
- private static bool GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- // For partial CJK Dates, the only valid formats are with a specified year, followed by two numbers, which
- // will be the Month and Day, and with a specified Month, when the numbers are either the year and day or
- // day and year, depending on the short date pattern.
-
- if ((result.flags & ParseFlags.HaveYear) != 0)
- {
- if (((result.flags & ParseFlags.HaveMonth) == 0) && ((result.flags & ParseFlags.HaveDay) == 0))
- {
- if (TryAdjustYear(ref result, raw.year, out result.Year) && SetDateYMD(ref result, result.Year, raw.GetNumber(0), raw.GetNumber(1)))
- {
- return true;
- }
- }
- }
- else if ((result.flags & ParseFlags.HaveMonth) != 0)
- {
- if (((result.flags & ParseFlags.HaveYear) == 0) && ((result.flags & ParseFlags.HaveDay) == 0))
- {
- int order;
- if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, out order))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDatePattern), dtfi.ShortDatePattern);
- return false;
- }
- int year;
- if (order == ORDER_YMD)
- {
- if (TryAdjustYear(ref result, raw.GetNumber(0), out year) && SetDateYMD(ref result, year, result.Month, raw.GetNumber(1)))
- {
- return true;
- }
- }
- else
- {
- if (TryAdjustYear(ref result, raw.GetNumber(1), out year) && SetDateYMD(ref result, year, result.Month, raw.GetNumber(0)))
- {
- return true;
- }
- }
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
-
- //
- // A date suffix is found, use this method to put the number into the result.
- //
- private static bool ProcessDateTimeSuffix(ref DateTimeResult result, ref DateTimeRawInfo raw, ref DateTimeToken dtok)
- {
- switch (dtok.suffix)
- {
- case TokenType.SEP_YearSuff:
- if ((result.flags & ParseFlags.HaveYear) != 0)
- {
- return false;
- }
- result.flags |= ParseFlags.HaveYear;
- result.Year = raw.year = dtok.num;
- break;
- case TokenType.SEP_MonthSuff:
- if ((result.flags & ParseFlags.HaveMonth) != 0)
- {
- return false;
- }
- result.flags |= ParseFlags.HaveMonth;
- result.Month = raw.month = dtok.num;
- break;
- case TokenType.SEP_DaySuff:
- if ((result.flags & ParseFlags.HaveDay) != 0)
- {
- return false;
- }
- result.flags |= ParseFlags.HaveDay;
- result.Day = dtok.num;
- break;
- case TokenType.SEP_HourSuff:
- if ((result.flags & ParseFlags.HaveHour) != 0)
- {
- return false;
- }
- result.flags |= ParseFlags.HaveHour;
- result.Hour = dtok.num;
- break;
- case TokenType.SEP_MinuteSuff:
- if ((result.flags & ParseFlags.HaveMinute) != 0)
- {
- return false;
- }
- result.flags |= ParseFlags.HaveMinute;
- result.Minute = dtok.num;
- break;
- case TokenType.SEP_SecondSuff:
- if ((result.flags & ParseFlags.HaveSecond) != 0)
- {
- return false;
- }
- result.flags |= ParseFlags.HaveSecond;
- result.Second = dtok.num;
- break;
- }
- return true;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Actions:
- // This is used by DateTime.Parse().
- // Process the terminal state for the Hebrew calendar parsing.
- //
- ////////////////////////////////////////////////////////////////////////
-
- internal static bool ProcessHebrewTerminalState(DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- // The following are accepted terminal state for Hebrew date.
- switch (dps)
- {
- case DS.DX_MNN:
- // Deal with the default long/short date format when the year number is ambigous (i.e. year < 100).
- raw.year = raw.GetNumber(1);
- if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- if (!GetDayOfMNN(ref result, ref raw, dtfi))
- {
- return false;
- }
- break;
- case DS.DX_YMN:
- // Deal with the default long/short date format when the year number is NOT ambigous (i.e. year >= 100).
- if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- if (!GetDayOfYMN(ref result, ref raw))
- {
- return false;
- }
- break;
- case DS.DX_NNY:
- // When formatting, we only format up to the hundred digit of the Hebrew year, although Hebrew year is now over 5000.
- // E.g. if the year is 5763, we only format as 763. so we do the reverse when parsing.
- if (raw.year < 1000)
- {
- raw.year += 5000;
- }
- if (!GetDayOfNNY(ref result, ref raw, dtfi))
- {
- return false;
- }
- if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- break;
- case DS.DX_NM:
- case DS.DX_MN:
- // Deal with Month/Day pattern.
- GetDefaultYear(ref result, ref styles);
- if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- if (!GetHebrewDayOfNM(ref result, ref raw, dtfi))
- {
- return false;
- }
- break;
- case DS.DX_YM:
- // Deal with Year/Month pattern.
- if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- if (!GetDayOfYM(ref result, ref raw))
- {
- return false;
- }
- break;
- case DS.TX_N:
- // Deal hour + AM/PM
- if (!GetTimeOfN(ref result, ref raw))
- {
- return false;
- }
- break;
- case DS.TX_NN:
- if (!GetTimeOfNN(ref result, ref raw))
- {
- return false;
- }
- break;
- case DS.TX_NNN:
- if (!GetTimeOfNNN(ref result, ref raw))
- {
- return false;
- }
- break;
- default:
- result.SetBadDateTimeFailure();
- return false;
- }
- if (dps > DS.ERROR)
- {
- //
- // We have reached a terminal state. Reset the raw num count.
- //
- raw.numCount = 0;
- }
- return true;
- }
-
- //
- // A terminal state has been reached, call the appropriate function to fill in the parsing result.
- // Return true if the state is a terminal state.
- //
- internal static bool ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
- {
- bool passed = true;
- switch (dps)
- {
- case DS.DX_NN:
- passed = GetDayOfNN(ref result, ref styles, ref raw, dtfi);
- break;
- case DS.DX_NNN:
- passed = GetDayOfNNN(ref result, ref raw, dtfi);
- break;
- case DS.DX_MN:
- passed = GetDayOfMN(ref result, ref styles, ref raw, dtfi);
- break;
- case DS.DX_NM:
- passed = GetDayOfNM(ref result, ref styles, ref raw, dtfi);
- break;
- case DS.DX_MNN:
- passed = GetDayOfMNN(ref result, ref raw, dtfi);
- break;
- case DS.DX_DS:
- // The result has got the correct value. No need to process.
- passed = true;
- break;
- case DS.DX_YNN:
- passed = GetDayOfYNN(ref result, ref raw, dtfi);
- break;
- case DS.DX_NNY:
- passed = GetDayOfNNY(ref result, ref raw, dtfi);
- break;
- case DS.DX_YMN:
- passed = GetDayOfYMN(ref result, ref raw);
- break;
- case DS.DX_YN:
- passed = GetDayOfYN(ref result, ref raw);
- break;
- case DS.DX_YM:
- passed = GetDayOfYM(ref result, ref raw);
- break;
- case DS.TX_N:
- passed = GetTimeOfN(ref result, ref raw);
- break;
- case DS.TX_NN:
- passed = GetTimeOfNN(ref result, ref raw);
- break;
- case DS.TX_NNN:
- passed = GetTimeOfNNN(ref result, ref raw);
- break;
- case DS.TX_TS:
- // The result has got the correct value. Nothing to do.
- passed = true;
- break;
- case DS.DX_DSN:
- passed = GetDateOfDSN(ref result, ref raw);
- break;
- case DS.DX_NDS:
- passed = GetDateOfNDS(ref result, ref raw);
- break;
- case DS.DX_NNDS:
- passed = GetDateOfNNDS(ref result, ref raw, dtfi);
- break;
- }
-
- PTSTraceExit(dps, passed);
- if (!passed)
- {
- return false;
- }
-
- if (dps > DS.ERROR)
- {
- //
- // We have reached a terminal state. Reset the raw num count.
- //
- raw.numCount = 0;
- }
- return true;
- }
-
- internal static DateTime Parse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
- {
- DateTimeResult result = default; // The buffer to store the parsing result.
- result.Init(s);
- if (TryParse(s, dtfi, styles, ref result))
- {
- return result.parsedDate;
- }
- else
- {
- throw GetDateTimeParseException(ref result);
- }
- }
-
- internal static DateTime Parse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out TimeSpan offset)
- {
- DateTimeResult result = default; // The buffer to store the parsing result.
- result.Init(s);
- result.flags |= ParseFlags.CaptureOffset;
- if (TryParse(s, dtfi, styles, ref result))
- {
- offset = result.timeZoneOffset;
- return result.parsedDate;
- }
- else
- {
- throw GetDateTimeParseException(ref result);
- }
- }
-
- internal static bool TryParse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out DateTime result)
- {
- DateTimeResult resultData = default; // The buffer to store the parsing result.
- resultData.Init(s);
-
- if (TryParse(s, dtfi, styles, ref resultData))
- {
- result = resultData.parsedDate;
- return true;
- }
-
- result = DateTime.MinValue;
- return false;
- }
-
- internal static bool TryParse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out DateTime result, out TimeSpan offset)
- {
- DateTimeResult parseResult = default; // The buffer to store the parsing result.
- parseResult.Init(s);
- parseResult.flags |= ParseFlags.CaptureOffset;
-
- if (TryParse(s, dtfi, styles, ref parseResult))
- {
- result = parseResult.parsedDate;
- offset = parseResult.timeZoneOffset;
- return true;
- }
-
- result = DateTime.MinValue;
- offset = TimeSpan.Zero;
- return false;
- }
-
- //
- // This is the real method to do the parsing work.
- //
- internal static bool TryParse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result)
- {
- if (s.Length == 0)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDateTime));
- return false;
- }
-
- Debug.Assert(dtfi != null, "dtfi == null");
-
-#if _LOGGING
- DTFITrace(dtfi);
-#endif
-
- DateTime time;
- //
- // First try the predefined format.
- //
-
- DS dps = DS.BEGIN; // Date Parsing State.
- bool reachTerminalState = false;
-
- DateTimeToken dtok = default; // The buffer to store the parsing token.
- dtok.suffix = TokenType.SEP_Unk;
- DateTimeRawInfo raw = default; // The buffer to store temporary parsing information.
- unsafe
- {
- int* numberPointer = stackalloc int[3];
- raw.Init(numberPointer);
- }
- raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal);
-
- result.calendar = dtfi.Calendar;
- result.era = Calendar.CurrentEra;
-
- //
- // The string to be parsed. Use a __DTString wrapper so that we can trace the index which
- // indicates the begining of next token.
- //
- __DTString str = new __DTString(s, dtfi);
-
- str.GetNext();
-
- //
- // The following loop will break out when we reach the end of the str.
- //
- do
- {
- //
- // Call the lexer to get the next token.
- //
- // If we find a era in Lex(), the era value will be in raw.era.
- if (!Lex(dps, ref str, ref dtok, ref raw, ref result, ref dtfi, styles))
- {
- TPTraceExit("0000", dps);
- return false;
- }
-
- //
- // If the token is not unknown, process it.
- // Otherwise, just discard it.
- //
- if (dtok.dtt != DTT.Unk)
- {
- //
- // Check if we got any CJK Date/Time suffix.
- // Since the Date/Time suffix tells us the number belongs to year/month/day/hour/minute/second,
- // store the number in the appropriate field in the result.
- //
- if (dtok.suffix != TokenType.SEP_Unk)
- {
- if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok))
- {
- result.SetBadDateTimeFailure();
- TPTraceExit("0010", dps);
- return false;
- }
-
- dtok.suffix = TokenType.SEP_Unk; // Reset suffix to SEP_Unk;
- }
-
- if (dtok.dtt == DTT.NumLocalTimeMark)
- {
- if (dps == DS.D_YNd || dps == DS.D_YN)
- {
- // Consider this as ISO 8601 format:
- // "yyyy-MM-dd'T'HH:mm:ss" 1999-10-31T02:00:00
- TPTraceExit("0020", dps);
- return ParseISO8601(ref raw, ref str, styles, ref result);
- }
- else
- {
- result.SetBadDateTimeFailure();
- TPTraceExit("0030", dps);
- return false;
- }
- }
-
- if (raw.hasSameDateAndTimeSeparators)
- {
- if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep)
- {
- // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
- // as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead
- if (dps == DS.T_Nt)
- {
- dps = DS.D_Nd;
- }
- if (dps == DS.T_NNt)
- {
- dps = DS.D_NNd;
- }
- }
-
- bool atEnd = str.AtEnd();
- if (dateParsingStates[(int)dps][(int)dtok.dtt] == DS.ERROR || atEnd)
- {
- switch (dtok.dtt)
- {
- // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
- // changing the token to end with space instead of Date Separator will avoid failing the parsing.
-
- case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break;
- case DTT.NumDatesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break;
- case DTT.NumTimesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break;
- case DTT.MonthDatesep: dtok.dtt = atEnd ? DTT.MonthEnd : DTT.MonthSpace; break;
- }
- }
- }
-
- //
- // Advance to the next state, and continue
- //
- dps = dateParsingStates[(int)dps][(int)dtok.dtt];
-
- if (dps == DS.ERROR)
- {
- result.SetBadDateTimeFailure();
- TPTraceExit("0040 (invalid state transition)", dps);
- return false;
- }
- else if (dps > DS.ERROR)
- {
- if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0)
- {
- if (!ProcessHebrewTerminalState(dps, ref result, ref styles, ref raw, dtfi))
- {
- TPTraceExit("0050 (ProcessHebrewTerminalState)", dps);
- return false;
- }
- }
- else
- {
- if (!ProcessTerminalState(dps, ref str, ref result, ref styles, ref raw, dtfi))
- {
- TPTraceExit("0060 (ProcessTerminalState)", dps);
- return false;
- }
- }
- reachTerminalState = true;
-
- //
- // If we have reached a terminal state, start over from DS.BEGIN again.
- // For example, when we parsed "1999-12-23 13:30", we will reach a terminal state at "1999-12-23",
- // and we start over so we can continue to parse "12:30".
- //
- dps = DS.BEGIN;
- }
- }
- } while (dtok.dtt != DTT.End && dtok.dtt != DTT.NumEnd && dtok.dtt != DTT.MonthEnd);
-
- if (!reachTerminalState)
- {
- result.SetBadDateTimeFailure();
- TPTraceExit("0070 (did not reach terminal state)", dps);
- return false;
- }
-
- AdjustTimeMark(dtfi, ref raw);
- if (!AdjustHour(ref result.Hour, raw.timeMark))
- {
- result.SetBadDateTimeFailure();
- TPTraceExit("0080 (AdjustHour)", dps);
- return false;
- }
-
- // Check if the parsed string only contains hour/minute/second values.
- bool bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);
-
- //
- // Check if any year/month/day is missing in the parsing string.
- // If yes, get the default value from today's date.
- //
- if (!CheckDefaultDateTime(ref result, ref result.calendar, styles))
- {
- TPTraceExit("0090 (failed to fill in missing year/month/day defaults)", dps);
- return false;
- }
-
- if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day,
- result.Hour, result.Minute, result.Second, 0, result.era, out time))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- TPTraceExit("0100 (result.calendar.TryToDateTime)", dps);
- return false;
- }
-
- if (raw.fraction > 0)
- {
- if (!time.TryAddTicks((long)Math.Round(raw.fraction * Calendar.TicksPerSecond), out time))
- {
- result.SetBadDateTimeFailure();
- TPTraceExit("0100 (time.TryAddTicks)", dps);
- return false;
- }
- }
-
- //
- // We have to check day of week before we adjust to the time zone.
- // Otherwise, the value of day of week may change after adjusting to the time zone.
- //
- if (raw.dayOfWeek != -1)
- {
- //
- // Check if day of week is correct.
- //
- if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time))
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
- TPTraceExit("0110 (dayOfWeek check)", dps);
- return false;
- }
- }
-
- result.parsedDate = time;
-
- if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
- {
- TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
- return false;
- }
- TPTraceExit("0130 (success)", dps);
- return true;
- }
-
- // Handles time zone adjustments and sets DateTimeKind values as required by the styles
- private static bool DetermineTimeZoneAdjustments(ref DateTimeResult result, DateTimeStyles styles, bool bTimeOnly)
- {
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
- // no adjustment is required in most cases
- return DateTimeOffsetTimeZonePostProcessing(ref result, styles);
- }
- else
- {
- long offsetTicks = result.timeZoneOffset.Ticks;
-
- // the DateTime offset must be within +- 14:00 hours.
- if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_OffsetOutOfRange));
- return false;
- }
- }
-
- // The flags AssumeUniveral and AssumeLocal only apply when the input does not have a time zone
- if ((result.flags & ParseFlags.TimeZoneUsed) == 0)
- {
- // If AssumeLocal or AssumeLocal is used, there will always be a kind specified. As in the
- // case when a time zone is present, it will default to being local unless AdjustToUniversal
- // is present. These comparisons determine whether setting the kind is sufficient, or if a
- // time zone adjustment is required. For consistentcy with the rest of parsing, it is desirable
- // to fall through to the Adjust methods below, so that there is consist handling of boundary
- // cases like wrapping around on time-only dates and temporarily allowing an adjusted date
- // to exceed DateTime.MaxValue
- if ((styles & DateTimeStyles.AssumeLocal) != 0)
- {
- if ((styles & DateTimeStyles.AdjustToUniversal) != 0)
- {
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = TimeZoneInfo.GetLocalUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- }
- else
- {
- result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Local);
- return true;
- }
- }
- else if ((styles & DateTimeStyles.AssumeUniversal) != 0)
- {
- if ((styles & DateTimeStyles.AdjustToUniversal) != 0)
- {
- result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Utc);
- return true;
- }
- else
- {
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = TimeSpan.Zero;
- }
- }
- else
- {
- // No time zone and no Assume flags, so DateTimeKind.Unspecified is fine
- Debug.Assert(result.parsedDate.Kind == DateTimeKind.Unspecified, "result.parsedDate.Kind == DateTimeKind.Unspecified");
- return true;
- }
- }
-
- if (((styles & DateTimeStyles.RoundtripKind) != 0) && ((result.flags & ParseFlags.TimeZoneUtc) != 0))
- {
- result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Utc);
- return true;
- }
-
- if ((styles & DateTimeStyles.AdjustToUniversal) != 0)
- {
- return AdjustTimeZoneToUniversal(ref result);
- }
- return AdjustTimeZoneToLocal(ref result, bTimeOnly);
- }
-
- // Apply validation and adjustments specific to DateTimeOffset
- private static bool DateTimeOffsetTimeZonePostProcessing(ref DateTimeResult result, DateTimeStyles styles)
- {
- // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
- // the input string.
- if ((result.flags & ParseFlags.TimeZoneUsed) == 0)
- {
- if ((styles & DateTimeStyles.AssumeUniversal) != 0)
- {
- // AssumeUniversal causes the offset to default to zero (0)
- result.timeZoneOffset = TimeSpan.Zero;
- }
- else
- {
- // AssumeLocal causes the offset to default to Local. This flag is on by default for DateTimeOffset.
- result.timeZoneOffset = TimeZoneInfo.GetLocalUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- }
- }
-
- long offsetTicks = result.timeZoneOffset.Ticks;
-
- // there should be no overflow, because the offset can be no more than -+100 hours and the date already
- // fits within a DateTime.
- long utcTicks = result.parsedDate.Ticks - offsetTicks;
-
- // For DateTimeOffset, both the parsed time and the corresponding UTC value must be within the boundaries
- // of a DateTime instance.
- if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_UTCOutOfRange));
- return false;
- }
-
- // the offset must be within +- 14:00 hours.
- if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_OffsetOutOfRange));
- return false;
- }
-
- // DateTimeOffset should still honor the AdjustToUniversal flag for consistency with DateTime. It means you
- // want to return an adjusted UTC value, so store the utcTicks in the DateTime and set the offset to zero
- if ((styles & DateTimeStyles.AdjustToUniversal) != 0)
- {
- if (((result.flags & ParseFlags.TimeZoneUsed) == 0) && ((styles & DateTimeStyles.AssumeUniversal) == 0))
- {
- // Handle the special case where the timeZoneOffset was defaulted to Local
- bool toUtcResult = AdjustTimeZoneToUniversal(ref result);
- result.timeZoneOffset = TimeSpan.Zero;
- return toUtcResult;
- }
-
- // The constructor should always succeed because of the range check earlier in the function
- // Although it is UTC, internally DateTimeOffset does not use this flag
- result.parsedDate = new DateTime(utcTicks, DateTimeKind.Utc);
- result.timeZoneOffset = TimeSpan.Zero;
- }
-
- return true;
- }
-
- //
- // Adjust the specified time to universal time based on the supplied timezone.
- // E.g. when parsing "2001/06/08 14:00-07:00",
- // the time is 2001/06/08 14:00, and timeZoneOffset = -07:00.
- // The result will be "2001/06/08 21:00"
- //
- private static bool AdjustTimeZoneToUniversal(ref DateTimeResult result)
- {
- long resultTicks = result.parsedDate.Ticks;
- resultTicks -= result.timeZoneOffset.Ticks;
- if (resultTicks < 0)
- {
- resultTicks += Calendar.TicksPerDay;
- }
-
- if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_DateOutOfRange));
- return false;
- }
- result.parsedDate = new DateTime(resultTicks, DateTimeKind.Utc);
- return true;
- }
-
- //
- // Adjust the specified time to universal time based on the supplied timezone,
- // and then convert to local time.
- // E.g. when parsing "2001/06/08 14:00-04:00", and local timezone is GMT-7.
- // the time is 2001/06/08 14:00, and timeZoneOffset = -05:00.
- // The result will be "2001/06/08 11:00"
- //
- private static bool AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
- {
- long resultTicks = result.parsedDate.Ticks;
- // Convert to local ticks
- TimeZoneInfo tz = TimeZoneInfo.Local;
- bool isAmbiguousLocalDst = false;
- if (resultTicks < Calendar.TicksPerDay)
- {
- //
- // This is time of day.
- //
-
- // Adjust timezone.
- resultTicks -= result.timeZoneOffset.Ticks;
- // If the time is time of day, use the current timezone offset.
- resultTicks += tz.GetUtcOffset(bTimeOnly ? DateTime.Now : result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
-
- if (resultTicks < 0)
- {
- resultTicks += Calendar.TicksPerDay;
- }
- }
- else
- {
- // Adjust timezone to GMT.
- resultTicks -= result.timeZoneOffset.Ticks;
- if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
- {
- // If the result ticks is greater than DateTime.MaxValue, we can not create a DateTime from this ticks.
- // In this case, keep using the old code.
- resultTicks += tz.GetUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
- }
- else
- {
- // Convert the GMT time to local time.
- DateTime utcDt = new DateTime(resultTicks, DateTimeKind.Utc);
- bool isDaylightSavings = false;
- resultTicks += TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
- }
- }
- if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
- {
- result.parsedDate = DateTime.MinValue;
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_DateOutOfRange));
- return false;
- }
- result.parsedDate = new DateTime(resultTicks, DateTimeKind.Local, isAmbiguousLocalDst);
- return true;
- }
-
- //
- // Parse the ISO8601 format string found during Parse();
- //
- //
- private static bool ParseISO8601(ref DateTimeRawInfo raw, ref __DTString str, DateTimeStyles styles, ref DateTimeResult result)
- {
- if (raw.year < 0 || raw.GetNumber(0) < 0 || raw.GetNumber(1) < 0)
- {
- }
- str.Index--;
- int hour, minute;
- int second = 0;
- double partSecond = 0;
-
- str.SkipWhiteSpaces();
- if (!ParseDigits(ref str, 2, out hour))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- str.SkipWhiteSpaces();
- if (!str.Match(':'))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- str.SkipWhiteSpaces();
- if (!ParseDigits(ref str, 2, out minute))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- str.SkipWhiteSpaces();
- if (str.Match(':'))
- {
- str.SkipWhiteSpaces();
- if (!ParseDigits(ref str, 2, out second))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if (str.Match('.'))
- {
- if (!ParseFraction(ref str, out partSecond))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- str.Index--;
- }
- str.SkipWhiteSpaces();
- }
- if (str.GetNext())
- {
- char ch = str.GetChar();
- if (ch == '+' || ch == '-')
- {
- result.flags |= ParseFlags.TimeZoneUsed;
- if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- else if (ch == 'Z' || ch == 'z')
- {
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = TimeSpan.Zero;
- result.flags |= ParseFlags.TimeZoneUtc;
- }
- else
- {
- str.Index--;
- }
- str.SkipWhiteSpaces();
- if (str.Match('#'))
- {
- if (!VerifyValidPunctuation(ref str))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- str.SkipWhiteSpaces();
- }
- if (str.Match('\0'))
- {
- if (!VerifyValidPunctuation(ref str))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- if (str.GetNext())
- {
- // If this is true, there were non-white space characters remaining in the DateTime
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- DateTime time;
- Calendar calendar = GregorianCalendar.GetDefaultInstance();
- if (!calendar.TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1),
- hour, minute, second, 0, result.era, out time))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
-
- if (!time.TryAddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond), out time))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- result.parsedDate = time;
- return DetermineTimeZoneAdjustments(ref result, styles, false);
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Actions:
- // Parse the current word as a Hebrew number.
- // This is used by DateTime.ParseExact().
- //
- ////////////////////////////////////////////////////////////////////////
-
- internal static bool MatchHebrewDigits(ref __DTString str, int digitLen, out int number)
- {
- number = 0;
-
- // Create a context object so that we can parse the Hebrew number text character by character.
- HebrewNumberParsingContext context = new HebrewNumberParsingContext(0);
-
- // Set this to ContinueParsing so that we will run the following while loop in the first time.
- HebrewNumberParsingState state = HebrewNumberParsingState.ContinueParsing;
-
- while (state == HebrewNumberParsingState.ContinueParsing && str.GetNext())
- {
- state = HebrewNumber.ParseByChar(str.GetChar(), ref context);
- }
-
- if (state == HebrewNumberParsingState.FoundEndOfHebrewNumber)
- {
- // If we have reached a terminal state, update the result and returns.
- number = context.result;
- return true;
- }
-
- // If we run out of the character before reaching FoundEndOfHebrewNumber, or
- // the state is InvalidHebrewNumber or ContinueParsing, we fail to match a Hebrew number.
- // Return an error.
- return false;
- }
-
- /*=================================ParseDigits==================================
- **Action: Parse the number string in __DTString that are formatted using
- ** the following patterns:
- ** "0", "00", and "000..0"
- **Returns: the integer value
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if error in parsing number.
- ==============================================================================*/
-
- internal static bool ParseDigits(ref __DTString str, int digitLen, out int result)
- {
- if (digitLen == 1)
- {
- // 1 really means 1 or 2 for this call
- return ParseDigits(ref str, 1, 2, out result);
- }
- else
- {
- return ParseDigits(ref str, digitLen, digitLen, out result);
- }
- }
-
- internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result)
- {
- Debug.Assert(minDigitLen > 0, "minDigitLen > 0");
- Debug.Assert(maxDigitLen < 9, "maxDigitLen < 9");
- Debug.Assert(minDigitLen <= maxDigitLen, "minDigitLen <= maxDigitLen");
- int localResult = 0;
- int startingIndex = str.Index;
- int tokenLength = 0;
- while (tokenLength < maxDigitLen)
- {
- if (!str.GetNextDigit())
- {
- str.Index--;
- break;
- }
- localResult = localResult * 10 + str.GetDigit();
- tokenLength++;
- }
- result = localResult;
- if (tokenLength < minDigitLen)
- {
- str.Index = startingIndex;
- return false;
- }
- return true;
- }
-
- /*=================================ParseFractionExact==================================
- **Action: Parse the number string in __DTString that are formatted using
- ** the following patterns:
- ** "0", "00", and "000..0"
- **Returns: the fraction value
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if error in parsing number.
- ==============================================================================*/
-
- private static bool ParseFractionExact(ref __DTString str, int maxDigitLen, ref double result)
- {
- if (!str.GetNextDigit())
- {
- str.Index--;
- return false;
- }
- result = str.GetDigit();
-
- int digitLen = 1;
- for (; digitLen < maxDigitLen; digitLen++)
- {
- if (!str.GetNextDigit())
- {
- str.Index--;
- break;
- }
- result = result * 10 + str.GetDigit();
- }
-
- result /= TimeSpanParse.Pow10(digitLen);
- return digitLen == maxDigitLen;
- }
-
- /*=================================ParseSign==================================
- **Action: Parse a positive or a negative sign.
- **Returns: true if postive sign. flase if negative sign.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if end of string is encountered or a sign
- ** symbol is not found.
- ==============================================================================*/
-
- private static bool ParseSign(ref __DTString str, ref bool result)
- {
- if (!str.GetNext())
- {
- // A sign symbol ('+' or '-') is expected. However, end of string is encountered.
- return false;
- }
- char ch = str.GetChar();
- if (ch == '+')
- {
- result = true;
- return true;
- }
- else if (ch == '-')
- {
- result = false;
- return true;
- }
- // A sign symbol ('+' or '-') is expected.
- return false;
- }
-
- /*=================================ParseTimeZoneOffset==================================
- **Action: Parse the string formatted using "z", "zz", "zzz" in DateTime.Format().
- **Returns: the TimeSpan for the parsed timezone offset.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- ** len: the repeated number of the "z"
- **Exceptions: FormatException if errors in parsing.
- ==============================================================================*/
-
- private static bool ParseTimeZoneOffset(ref __DTString str, int len, ref TimeSpan result)
- {
- bool isPositive = true;
- int hourOffset;
- int minuteOffset = 0;
-
- switch (len)
- {
- case 1:
- case 2:
- if (!ParseSign(ref str, ref isPositive))
- {
- return false;
- }
- if (!ParseDigits(ref str, len, out hourOffset))
- {
- return false;
- }
- break;
- default:
- if (!ParseSign(ref str, ref isPositive))
- {
- return false;
- }
-
- // Parsing 1 digit will actually parse 1 or 2.
- if (!ParseDigits(ref str, 1, out hourOffset))
- {
- return false;
- }
- // ':' is optional.
- if (str.Match(":"))
- {
- // Found ':'
- if (!ParseDigits(ref str, 2, out minuteOffset))
- {
- return false;
- }
- }
- else
- {
- // Since we can not match ':', put the char back.
- str.Index--;
- if (!ParseDigits(ref str, 2, out minuteOffset))
- {
- return false;
- }
- }
- break;
- }
- if (minuteOffset < 0 || minuteOffset >= 60)
- {
- return false;
- }
-
- result = (new TimeSpan(hourOffset, minuteOffset, 0));
- if (!isPositive)
- {
- result = result.Negate();
- }
- return true;
- }
-
- /*=================================MatchAbbreviatedMonthName==================================
- **Action: Parse the abbreviated month name from string starting at str.Index.
- **Returns: A value from 1 to 12 for the first month to the twelfth month.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if an abbreviated month name can not be found.
- ==============================================================================*/
-
- private static bool MatchAbbreviatedMonthName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result)
- {
- int maxMatchStrLen = 0;
- result = -1;
- if (str.GetNext())
- {
- //
- // Scan the month names (note that some calendars has 13 months) and find
- // the matching month name which has the max string length.
- // We need to do this because some cultures (e.g. "cs-CZ") which have
- // abbreviated month names with the same prefix.
- //
- int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
- for (int i = 1; i <= monthsInYear; i++)
- {
- string searchStr = dtfi.GetAbbreviatedMonthName(i);
- int matchStrLen = searchStr.Length;
- if (dtfi.HasSpacesInMonthNames
- ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
- : str.MatchSpecifiedWord(searchStr))
- {
- if (matchStrLen > maxMatchStrLen)
- {
- maxMatchStrLen = matchStrLen;
- result = i;
- }
- }
- }
-
- // Search genitive form.
- if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
- {
- int tempResult = str.MatchLongestWords(dtfi.AbbreviatedMonthGenitiveNames, ref maxMatchStrLen);
-
- // We found a longer match in the genitive month name. Use this as the result.
- // tempResult + 1 should be the month value.
- if (tempResult >= 0)
- {
- result = tempResult + 1;
- }
- }
-
- // Search leap year form.
- if ((dtfi.FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0)
- {
- int tempResult = str.MatchLongestWords(dtfi.InternalGetLeapYearMonthNames(), ref maxMatchStrLen);
- // We found a longer match in the leap year month name. Use this as the result.
- // The result from MatchLongestWords is 0 ~ length of word array.
- // So we increment the result by one to become the month value.
- if (tempResult >= 0)
- {
- result = tempResult + 1;
- }
- }
- }
- if (result > 0)
- {
- str.Index += (maxMatchStrLen - 1);
- return true;
- }
- return false;
- }
-
- /*=================================MatchMonthName==================================
- **Action: Parse the month name from string starting at str.Index.
- **Returns: A value from 1 to 12 indicating the first month to the twelfth month.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if a month name can not be found.
- ==============================================================================*/
-
- private static bool MatchMonthName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result)
- {
- int maxMatchStrLen = 0;
- result = -1;
- if (str.GetNext())
- {
- //
- // Scan the month names (note that some calendars has 13 months) and find
- // the matching month name which has the max string length.
- // We need to do this because some cultures (e.g. "vi-VN") which have
- // month names with the same prefix.
- //
- int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
- for (int i = 1; i <= monthsInYear; i++)
- {
- string searchStr = dtfi.GetMonthName(i);
- int matchStrLen = searchStr.Length;
- if (dtfi.HasSpacesInMonthNames
- ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
- : str.MatchSpecifiedWord(searchStr))
- {
- if (matchStrLen > maxMatchStrLen)
- {
- maxMatchStrLen = matchStrLen;
- result = i;
- }
- }
- }
-
- // Search genitive form.
- if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
- {
- int tempResult = str.MatchLongestWords(dtfi.MonthGenitiveNames, ref maxMatchStrLen);
- // We found a longer match in the genitive month name. Use this as the result.
- // The result from MatchLongestWords is 0 ~ length of word array.
- // So we increment the result by one to become the month value.
- if (tempResult >= 0)
- {
- result = tempResult + 1;
- }
- }
-
- // Search leap year form.
- if ((dtfi.FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0)
- {
- int tempResult = str.MatchLongestWords(dtfi.InternalGetLeapYearMonthNames(), ref maxMatchStrLen);
- // We found a longer match in the leap year month name. Use this as the result.
- // The result from MatchLongestWords is 0 ~ length of word array.
- // So we increment the result by one to become the month value.
- if (tempResult >= 0)
- {
- result = tempResult + 1;
- }
- }
- }
-
- if (result > 0)
- {
- str.Index += (maxMatchStrLen - 1);
- return true;
- }
- return false;
- }
-
- /*=================================MatchAbbreviatedDayName==================================
- **Action: Parse the abbreviated day of week name from string starting at str.Index.
- **Returns: A value from 0 to 6 indicating Sunday to Saturday.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if a abbreviated day of week name can not be found.
- ==============================================================================*/
-
- private static bool MatchAbbreviatedDayName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result)
- {
- int maxMatchStrLen = 0;
- result = -1;
- if (str.GetNext())
- {
- for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
- {
- string searchStr = dtfi.GetAbbreviatedDayName(i);
- int matchStrLen = searchStr.Length;
- if (dtfi.HasSpacesInDayNames
- ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
- : str.MatchSpecifiedWord(searchStr))
- {
- if (matchStrLen > maxMatchStrLen)
- {
- maxMatchStrLen = matchStrLen;
- result = (int)i;
- }
- }
- }
- }
- if (result >= 0)
- {
- str.Index += maxMatchStrLen - 1;
- return true;
- }
- return false;
- }
-
- /*=================================MatchDayName==================================
- **Action: Parse the day of week name from string starting at str.Index.
- **Returns: A value from 0 to 6 indicating Sunday to Saturday.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if a day of week name can not be found.
- ==============================================================================*/
-
- private static bool MatchDayName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result)
- {
- // Turkish (tr-TR) got day names with the same prefix.
- int maxMatchStrLen = 0;
- result = -1;
- if (str.GetNext())
- {
- for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
- {
- string searchStr = dtfi.GetDayName(i);
- int matchStrLen = searchStr.Length;
- if (dtfi.HasSpacesInDayNames
- ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
- : str.MatchSpecifiedWord(searchStr))
- {
- if (matchStrLen > maxMatchStrLen)
- {
- maxMatchStrLen = matchStrLen;
- result = (int)i;
- }
- }
- }
- }
- if (result >= 0)
- {
- str.Index += maxMatchStrLen - 1;
- return true;
- }
- return false;
- }
-
- /*=================================MatchEraName==================================
- **Action: Parse era name from string starting at str.Index.
- **Returns: An era value.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if an era name can not be found.
- ==============================================================================*/
-
- private static bool MatchEraName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result)
- {
- if (str.GetNext())
- {
- int[] eras = dtfi.Calendar.Eras;
-
- if (eras != null)
- {
- for (int i = 0; i < eras.Length; i++)
- {
- string searchStr = dtfi.GetEraName(eras[i]);
- if (str.MatchSpecifiedWord(searchStr))
- {
- str.Index += (searchStr.Length - 1);
- result = eras[i];
- return true;
- }
- searchStr = dtfi.GetAbbreviatedEraName(eras[i]);
- if (str.MatchSpecifiedWord(searchStr))
- {
- str.Index += (searchStr.Length - 1);
- result = eras[i];
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /*=================================MatchTimeMark==================================
- **Action: Parse the time mark (AM/PM) from string starting at str.Index.
- **Returns: TM_AM or TM_PM.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if a time mark can not be found.
- ==============================================================================*/
-
- private static bool MatchTimeMark(ref __DTString str, DateTimeFormatInfo dtfi, ref TM result)
- {
- result = TM.NotSet;
- // In some cultures have empty strings in AM/PM mark. E.g. af-ZA (0x0436), the AM mark is "", and PM mark is "nm".
- if (dtfi.AMDesignator.Length == 0)
- {
- result = TM.AM;
- }
- if (dtfi.PMDesignator.Length == 0)
- {
- result = TM.PM;
- }
-
- if (str.GetNext())
- {
- string searchStr = dtfi.AMDesignator;
- if (searchStr.Length > 0)
- {
- if (str.MatchSpecifiedWord(searchStr))
- {
- // Found an AM timemark with length > 0.
- str.Index += (searchStr.Length - 1);
- result = TM.AM;
- return true;
- }
- }
- searchStr = dtfi.PMDesignator;
- if (searchStr.Length > 0)
- {
- if (str.MatchSpecifiedWord(searchStr))
- {
- // Found a PM timemark with length > 0.
- str.Index += (searchStr.Length - 1);
- result = TM.PM;
- return true;
- }
- }
- str.Index--; // Undo the GetNext call.
- }
- if (result != TM.NotSet)
- {
- // If one of the AM/PM marks is empty string, return the result.
- return true;
- }
- return false;
- }
-
- /*=================================MatchAbbreviatedTimeMark==================================
- **Action: Parse the abbreviated time mark (AM/PM) from string starting at str.Index.
- **Returns: TM_AM or TM_PM.
- **Arguments: str: a __DTString. The parsing will start from the
- ** next character after str.Index.
- **Exceptions: FormatException if a abbreviated time mark can not be found.
- ==============================================================================*/
-
- private static bool MatchAbbreviatedTimeMark(ref __DTString str, DateTimeFormatInfo dtfi, ref TM result)
- {
- // NOTENOTE : the assumption here is that abbreviated time mark is the first
- // character of the AM/PM designator. If this invariant changes, we have to
- // change the code below.
- if (str.GetNext())
- {
- string amDesignator = dtfi.AMDesignator;
- if (amDesignator.Length > 0 && str.GetChar() == amDesignator[0])
- {
- result = TM.AM;
- return true;
- }
-
- string pmDesignator = dtfi.PMDesignator;
- if (pmDesignator.Length > 0 && str.GetChar() == pmDesignator[0])
- {
- result = TM.PM;
- return true;
- }
- }
- return false;
- }
-
- /*=================================CheckNewValue==================================
- **Action: Check if currentValue is initialized. If not, return the newValue.
- ** If yes, check if the current value is equal to newValue. Return false
- ** if they are not equal. This is used to check the case like "d" and "dd" are both
- ** used to format a string.
- **Returns: the correct value for currentValue.
- **Arguments:
- **Exceptions:
- ==============================================================================*/
-
- private static bool CheckNewValue(ref int currentValue, int newValue, char patternChar, ref DateTimeResult result)
- {
- if (currentValue == -1)
- {
- currentValue = newValue;
- return true;
- }
- else
- {
- if (newValue != currentValue)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), patternChar);
- return false;
- }
- }
- return true;
- }
-
- private static DateTime GetDateTimeNow(ref DateTimeResult result, ref DateTimeStyles styles)
- {
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
- {
- // use the supplied offset to calculate 'Now'
- return new DateTime(DateTime.UtcNow.Ticks + result.timeZoneOffset.Ticks, DateTimeKind.Unspecified);
- }
- else if ((styles & DateTimeStyles.AssumeUniversal) != 0)
- {
- // assume the offset is Utc
- return DateTime.UtcNow;
- }
- }
-
- // assume the offset is Local
- return DateTime.Now;
- }
-
- private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
- {
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- // DateTimeOffset.Parse should allow dates without a year, but only if there is also no time zone marker;
- // e.g. "May 1 5pm" is OK, but "May 1 5pm -08:30" is not. This is somewhat pragmatic, since we would
- // have to rearchitect parsing completely to allow this one case to correctly handle things like leap
- // years and leap months. Is an extremely corner case, and DateTime is basically incorrect in that
- // case today.
- //
- // values like "11:00Z" or "11:00 -3:00" are also acceptable
- //
- // if ((month or day is set) and (year is not set and time zone is set))
- //
- if (((result.Month != -1) || (result.Day != -1))
- && ((result.Year == -1 || ((result.flags & ParseFlags.YearDefault) != 0)) && (result.flags & ParseFlags.TimeZoneUsed) != 0))
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_MissingIncompleteDate));
- return false;
- }
- }
-
- if ((result.Year == -1) || (result.Month == -1) || (result.Day == -1))
- {
- /*
- The following table describes the behaviors of getting the default value
- when a certain year/month/day values are missing.
-
- An "X" means that the value exists. And "--" means that value is missing.
-
- Year Month Day => ResultYear ResultMonth ResultDay Note
-
- X X X Parsed year Parsed month Parsed day
- X X -- Parsed Year Parsed month First day If we have year and month, assume the first day of that month.
- X -- X Parsed year First month Parsed day If the month is missing, assume first month of that year.
- X -- -- Parsed year First month First day If we have only the year, assume the first day of that year.
-
- -- X X CurrentYear Parsed month Parsed day If the year is missing, assume the current year.
- -- X -- CurrentYear Parsed month First day If we have only a month value, assume the current year and current day.
- -- -- X CurrentYear First month Parsed day If we have only a day value, assume current year and first month.
- -- -- -- CurrentYear Current month Current day So this means that if the date string only contains time, you will get current date.
-
- */
-
- DateTime now = GetDateTimeNow(ref result, ref styles);
- if (result.Month == -1 && result.Day == -1)
- {
- if (result.Year == -1)
- {
- if ((styles & DateTimeStyles.NoCurrentDateDefault) != 0)
- {
- // If there is no year/month/day values, and NoCurrentDateDefault flag is used,
- // set the year/month/day value to the beginning year/month/day of DateTime().
- // Note we should be using Gregorian for the year/month/day.
- cal = GregorianCalendar.GetDefaultInstance();
- result.Year = result.Month = result.Day = 1;
- }
- else
- {
- // Year/Month/Day are all missing.
- result.Year = cal.GetYear(now);
- result.Month = cal.GetMonth(now);
- result.Day = cal.GetDayOfMonth(now);
- }
- }
- else
- {
- // Month/Day are both missing.
- result.Month = 1;
- result.Day = 1;
- }
- }
- else
- {
- if (result.Year == -1)
- {
- result.Year = cal.GetYear(now);
- }
- if (result.Month == -1)
- {
- result.Month = 1;
- }
- if (result.Day == -1)
- {
- result.Day = 1;
- }
- }
- }
- // Set Hour/Minute/Second to zero if these value are not in str.
- if (result.Hour == -1) result.Hour = 0;
- if (result.Minute == -1) result.Minute = 0;
- if (result.Second == -1) result.Second = 0;
- if (result.era == -1) result.era = Calendar.CurrentEra;
- return true;
- }
-
- // Expand a pre-defined format string (like "D" for long date) to the real format that
- // we are going to use in the date time parsing.
- // This method also set the dtfi according/parseInfo to some special pre-defined
- // formats.
- //
- private static string ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
- {
- //
- // Check the format to see if we need to override the dtfi to be InvariantInfo,
- // and see if we need to set up the userUniversalTime flag.
- //
- switch (format[0])
- {
- case 's': // Sortable format (in local time)
- case 'o':
- case 'O': // Round Trip Format
- ConfigureFormatOS(ref dtfi, ref parseInfo);
- break;
- case 'r':
- case 'R': // RFC 1123 Standard. (in Universal time)
- ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
- break;
- case 'u': // Universal time format in sortable format.
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
-
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- result.flags |= ParseFlags.UtcSortPattern;
- }
- break;
- case 'U': // Universal time format with culture-dependent format.
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = new TimeSpan(0);
- result.flags |= ParseFlags.TimeZoneUtc;
- if (dtfi.Calendar.GetType() != typeof(GregorianCalendar))
- {
- dtfi = (DateTimeFormatInfo)dtfi.Clone();
- dtfi.Calendar = GregorianCalendar.GetDefaultInstance();
- }
- break;
- }
-
- //
- // Expand the pre-defined format character to the real format from DateTimeFormatInfo.
- //
- return DateTimeFormat.GetRealFormat(format, dtfi);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static bool ParseJapaneseEraStart(ref __DTString str, DateTimeFormatInfo dtfi)
- {
- // ParseJapaneseEraStart will be called when parsing the year number. We can have dates which not listing
- // the year as a number and listing it as JapaneseEraStart symbol (which means year 1).
- // This will be legitimate date to recognize.
- if (LocalAppContextSwitches.EnforceLegacyJapaneseDateParsing || dtfi.Calendar.ID != CalendarId.JAPAN || !str.GetNext())
- return false;
-
- if (str.m_current != DateTimeFormatInfo.JapaneseEraStart[0])
- {
- str.Index--;
- return false;
- }
-
- return true;
- }
-
- private static void ConfigureFormatR(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
- {
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- result.flags |= ParseFlags.Rfc1123Pattern;
- }
- }
-
- private static void ConfigureFormatOS(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo)
- {
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
- }
-
- // Given a specified format character, parse and update the parsing result.
- //
- private static bool ParseByFormat(
- ref __DTString str,
- ref __DTString format,
- ref ParsingInfo parseInfo,
- DateTimeFormatInfo dtfi,
- ref DateTimeResult result)
- {
- int tokenLen = 0;
- int tempYear = 0, tempMonth = 0, tempDay = 0, tempDayOfWeek = 0, tempHour = 0, tempMinute = 0, tempSecond = 0;
- double tempFraction = 0;
- TM tempTimeMark = 0;
-
- char ch = format.GetChar();
-
- switch (ch)
- {
- case 'y':
- tokenLen = format.GetRepeatCount();
- bool parseResult;
- if (ParseJapaneseEraStart(ref str, dtfi))
- {
- tempYear = 1;
- parseResult = true;
- }
- else if (dtfi.HasForceTwoDigitYears)
- {
- parseResult = ParseDigits(ref str, 1, 4, out tempYear);
- }
- else
- {
- if (tokenLen <= 2)
- {
- parseInfo.fUseTwoDigitYear = true;
- }
- parseResult = ParseDigits(ref str, tokenLen, out tempYear);
- }
- if (!parseResult && parseInfo.fCustomNumberParser)
- {
- parseResult = parseInfo.parseNumberDelegate(ref str, tokenLen, out tempYear);
- }
- if (!parseResult)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if (!CheckNewValue(ref result.Year, tempYear, ch, ref result))
- {
- return false;
- }
- break;
- case 'M':
- tokenLen = format.GetRepeatCount();
- if (tokenLen <= 2)
- {
- if (!ParseDigits(ref str, tokenLen, out tempMonth))
- {
- if (!parseInfo.fCustomNumberParser ||
- !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempMonth))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- }
- else
- {
- if (tokenLen == 3)
- {
- if (!MatchAbbreviatedMonthName(ref str, dtfi, ref tempMonth))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- else
- {
- if (!MatchMonthName(ref str, dtfi, ref tempMonth))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- result.flags |= ParseFlags.ParsedMonthName;
- }
- if (!CheckNewValue(ref result.Month, tempMonth, ch, ref result))
- {
- return false;
- }
- break;
- case 'd':
- // Day & Day of week
- tokenLen = format.GetRepeatCount();
- if (tokenLen <= 2)
- {
- // "d" & "dd"
-
- if (!ParseDigits(ref str, tokenLen, out tempDay))
- {
- if (!parseInfo.fCustomNumberParser ||
- !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempDay))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- if (!CheckNewValue(ref result.Day, tempDay, ch, ref result))
- {
- return false;
- }
- }
- else
- {
- if (tokenLen == 3)
- {
- // "ddd"
- if (!MatchAbbreviatedDayName(ref str, dtfi, ref tempDayOfWeek))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- else
- {
- // "dddd*"
- if (!MatchDayName(ref str, dtfi, ref tempDayOfWeek))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- if (!CheckNewValue(ref parseInfo.dayOfWeek, tempDayOfWeek, ch, ref result))
- {
- return false;
- }
- }
- break;
- case 'g':
- tokenLen = format.GetRepeatCount();
- // Put the era value in result.era.
- if (!MatchEraName(ref str, dtfi, ref result.era))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- break;
- case 'h':
- parseInfo.fUseHour12 = true;
- tokenLen = format.GetRepeatCount();
- if (!ParseDigits(ref str, tokenLen < 2 ? 1 : 2, out tempHour))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result))
- {
- return false;
- }
- break;
- case 'H':
- tokenLen = format.GetRepeatCount();
- if (!ParseDigits(ref str, tokenLen < 2 ? 1 : 2, out tempHour))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result))
- {
- return false;
- }
- break;
- case 'm':
- tokenLen = format.GetRepeatCount();
- if (!ParseDigits(ref str, tokenLen < 2 ? 1 : 2, out tempMinute))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if (!CheckNewValue(ref result.Minute, tempMinute, ch, ref result))
- {
- return false;
- }
- break;
- case 's':
- tokenLen = format.GetRepeatCount();
- if (!ParseDigits(ref str, tokenLen < 2 ? 1 : 2, out tempSecond))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if (!CheckNewValue(ref result.Second, tempSecond, ch, ref result))
- {
- return false;
- }
- break;
- case 'f':
- case 'F':
- tokenLen = format.GetRepeatCount();
- if (tokenLen <= DateTimeFormat.MaxSecondsFractionDigits)
- {
- if (!ParseFractionExact(ref str, tokenLen, ref tempFraction))
- {
- if (ch == 'f')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- if (result.fraction < 0)
- {
- result.fraction = tempFraction;
- }
- else
- {
- if (tempFraction != result.fraction)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), ch);
- return false;
- }
- }
- }
- else
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- break;
- case 't':
- // AM/PM designator
- tokenLen = format.GetRepeatCount();
- if (tokenLen == 1)
- {
- if (!MatchAbbreviatedTimeMark(ref str, dtfi, ref tempTimeMark))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- else
- {
- if (!MatchTimeMark(ref str, dtfi, ref tempTimeMark))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- if (parseInfo.timeMark == TM.NotSet)
- {
- parseInfo.timeMark = tempTimeMark;
- }
- else
- {
- if (parseInfo.timeMark != tempTimeMark)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), ch);
- return false;
- }
- }
- break;
- case 'z':
- // timezone offset
- tokenLen = format.GetRepeatCount();
- {
- TimeSpan tempTimeZoneOffset = new TimeSpan(0);
- if (!ParseTimeZoneOffset(ref str, tokenLen, ref tempTimeZoneOffset))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'z');
- return false;
- }
- result.timeZoneOffset = tempTimeZoneOffset;
- result.flags |= ParseFlags.TimeZoneUsed;
- }
- break;
- case 'Z':
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'Z');
- return false;
- }
-
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = new TimeSpan(0);
- result.flags |= ParseFlags.TimeZoneUtc;
-
- // The updating of the indexes is to reflect that ParseExact MatchXXX methods assume that
- // they need to increment the index and Parse GetXXX do not. Since we are calling a Parse
- // method from inside ParseExact we need to adjust this. Long term, we should try to
- // eliminate this discrepancy.
- str.Index++;
- if (!GetTimeZoneName(ref str))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- str.Index--;
- break;
- case 'K':
- // This should parse either as a blank, the 'Z' character or a local offset like "-07:00"
- if (str.Match('Z'))
- {
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'K');
- return false;
- }
-
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = new TimeSpan(0);
- result.flags |= ParseFlags.TimeZoneUtc;
- }
- else if (str.Match('+') || str.Match('-'))
- {
- str.Index--; // Put the character back for the parser
- TimeSpan tempTimeZoneOffset = new TimeSpan(0);
- if (!ParseTimeZoneOffset(ref str, 3, ref tempTimeZoneOffset))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset)
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_RepeatDateTimePattern), 'K');
- return false;
- }
- result.timeZoneOffset = tempTimeZoneOffset;
- result.flags |= ParseFlags.TimeZoneUsed;
- }
- // Otherwise it is unspecified and we consume no characters
- break;
- case ':':
- // We match the separator in time pattern with the character in the time string if both equal to ':' or the date separator is matching the characters in the date string
- // We have to exclude the case when the time separator is more than one character and starts with ':' something like "::" for instance.
- if (((dtfi.TimeSeparator.Length > 1 && dtfi.TimeSeparator[0] == ':') || !str.Match(':')) &&
- !str.Match(dtfi.TimeSeparator))
- {
- // A time separator is expected.
- result.SetBadDateTimeFailure();
- return false;
- }
- break;
- case '/':
- // We match the separator in date pattern with the character in the date string if both equal to '/' or the date separator is matching the characters in the date string
- // We have to exclude the case when the date separator is more than one character and starts with '/' something like "//" for instance.
- if (((dtfi.DateSeparator.Length > 1 && dtfi.DateSeparator[0] == '/') || !str.Match('/')) &&
- !str.Match(dtfi.DateSeparator))
- {
- // A date separator is expected.
- result.SetBadDateTimeFailure();
- return false;
- }
- break;
- case '\"':
- case '\'':
- StringBuilder enquotedString = StringBuilderCache.Acquire();
- // Use ParseQuoteString so that we can handle escape characters within the quoted string.
- if (!TryParseQuoteString(format.Value, format.Index, enquotedString, out tokenLen))
- {
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadQuote), ch);
- StringBuilderCache.Release(enquotedString);
- return false;
- }
- format.Index += tokenLen - 1;
-
- // Some cultures uses space in the quoted string. E.g. Spanish has long date format as:
- // "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space
- // in the quoted string.
- string quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
-
- for (int i = 0; i < quotedStr.Length; i++)
- {
- if (quotedStr[i] == ' ' && parseInfo.fAllowInnerWhite)
- {
- str.SkipWhiteSpaces();
- }
- else if (!str.Match(quotedStr[i]))
- {
- // Can not find the matching quoted string.
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- // The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot
- // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
- // fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released
- // with this issue.
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- if (((result.flags & ParseFlags.Rfc1123Pattern) != 0 && quotedStr == GMTName) ||
- ((result.flags & ParseFlags.UtcSortPattern) != 0 && quotedStr == ZuluName))
- {
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = TimeSpan.Zero;
- }
- }
-
- break;
- case '%':
- // Skip this so we can get to the next pattern character.
- // Used in case like "%d", "%y"
-
- // Make sure the next character is not a '%' again.
- if (format.Index >= format.Value.Length - 1 || format.Value[format.Index + 1] == '%')
- {
- result.SetBadFormatSpecifierFailure(format.Value);
- return false;
- }
- break;
- case '\\':
- // Escape character. For example, "\d".
- // Get the next character in format, and see if we can
- // find a match in str.
- if (format.GetNext())
- {
- if (!str.Match(format.GetChar()))
- {
- // Can not find a match for the escaped character.
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- else
- {
- result.SetBadFormatSpecifierFailure(format.Value);
- return false;
- }
- break;
- case '.':
- if (!str.Match(ch))
- {
- if (format.GetNext())
- {
- // If we encounter the pattern ".F", and the dot is not present, it is an optional
- // second fraction and we can skip this format.
- if (format.Match('F'))
- {
- format.GetRepeatCount();
- break;
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
- break;
- default:
- if (ch == ' ')
- {
- if (parseInfo.fAllowInnerWhite)
- {
- // Skip whitespaces if AllowInnerWhite.
- // Do nothing here.
- }
- else
- {
- if (!str.Match(ch))
- {
- // If the space does not match, and trailing space is allowed, we do
- // one more step to see if the next format character can lead to
- // successful parsing.
- // This is used to deal with special case that a empty string can match
- // a specific pattern.
- // The example here is af-ZA, which has a time format like "hh:mm:ss tt". However,
- // its AM symbol is "" (empty string). If fAllowTrailingWhite is used, and time is in
- // the AM, we will trim the whitespaces at the end, which will lead to a failure
- // when we are trying to match the space before "tt".
- if (parseInfo.fAllowTrailingWhite)
- {
- if (format.GetNext())
- {
- if (ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result))
- {
- return true;
- }
- }
- }
- result.SetBadDateTimeFailure();
- return false;
- }
- // Found a macth.
- }
- }
- else
- {
- if (format.MatchSpecifiedWord(GMTName))
- {
- format.Index += (GMTName.Length - 1);
- // Found GMT string in format. This means the DateTime string
- // is in GMT timezone.
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = TimeSpan.Zero;
- if (!str.Match(GMTName))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- else if (!str.Match(ch))
- {
- // ch is expected.
- result.SetBadDateTimeFailure();
- return false;
- }
- }
- break;
- } // switch
- return true;
- }
-
- //
- // The pos should point to a quote character. This method will
- // get the string enclosed by the quote character.
- //
- internal static bool TryParseQuoteString(ReadOnlySpan<char> format, int pos, StringBuilder result, out int returnValue)
- {
- //
- // NOTE : pos will be the index of the quote character in the 'format' string.
- //
- returnValue = 0;
- int formatLen = format.Length;
- int beginPos = pos;
- char quoteChar = format[pos++]; // Get the character used to quote the following string.
-
- bool foundQuote = false;
- while (pos < formatLen)
- {
- char ch = format[pos++];
- if (ch == quoteChar)
- {
- foundQuote = true;
- break;
- }
- else if (ch == '\\')
- {
- // The following are used to support escaped character.
- // Escaped character is also supported in the quoted string.
- // Therefore, someone can use a format like "'minute:' mm\"" to display:
- // minute: 45"
- // because the second double quote is escaped.
- if (pos < formatLen)
- {
- result.Append(format[pos++]);
- }
- else
- {
- //
- // This means that '\' is at the end of the formatting string.
- //
- return false;
- }
- }
- else
- {
- result.Append(ch);
- }
- }
-
- if (!foundQuote)
- {
- // Here we can't find the matching quote.
- return false;
- }
-
- //
- // Return the character count including the begin/end quote characters and enclosed string.
- //
- returnValue = (pos - beginPos);
- return true;
- }
-
- /*=================================DoStrictParse==================================
- **Action: Do DateTime parsing using the format in formatParam.
- **Returns: The parsed DateTime.
- **Arguments:
- **Exceptions:
- **
- **Notes:
- ** When the following general formats are used, InvariantInfo is used in dtfi:
- ** 'r', 'R', 's'.
- ** When the following general formats are used, the time is assumed to be in Universal time.
- **
- **Limitations:
- ** Only GregorianCalendar is supported for now.
- ** Only support GMT timezone.
- ==============================================================================*/
-
- private static bool DoStrictParse(
- ReadOnlySpan<char> s,
- ReadOnlySpan<char> formatParam,
- DateTimeStyles styles,
- DateTimeFormatInfo dtfi,
- ref DateTimeResult result)
- {
- ParsingInfo parseInfo = default;
- parseInfo.Init();
-
- parseInfo.calendar = dtfi.Calendar;
- parseInfo.fAllowInnerWhite = ((styles & DateTimeStyles.AllowInnerWhite) != 0);
- parseInfo.fAllowTrailingWhite = ((styles & DateTimeStyles.AllowTrailingWhite) != 0);
-
- if (formatParam.Length == 1)
- {
- char formatParamChar = formatParam[0];
-
- // Fast-paths for common and important formats/configurations.
- if (styles == DateTimeStyles.None)
- {
- switch (formatParamChar)
- {
- case 'R':
- case 'r':
- ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
- return ParseFormatR(s, ref parseInfo, ref result);
-
- case 'O':
- case 'o':
- ConfigureFormatOS(ref dtfi, ref parseInfo);
- return ParseFormatO(s, ref result);
- }
- }
-
- if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParamChar == 'U')
- {
- // The 'U' format is not allowed for DateTimeOffset
- result.SetBadFormatSpecifierFailure(formatParam);
- return false;
- }
-
- formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
- }
-
- bool bTimeOnly = false;
- result.calendar = parseInfo.calendar;
-
- if (parseInfo.calendar.ID == CalendarId.HEBREW)
- {
- parseInfo.parseNumberDelegate = m_hebrewNumberParser;
- parseInfo.fCustomNumberParser = true;
- }
-
- // Reset these values to negative one so that we could throw exception
- // if we have parsed every item twice.
- result.Hour = result.Minute = result.Second = -1;
-
- __DTString format = new __DTString(formatParam, dtfi, false);
- __DTString str = new __DTString(s, dtfi, false);
-
- if (parseInfo.fAllowTrailingWhite)
- {
- // Trim trailing spaces if AllowTrailingWhite.
- format.TrimTail();
- format.RemoveTrailingInQuoteSpaces();
- str.TrimTail();
- }
-
- if ((styles & DateTimeStyles.AllowLeadingWhite) != 0)
- {
- format.SkipWhiteSpaces();
- format.RemoveLeadingInQuoteSpaces();
- str.SkipWhiteSpaces();
- }
-
- //
- // Scan every character in format and match the pattern in str.
- //
- while (format.GetNext())
- {
- // We trim inner spaces here, so that we will not eat trailing spaces when
- // AllowTrailingWhite is not used.
- if (parseInfo.fAllowInnerWhite)
- {
- str.SkipWhiteSpaces();
- }
- if (!ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result))
- {
- return false;
- }
- }
-
- if (str.Index < str.Value.Length - 1)
- {
- // There are still remaining character in str.
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if (parseInfo.fUseTwoDigitYear && ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) == 0))
- {
- // A two digit year value is expected. Check if the parsed year value is valid.
- if (result.Year >= 100)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- try
- {
- result.Year = parseInfo.calendar.ToFourDigitYear(result.Year);
- }
- catch (ArgumentOutOfRangeException)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- if (parseInfo.fUseHour12)
- {
- if (parseInfo.timeMark == TM.NotSet)
- {
- // hh is used, but no AM/PM designator is specified.
- // Assume the time is AM.
- // Don't throw exceptions in here becasue it is very confusing for the caller.
- // I always got confused myself when I use "hh:mm:ss" to parse a time string,
- // and ParseExact() throws on me (because I didn't use the 24-hour clock 'HH').
- parseInfo.timeMark = TM.AM;
- }
- if (result.Hour > 12)
- {
- // AM/PM is used, but the value for HH is too big.
- result.SetBadDateTimeFailure();
- return false;
- }
- if (parseInfo.timeMark == TM.AM)
- {
- if (result.Hour == 12)
- {
- result.Hour = 0;
- }
- }
- else
- {
- result.Hour = (result.Hour == 12) ? 12 : result.Hour + 12;
- }
- }
- else
- {
- // Military (24-hour time) mode
- //
- // AM cannot be set with a 24-hour time like 17:15.
- // PM cannot be set with a 24-hour time like 03:15.
- if ((parseInfo.timeMark == TM.AM && result.Hour >= 12)
- || (parseInfo.timeMark == TM.PM && result.Hour < 12))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- // Check if the parsed string only contains hour/minute/second values.
- bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);
- if (!CheckDefaultDateTime(ref result, ref parseInfo.calendar, styles))
- {
- return false;
- }
-
- if (!bTimeOnly && dtfi.HasYearMonthAdjustment)
- {
- if (!dtfi.YearMonthAdjustment(ref result.Year, ref result.Month, (result.flags & ParseFlags.ParsedMonthName) != 0))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- }
- if (!parseInfo.calendar.TryToDateTime(result.Year, result.Month, result.Day,
- result.Hour, result.Minute, result.Second, 0, result.era, out result.parsedDate))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
- if (result.fraction > 0)
- {
- if (!result.parsedDate.TryAddTicks((long)Math.Round(result.fraction * Calendar.TicksPerSecond), out result.parsedDate))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- //
- // We have to check day of week before we adjust to the time zone.
- // It is because the value of day of week may change after adjusting
- // to the time zone.
- //
- if (parseInfo.dayOfWeek != -1)
- {
- //
- // Check if day of week is correct.
- //
- if (parseInfo.dayOfWeek != (int)parseInfo.calendar.GetDayOfWeek(result.parsedDate))
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
- return false;
- }
- }
-
- return DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly);
- }
-
- private static bool ParseFormatR(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
- {
- // Example:
- // Tue, 03 Jan 2017 08:08:05 GMT
-
- // The format is exactly 29 characters.
- if ((uint)source.Length != 29)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Parse the three-letter day of week. Any casing is valid.
- DayOfWeek dayOfWeek;
- {
- uint dow0 = source[0], dow1 = source[1], dow2 = source[2], comma = source[3];
-
- if ((dow0 | dow1 | dow2 | comma) > 0x7F)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma | 0x20202000;
- switch (dowString)
- {
- case 0x73756E2c /* 'sun,' */: dayOfWeek = DayOfWeek.Sunday; break;
- case 0x6d6f6e2c /* 'mon,' */: dayOfWeek = DayOfWeek.Monday; break;
- case 0x7475652c /* 'tue,' */: dayOfWeek = DayOfWeek.Tuesday; break;
- case 0x7765642c /* 'wed,' */: dayOfWeek = DayOfWeek.Wednesday; break;
- case 0x7468752c /* 'thu,' */: dayOfWeek = DayOfWeek.Thursday; break;
- case 0x6672692c /* 'fri,' */: dayOfWeek = DayOfWeek.Friday; break;
- case 0x7361742c /* 'sat,' */: dayOfWeek = DayOfWeek.Saturday; break;
- default:
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- if (source[4] != ' ')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Parse the two digit day.
- int day;
- {
- uint digit1 = (uint)(source[5] - '0'), digit2 = (uint)(source[6] - '0');
-
- if (digit1 > 9 || digit2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- day = (int)(digit1 * 10 + digit2);
- }
-
- if (source[7] != ' ')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Parse the three letter month (followed by a space). Any casing is valid.
- int month;
- {
- uint m0 = source[8], m1 = source[9], m2 = source[10], space = source[11];
-
- if ((m0 | m1 | m2 | space) > 0x7F)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- switch ((m0 << 24) | (m1 << 16) | (m2 << 8) | space | 0x20202000)
- {
- case 0x6a616e20: /* 'jan ' */ month = 1; break;
- case 0x66656220: /* 'feb ' */ month = 2; break;
- case 0x6d617220: /* 'mar ' */ month = 3; break;
- case 0x61707220: /* 'apr ' */ month = 4; break;
- case 0x6d617920: /* 'may ' */ month = 5; break;
- case 0x6a756e20: /* 'jun ' */ month = 6; break;
- case 0x6a756c20: /* 'jul ' */ month = 7; break;
- case 0x61756720: /* 'aug ' */ month = 8; break;
- case 0x73657020: /* 'sep ' */ month = 9; break;
- case 0x6f637420: /* 'oct ' */ month = 10; break;
- case 0x6e6f7620: /* 'nov ' */ month = 11; break;
- case 0x64656320: /* 'dec ' */ month = 12; break;
- default:
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- // Parse the four-digit year.
- int year;
- {
- uint y1 = (uint)(source[12] - '0'), y2 = (uint)(source[13] - '0'), y3 = (uint)(source[14] - '0'), y4 = (uint)(source[15] - '0');
-
- if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- year = (int)(y1 * 1000 + y2 * 100 + y3 * 10 + y4);
- }
-
- if (source[16] != ' ')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Parse the two digit hour.
- int hour;
- {
- uint h1 = (uint)(source[17] - '0'), h2 = (uint)(source[18] - '0');
-
- if (h1 > 9 || h2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- hour = (int)(h1 * 10 + h2);
- }
-
- if (source[19] != ':')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Parse the two-digit minute.
- int minute;
- {
- uint m1 = (uint)(source[20] - '0');
- uint m2 = (uint)(source[21] - '0');
-
- if (m1 > 9 || m2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- minute = (int)(m1 * 10 + m2);
- }
-
- if (source[22] != ':')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Parse the two-digit second.
- int second;
- {
- uint s1 = (uint)(source[23] - '0'), s2 = (uint)(source[24] - '0');
-
- if (s1 > 9 || s2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- second = (int)(s1 * 10 + s2);
- }
-
- // Parse " GMT". It must be upper case.
- if (source[25] != ' ' || source[26] != 'G' || source[27] != 'M' || source[28] != 'T')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- // Validate that the parsed date is valid according to the calendar.
- if (!parseInfo.calendar.TryToDateTime(year, month, day, hour, minute, second, 0, 0, out result.parsedDate))
- {
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
- return false;
- }
-
- // And validate that the parsed day of week matches what the calendar said it should be.
- if (dayOfWeek != result.parsedDate.DayOfWeek)
- {
- result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
- return false;
- }
-
- return true;
- }
-
- private static bool ParseFormatO(ReadOnlySpan<char> source, ref DateTimeResult result)
- {
- // Examples:
- // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
- // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
- // 2017-06-12T05:30:45.7680000-7:00 (special-case of one-digit offset hour)
- // 2017-06-12T05:30:45.7680000-07:00
-
- if ((uint)source.Length < 27 ||
- source[4] != '-' ||
- source[7] != '-' ||
- source[10] != 'T' ||
- source[13] != ':' ||
- source[16] != ':' ||
- source[19] != '.')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int year;
- {
- uint y1 = (uint)(source[0] - '0'), y2 = (uint)(source[1] - '0'), y3 = (uint)(source[2] - '0'), y4 = (uint)(source[3] - '0');
-
- if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- year = (int)(y1 * 1000 + y2 * 100 + y3 * 10 + y4);
- }
-
- int month;
- {
- uint m1 = (uint)(source[5] - '0'), m2 = (uint)(source[6] - '0');
-
- if (m1 > 9 || m2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- month = (int)(m1 * 10 + m2);
- }
-
- int day;
- {
- uint d1 = (uint)(source[8] - '0'), d2 = (uint)(source[9] - '0');
-
- if (d1 > 9 || d2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- day = (int)(d1 * 10 + d2);
- }
-
- int hour;
- {
- uint h1 = (uint)(source[11] - '0'), h2 = (uint)(source[12] - '0');
-
- if (h1 > 9 || h2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- hour = (int)(h1 * 10 + h2);
- }
-
- int minute;
- {
- uint m1 = (uint)(source[14] - '0'), m2 = (uint)(source[15] - '0');
-
- if (m1 > 9 || m2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- minute = (int)(m1 * 10 + m2);
- }
-
- int second;
- {
- uint s1 = (uint)(source[17] - '0'), s2 = (uint)(source[18] - '0');
-
- if (s1 > 9 || s2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- second = (int)(s1 * 10 + s2);
- }
-
- double fraction;
- {
- uint f1 = (uint)(source[20] - '0');
- uint f2 = (uint)(source[21] - '0');
- uint f3 = (uint)(source[22] - '0');
- uint f4 = (uint)(source[23] - '0');
- uint f5 = (uint)(source[24] - '0');
- uint f6 = (uint)(source[25] - '0');
- uint f7 = (uint)(source[26] - '0');
-
- if (f1 > 9 || f2 > 9 || f3 > 9 || f4 > 9 || f5 > 9 || f6 > 9 || f7 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- fraction = (f1 * 1000000 + f2 * 100000 + f3 * 10000 + f4 * 1000 + f5 * 100 + f6 * 10 + f7) / 10000000.0;
- }
-
- if (!DateTime.TryCreate(year, month, day, hour, minute, second, 0, out DateTime dateTime))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if (!dateTime.TryAddTicks((long)Math.Round(fraction * Calendar.TicksPerSecond), out result.parsedDate))
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if ((uint)source.Length > 27)
- {
- char offsetChar = source[27];
- switch (offsetChar)
- {
- case 'Z':
- if (source.Length != 28)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
- result.flags |= ParseFlags.TimeZoneUsed | ParseFlags.TimeZoneUtc;
- break;
-
- case '+':
- case '-':
- int offsetHours, colonIndex;
-
- if ((uint)source.Length == 33)
- {
- uint oh1 = (uint)(source[28] - '0'), oh2 = (uint)(source[29] - '0');
-
- if (oh1 > 9 || oh2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- offsetHours = (int)(oh1 * 10 + oh2);
- colonIndex = 30;
- }
- else if ((uint)source.Length == 32) // special-case allowed for compat: only one offset hour digit
- {
- offsetHours = source[28] - '0';
-
- if ((uint)offsetHours > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- colonIndex = 29;
- }
- else
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- if (source[colonIndex] != ':')
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- int offsetMinutes;
- {
- uint om1 = (uint)(source[colonIndex + 1] - '0'), om2 = (uint)(source[colonIndex + 2] - '0');
-
- if (om1 > 9 || om2 > 9)
- {
- result.SetBadDateTimeFailure();
- return false;
- }
-
- offsetMinutes = (int)(om1 * 10 + om2);
- }
-
- result.flags |= ParseFlags.TimeZoneUsed;
- result.timeZoneOffset = new TimeSpan(offsetHours, offsetMinutes, 0);
- if (offsetChar == '-')
- {
- result.timeZoneOffset = result.timeZoneOffset.Negate();
- }
- break;
-
- default:
- result.SetBadDateTimeFailure();
- return false;
- }
- }
-
- return DetermineTimeZoneAdjustments(ref result, DateTimeStyles.None, bTimeOnly: false);
- }
-
- private static Exception GetDateTimeParseException(ref DateTimeResult result)
- {
- switch (result.failure)
- {
- case ParseFailureKind.ArgumentNull:
- return new ArgumentNullException(result.failureArgumentName, SR.GetResourceString(result.failureMessageID));
- case ParseFailureKind.Format:
- return new FormatException(SR.GetResourceString(result.failureMessageID));
- case ParseFailureKind.FormatWithParameter:
- return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, result.failureMessageFormatArgument));
- case ParseFailureKind.FormatBadDateTimeCalendar:
- return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.originalDateTimeString), result.calendar));
- case ParseFailureKind.FormatWithOriginalDateTime:
- return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.originalDateTimeString)));
- case ParseFailureKind.FormatWithFormatSpecifier:
- return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.failedFormatSpecifier)));
- case ParseFailureKind.FormatWithOriginalDateTimeAndParameter:
- return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.originalDateTimeString), result.failureMessageFormatArgument));
- default:
- Debug.Fail("Unknown DateTimeParseFailure: " + result.failure.ToString());
- return null!;
- }
- }
-
- [Conditional("_LOGGING")]
- private static void LexTraceExit(string message, DS dps)
- {
-#if _LOGGING
- if (!_tracingEnabled)
- return;
- Trace($"Lex return {message}, DS.{dps}");
-#endif // _LOGGING
- }
- [Conditional("_LOGGING")]
- private static void PTSTraceExit(DS dps, bool passed)
- {
-#if _LOGGING
- if (!_tracingEnabled)
- return;
- Trace($"ProcessTerminalState {(passed ? "passed" : "failed")} @ DS.{dps}");
-#endif // _LOGGING
- }
- [Conditional("_LOGGING")]
- private static void TPTraceExit(string message, DS dps)
- {
-#if _LOGGING
- if (!_tracingEnabled)
- return;
- Trace($"TryParse return {message}, DS.{dps}");
-#endif // _LOGGING
- }
- [Conditional("_LOGGING")]
- private static void DTFITrace(DateTimeFormatInfo dtfi)
- {
-#if _LOGGING
- if (!_tracingEnabled)
- return;
-
- Trace("DateTimeFormatInfo Properties");
- Trace($" NativeCalendarName {Hex(dtfi.NativeCalendarName)}");
- Trace($" AMDesignator {Hex(dtfi.AMDesignator)}");
- Trace($" PMDesignator {Hex(dtfi.PMDesignator)}");
- Trace($" TimeSeparator {Hex(dtfi.TimeSeparator)}");
- Trace($" AbbrvDayNames {Hex(dtfi.AbbreviatedDayNames)}");
- Trace($" ShortestDayNames {Hex(dtfi.ShortestDayNames)}");
- Trace($" DayNames {Hex(dtfi.DayNames)}");
- Trace($" AbbrvMonthNames {Hex(dtfi.AbbreviatedMonthNames)}");
- Trace($" MonthNames {Hex(dtfi.MonthNames)}");
- Trace($" AbbrvMonthGenNames {Hex(dtfi.AbbreviatedMonthGenitiveNames)}");
- Trace($" MonthGenNames {Hex(dtfi.MonthGenitiveNames)}");
-#endif // _LOGGING
- }
-#if _LOGGING
- // return a string in the form: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- private static string Hex(string[] strs)
- {
- if (strs == null || strs.Length == 0)
- return string.Empty;
- if (strs.Length == 1)
- return Hex(strs[0]);
-
- int curLineLength = 0;
- const int MaxLineLength = 55;
- const int NewLinePadding = 20;
-
- // invariant: strs.Length >= 2
- StringBuilder buffer = new StringBuilder();
- buffer.Append(Hex(strs[0]));
- curLineLength = buffer.Length;
- string s;
-
- for (int i = 1; i < strs.Length - 1; i++)
- {
- s = Hex(strs[i]);
-
- if (s.Length > MaxLineLength || (curLineLength + s.Length + 2) > MaxLineLength)
- {
- buffer.Append(',');
- buffer.Append(Environment.NewLineConst);
- buffer.Append(' ', NewLinePadding);
- curLineLength = 0;
- }
- else
- {
- buffer.Append(", ");
- curLineLength += 2;
- }
- buffer.Append(s);
- curLineLength += s.Length;
- }
-
- buffer.Append(',');
- s = Hex(strs[strs.Length - 1]);
- if (s.Length > MaxLineLength || (curLineLength + s.Length + 6) > MaxLineLength)
- {
- buffer.Append(Environment.NewLineConst);
- buffer.Append(' ', NewLinePadding);
- }
- else
- {
- buffer.Append(' ');
- }
- buffer.Append(s);
- return buffer.ToString();
- }
- // return a string in the form: "Sun"
- private static string Hex(string str) => Hex((ReadOnlySpan<char>)str);
- private static string Hex(ReadOnlySpan<char> str)
- {
- StringBuilder buffer = new StringBuilder();
- buffer.Append("\"");
- for (int i = 0; i < str.Length; i++)
- {
- if (str[i] <= '\x007f')
- buffer.Append(str[i]);
- else
- buffer.Append("\\u").Append(((int)str[i]).ToString("x4", CultureInfo.InvariantCulture));
- }
- buffer.Append("\"");
- return buffer.ToString();
- }
- // return an unicode escaped string form of char c
- private static string Hex(char c)
- {
- if (c <= '\x007f')
- return c.ToString(CultureInfo.InvariantCulture);
- else
- return "\\u" + ((int)c).ToString("x4", CultureInfo.InvariantCulture);
- }
-
- private static void Trace(string s)
- {
- // Internal.Console.WriteLine(s);
- }
-
- // for testing; do not make this readonly
- private static bool _tracingEnabled = false;
-#endif // _LOGGING
- }
-
- //
- // This is a string parsing helper which wraps a String object.
- // It has a Index property which tracks
- // the current parsing pointer of the string.
- //
- internal ref struct __DTString
- {
- //
- // Value property: stores the real string to be parsed.
- //
- internal ReadOnlySpan<char> Value;
-
- //
- // Index property: points to the character that we are currently parsing.
- //
- internal int Index;
-
- // The length of Value string.
- internal int Length => Value.Length;
-
- // The current character to be looked at.
- internal char m_current;
-
- private readonly CompareInfo m_info;
- // Flag to indicate if we encouter an digit, we should check for token or not.
- // In some cultures, such as mn-MN, it uses "\x0031\x00a0\x0434\x04af\x0433\x044d\x044d\x0440\x00a0\x0441\x0430\x0440" in month names.
- private readonly bool m_checkDigitToken;
-
- internal __DTString(ReadOnlySpan<char> str, DateTimeFormatInfo dtfi, bool checkDigitToken) : this(str, dtfi)
- {
- m_checkDigitToken = checkDigitToken;
- }
-
- internal __DTString(ReadOnlySpan<char> str, DateTimeFormatInfo dtfi)
- {
- Debug.Assert(dtfi != null, "Expected non-null DateTimeFormatInfo");
-
- Index = -1;
- Value = str;
-
- m_current = '\0';
- m_info = dtfi.CompareInfo;
- m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
- }
-
- internal CompareInfo CompareInfo => m_info;
-
- //
- // Advance the Index.
- // Return true if Index is NOT at the end of the string.
- //
- // Typical usage:
- // while (str.GetNext())
- // {
- // char ch = str.GetChar()
- // }
- internal bool GetNext()
- {
- Index++;
- if (Index < Length)
- {
- m_current = Value[Index];
- return true;
- }
- return false;
- }
-
- internal bool AtEnd()
- {
- return Index < Length ? false : true;
- }
-
- internal bool Advance(int count)
- {
- Debug.Assert(Index + count <= Length, "__DTString::Advance: Index + count <= len");
- Index += count;
- if (Index < Length)
- {
- m_current = Value[Index];
- return true;
- }
- return false;
- }
-
- // Used by DateTime.Parse() to get the next token.
- internal void GetRegularToken(out TokenType tokenType, out int tokenValue, DateTimeFormatInfo dtfi)
- {
- tokenValue = 0;
- if (Index >= Length)
- {
- tokenType = TokenType.EndOfString;
- return;
- }
-
- Start:
- if (DateTimeParse.IsDigit(m_current))
- {
- // This is a digit.
- tokenValue = m_current - '0';
- int value;
- int start = Index;
-
- //
- // Collect other digits.
- //
- while (++Index < Length)
- {
- m_current = Value[Index];
- value = m_current - '0';
- if (value >= 0 && value <= 9)
- {
- tokenValue = tokenValue * 10 + value;
- }
- else
- {
- break;
- }
- }
- if (Index - start > DateTimeParse.MaxDateTimeNumberDigits)
- {
- tokenType = TokenType.NumberToken;
- tokenValue = -1;
- }
- else if (Index - start < 3)
- {
- tokenType = TokenType.NumberToken;
- }
- else
- {
- // If there are more than 3 digits, assume that it's a year value.
- tokenType = TokenType.YearNumberToken;
- }
- if (m_checkDigitToken)
- {
- int save = Index;
- char saveCh = m_current;
- // Re-scan using the staring Index to see if this is a token.
- Index = start; // To include the first digit.
- m_current = Value[Index];
- TokenType tempType;
- int tempValue;
- // This DTFI has tokens starting with digits.
- // E.g. mn-MN has month name like "\x0031\x00a0\x0434\x04af\x0433\x044d\x044d\x0440\x00a0\x0441\x0430\x0440"
- if (dtfi.Tokenize(TokenType.RegularTokenMask, out tempType, out tempValue, ref this))
- {
- tokenType = tempType;
- tokenValue = tempValue;
- // This is a token, so the Index has been advanced propertly in DTFI.Tokenizer().
- }
- else
- {
- // Use the number token value.
- // Restore the index.
- Index = save;
- m_current = saveCh;
- }
- }
- }
- else if (char.IsWhiteSpace(m_current))
- {
- // Just skip to the next character.
- while (++Index < Length)
- {
- m_current = Value[Index];
- if (!char.IsWhiteSpace(m_current))
- {
- goto Start;
- }
- }
- // We have reached the end of string.
- tokenType = TokenType.EndOfString;
- }
- else
- {
- dtfi.Tokenize(TokenType.RegularTokenMask, out tokenType, out tokenValue, ref this);
- }
- }
-
- internal TokenType GetSeparatorToken(DateTimeFormatInfo dtfi, out int indexBeforeSeparator, out char charBeforeSeparator)
- {
- indexBeforeSeparator = Index;
- charBeforeSeparator = m_current;
- TokenType tokenType;
- if (!SkipWhiteSpaceCurrent())
- {
- // Reach the end of the string.
- return TokenType.SEP_End;
- }
- if (!DateTimeParse.IsDigit(m_current))
- {
- // Not a digit. Tokenize it.
- bool found = dtfi.Tokenize(TokenType.SeparatorTokenMask, out tokenType, out _, ref this);
- if (!found)
- {
- tokenType = TokenType.SEP_Space;
- }
- }
- else
- {
- // Do nothing here. If we see a number, it will not be a separator. There is no need wasting time trying to find the
- // separator token.
- tokenType = TokenType.SEP_Space;
- }
- return tokenType;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool MatchSpecifiedWord(string target) =>
- Index + target.Length <= Length &&
- m_info.Compare(Value.Slice(Index, target.Length), target, CompareOptions.IgnoreCase) == 0;
-
- private static readonly char[] WhiteSpaceChecks = new char[] { ' ', '\u00A0' };
-
- internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int matchLength)
- {
- int valueRemaining = Value.Length - Index;
- matchLength = target.Length;
-
- if (matchLength > valueRemaining || m_info.Compare(Value.Slice(Index, matchLength), target, CompareOptions.IgnoreCase) != 0)
- {
- // Check word by word
- int targetPosition = 0; // Where we are in the target string
- int thisPosition = Index; // Where we are in this string
- int wsIndex = target.IndexOfAny(WhiteSpaceChecks, targetPosition);
- if (wsIndex == -1)
- {
- return false;
- }
- do
- {
- int segmentLength = wsIndex - targetPosition;
- if (thisPosition >= Value.Length - segmentLength)
- { // Subtraction to prevent overflow.
- return false;
- }
- if (segmentLength == 0)
- {
- // If segmentLength == 0, it means that we have leading space in the target string.
- // In that case, skip the leading spaces in the target and this string.
- matchLength--;
- }
- else
- {
- // Make sure we also have whitespace in the input string
- if (!char.IsWhiteSpace(Value[thisPosition + segmentLength]))
- {
- return false;
- }
- if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
- {
- return false;
- }
- // Advance the input string
- thisPosition = thisPosition + segmentLength + 1;
- }
- // Advance our target string
- targetPosition = wsIndex + 1;
-
- // Skip past multiple whitespace
- while (thisPosition < Value.Length && char.IsWhiteSpace(Value[thisPosition]))
- {
- thisPosition++;
- matchLength++;
- }
- } while ((wsIndex = target.IndexOfAny(WhiteSpaceChecks, targetPosition)) >= 0);
- // now check the last segment;
- if (targetPosition < target.Length)
- {
- int segmentLength = target.Length - targetPosition;
- if (thisPosition > Value.Length - segmentLength)
- {
- return false;
- }
- if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
- {
- return false;
- }
- }
- }
-
- if (checkWordBoundary)
- {
- int nextCharIndex = Index + matchLength;
- if (nextCharIndex < Value.Length)
- {
- if (char.IsLetter(Value[nextCharIndex]))
- {
- return false;
- }
- }
- }
- return true;
- }
-
- //
- // Check to see if the string starting from Index is a prefix of
- // str.
- // If a match is found, true value is returned and Index is updated to the next character to be parsed.
- // Otherwise, Index is unchanged.
- //
- internal bool Match(string str)
- {
- if (++Index >= Length)
- {
- return false;
- }
-
- if (str.Length > (Value.Length - Index))
- {
- return false;
- }
-
- if (m_info.Compare(Value.Slice(Index, str.Length), str, CompareOptions.Ordinal) == 0)
- {
- // Update the Index to the end of the matching string.
- // So the following GetNext()/Match() opeartion will get
- // the next character to be parsed.
- Index += (str.Length - 1);
- return true;
- }
- return false;
- }
-
- internal bool Match(char ch)
- {
- if (++Index >= Length)
- {
- return false;
- }
- if (Value[Index] == ch)
- {
- m_current = ch;
- return true;
- }
- Index--;
- return false;
- }
-
- //
- // Actions: From the current position, try matching the longest word in the specified string array.
- // E.g. words[] = {"AB", "ABC", "ABCD"}, if the current position points to a substring like "ABC DEF",
- // MatchLongestWords(words, ref MaxMatchStrLen) will return 1 (the index), and maxMatchLen will be 3.
- // Returns:
- // The index that contains the longest word to match
- // Arguments:
- // words The string array that contains words to search.
- // maxMatchStrLen [in/out] the initialized maximum length. This parameter can be used to
- // find the longest match in two string arrays.
- //
- internal int MatchLongestWords(string[] words, ref int maxMatchStrLen)
- {
- int result = -1;
- for (int i = 0; i < words.Length; i++)
- {
- string word = words[i];
- int matchLength = word.Length;
- if (MatchSpecifiedWords(word, false, ref matchLength))
- {
- if (matchLength > maxMatchStrLen)
- {
- maxMatchStrLen = matchLength;
- result = i;
- }
- }
- }
-
- return result;
- }
-
- //
- // Get the number of repeat character after the current character.
- // For a string "hh:mm:ss" at Index of 3. GetRepeatCount() = 2, and Index
- // will point to the second ':'.
- //
- internal int GetRepeatCount()
- {
- char repeatChar = Value[Index];
- int pos = Index + 1;
- while ((pos < Length) && (Value[pos] == repeatChar))
- {
- pos++;
- }
- int repeatCount = (pos - Index);
- // Update the Index to the end of the repeated characters.
- // So the following GetNext() opeartion will get
- // the next character to be parsed.
- Index = pos - 1;
- return repeatCount;
- }
-
- // Return false when end of string is encountered or a non-digit character is found.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool GetNextDigit() =>
- ++Index < Length &&
- DateTimeParse.IsDigit(Value[Index]);
-
- //
- // Get the current character.
- //
- internal char GetChar()
- {
- Debug.Assert(Index >= 0 && Index < Length, "Index >= 0 && Index < len");
- return Value[Index];
- }
-
- //
- // Convert the current character to a digit, and return it.
- //
- internal int GetDigit()
- {
- Debug.Assert(Index >= 0 && Index < Length, "Index >= 0 && Index < len");
- Debug.Assert(DateTimeParse.IsDigit(Value[Index]), "IsDigit(Value[Index])");
- return Value[Index] - '0';
- }
-
- //
- // Eat White Space ahead of the current position
- //
- // Return false if end of string is encountered.
- //
- internal void SkipWhiteSpaces()
- {
- // Look ahead to see if the next character
- // is a whitespace.
- while (Index + 1 < Length)
- {
- char ch = Value[Index + 1];
- if (!char.IsWhiteSpace(ch))
- {
- return;
- }
- Index++;
- }
- return;
- }
-
- //
- // Skip white spaces from the current position
- //
- // Return false if end of string is encountered.
- //
- internal bool SkipWhiteSpaceCurrent()
- {
- if (Index >= Length)
- {
- return false;
- }
-
- if (!char.IsWhiteSpace(m_current))
- {
- return true;
- }
-
- while (++Index < Length)
- {
- m_current = Value[Index];
- if (!char.IsWhiteSpace(m_current))
- {
- return true;
- }
- // Nothing here.
- }
- return false;
- }
-
- internal void TrimTail()
- {
- int i = Length - 1;
- while (i >= 0 && char.IsWhiteSpace(Value[i]))
- {
- i--;
- }
- Value = Value.Slice(0, i + 1);
- }
-
- // Trim the trailing spaces within a quoted string.
- // Call this after TrimTail() is done.
- internal void RemoveTrailingInQuoteSpaces()
- {
- int i = Length - 1;
- if (i <= 1)
- {
- return;
- }
- char ch = Value[i];
- // Check if the last character is a quote.
- if (ch == '\'' || ch == '\"')
- {
- if (char.IsWhiteSpace(Value[i - 1]))
- {
- i--;
- while (i >= 1 && char.IsWhiteSpace(Value[i - 1]))
- {
- i--;
- }
- Span<char> result = new char[i + 1];
- result[i] = ch;
- Value.Slice(0, i).CopyTo(result);
- Value = result;
- }
- }
- }
-
- // Trim the leading spaces within a quoted string.
- // Call this after the leading spaces before quoted string are trimmed.
- internal void RemoveLeadingInQuoteSpaces()
- {
- if (Length <= 2)
- {
- return;
- }
- int i = 0;
- char ch = Value[i];
- // Check if the last character is a quote.
- if (ch == '\'' || ch == '\"')
- {
- while ((i + 1) < Length && char.IsWhiteSpace(Value[i + 1]))
- {
- i++;
- }
- if (i != 0)
- {
- Span<char> result = new char[Value.Length - i];
- result[0] = ch;
- Value.Slice(i + 1).CopyTo(result.Slice(1));
- Value = result;
- }
- }
- }
-
- internal DTSubString GetSubString()
- {
- DTSubString sub = default;
- sub.index = Index;
- sub.s = Value;
- while (Index + sub.length < Length)
- {
- DTSubStringType currentType;
- char ch = Value[Index + sub.length];
- if (ch >= '0' && ch <= '9')
- {
- currentType = DTSubStringType.Number;
- }
- else
- {
- currentType = DTSubStringType.Other;
- }
-
- if (sub.length == 0)
- {
- sub.type = currentType;
- }
- else
- {
- if (sub.type != currentType)
- {
- break;
- }
- }
- sub.length++;
- if (currentType == DTSubStringType.Number)
- {
- // Incorporate the number into the value
- // Limit the digits to prevent overflow
- if (sub.length > DateTimeParse.MaxDateTimeNumberDigits)
- {
- sub.type = DTSubStringType.Invalid;
- return sub;
- }
- int number = ch - '0';
- Debug.Assert(number >= 0 && number <= 9, "number >= 0 && number <= 9");
- sub.value = sub.value * 10 + number;
- }
- else
- {
- // For non numbers, just return this length 1 token. This should be expanded
- // to more types of thing if this parsing approach is used for things other
- // than numbers and single characters
- break;
- }
- }
- if (sub.length == 0)
- {
- sub.type = DTSubStringType.End;
- return sub;
- }
-
- return sub;
- }
-
- internal void ConsumeSubString(DTSubString sub)
- {
- Debug.Assert(sub.index == Index, "sub.index == Index");
- Debug.Assert(sub.index + sub.length <= Length, "sub.index + sub.length <= len");
- Index = sub.index + sub.length;
- if (Index < Length)
- {
- m_current = Value[Index];
- }
- }
- }
-
- internal enum DTSubStringType
- {
- Unknown = 0,
- Invalid = 1,
- Number = 2,
- End = 3,
- Other = 4,
- }
-
- internal ref struct DTSubString
- {
- internal ReadOnlySpan<char> s;
- internal int index;
- internal int length;
- internal DTSubStringType type;
- internal int value;
-
- internal char this[int relativeIndex] => s[index + relativeIndex];
- }
-
- //
- // The buffer to store the parsing token.
- //
- internal
- struct DateTimeToken
- {
- internal DateTimeParse.DTT dtt; // Store the token
- internal TokenType suffix; // Store the CJK Year/Month/Day suffix (if any)
- internal int num; // Store the number that we are parsing (if any)
- }
-
- //
- // The buffer to store temporary parsing information.
- //
- internal unsafe struct DateTimeRawInfo
- {
- private int* num;
- internal int numCount;
- internal int month;
- internal int year;
- internal int dayOfWeek;
- internal int era;
- internal DateTimeParse.TM timeMark;
- internal double fraction;
- internal bool hasSameDateAndTimeSeparators;
-
- internal void Init(int* numberBuffer)
- {
- month = -1;
- year = -1;
- dayOfWeek = -1;
- era = -1;
- timeMark = DateTimeParse.TM.NotSet;
- fraction = -1;
- num = numberBuffer;
- }
-
- internal void AddNumber(int value)
- {
- num[numCount++] = value;
- }
-
- internal int GetNumber(int index)
- {
- return num[index];
- }
- }
-
- internal enum ParseFailureKind
- {
- None = 0,
- ArgumentNull = 1,
- Format = 2,
- FormatWithParameter = 3,
- FormatWithOriginalDateTime = 4,
- FormatWithFormatSpecifier = 5,
- FormatWithOriginalDateTimeAndParameter = 6,
- FormatBadDateTimeCalendar = 7, // FormatException when ArgumentOutOfRange is thrown by a Calendar.TryToDateTime().
- }
-
- [Flags]
- internal enum ParseFlags
- {
- HaveYear = 0x00000001,
- HaveMonth = 0x00000002,
- HaveDay = 0x00000004,
- HaveHour = 0x00000008,
- HaveMinute = 0x00000010,
- HaveSecond = 0x00000020,
- HaveTime = 0x00000040,
- HaveDate = 0x00000080,
- TimeZoneUsed = 0x00000100,
- TimeZoneUtc = 0x00000200,
- ParsedMonthName = 0x00000400,
- CaptureOffset = 0x00000800,
- YearDefault = 0x00001000,
- Rfc1123Pattern = 0x00002000,
- UtcSortPattern = 0x00004000,
- }
-
- //
- // This will store the result of the parsing. And it will be eventually
- // used to construct a DateTime instance.
- //
- internal ref struct DateTimeResult
- {
- internal int Year;
- internal int Month;
- internal int Day;
- //
- // Set time default to 00:00:00.
- //
- internal int Hour;
- internal int Minute;
- internal int Second;
- internal double fraction;
-
- internal int era;
-
- internal ParseFlags flags;
-
- internal TimeSpan timeZoneOffset;
-
- internal Calendar calendar;
-
- internal DateTime parsedDate;
-
- internal ParseFailureKind failure;
- internal string failureMessageID;
- internal object? failureMessageFormatArgument;
- internal string failureArgumentName;
- internal ReadOnlySpan<char> originalDateTimeString;
- internal ReadOnlySpan<char> failedFormatSpecifier;
-
- internal void Init(ReadOnlySpan<char> originalDateTimeString)
- {
- this.originalDateTimeString = originalDateTimeString;
- Year = -1;
- Month = -1;
- Day = -1;
- fraction = -1;
- era = -1;
- }
-
- internal void SetDate(int year, int month, int day)
- {
- Year = year;
- Month = month;
- Day = day;
- }
-
- internal void SetBadFormatSpecifierFailure()
- {
- SetBadFormatSpecifierFailure(ReadOnlySpan<char>.Empty);
- }
-
- internal void SetBadFormatSpecifierFailure(ReadOnlySpan<char> failedFormatSpecifier)
- {
- this.failure = ParseFailureKind.FormatWithFormatSpecifier;
- this.failureMessageID = nameof(SR.Format_BadFormatSpecifier);
- this.failedFormatSpecifier = failedFormatSpecifier;
- }
-
- internal void SetBadDateTimeFailure()
- {
- this.failure = ParseFailureKind.FormatWithOriginalDateTime;
- this.failureMessageID = nameof(SR.Format_BadDateTime);
- this.failureMessageFormatArgument = null;
- }
-
- internal void SetFailure(ParseFailureKind failure, string failureMessageID)
- {
- this.failure = failure;
- this.failureMessageID = failureMessageID;
- this.failureMessageFormatArgument = null;
- }
-
- internal void SetFailure(ParseFailureKind failure, string failureMessageID, object? failureMessageFormatArgument)
- {
- this.failure = failure;
- this.failureMessageID = failureMessageID;
- this.failureMessageFormatArgument = failureMessageFormatArgument;
- }
-
- internal void SetFailure(ParseFailureKind failure, string failureMessageID, object? failureMessageFormatArgument, string failureArgumentName)
- {
- this.failure = failure;
- this.failureMessageID = failureMessageID;
- this.failureMessageFormatArgument = failureMessageFormatArgument;
- this.failureArgumentName = failureArgumentName;
- }
- }
-
- // This is the helper data structure used in ParseExact().
- internal struct ParsingInfo
- {
- internal Calendar calendar;
- internal int dayOfWeek;
- internal DateTimeParse.TM timeMark;
-
- internal bool fUseHour12;
- internal bool fUseTwoDigitYear;
- internal bool fAllowInnerWhite;
- internal bool fAllowTrailingWhite;
- internal bool fCustomNumberParser;
- internal DateTimeParse.MatchNumberDelegate parseNumberDelegate;
-
- internal void Init()
- {
- dayOfWeek = -1;
- timeMark = DateTimeParse.TM.NotSet;
- }
- }
-
- //
- // The type of token that will be returned by DateTimeFormatInfo.Tokenize().
- //
- internal enum TokenType
- {
- // The valid token should start from 1.
-
- // Regular tokens. The range is from 0x00 ~ 0xff.
- NumberToken = 1, // The number. E.g. "12"
- YearNumberToken = 2, // The number which is considered as year number, which has 3 or more digits. E.g. "2003"
- Am = 3, // AM timemark. E.g. "AM"
- Pm = 4, // PM timemark. E.g. "PM"
- MonthToken = 5, // A word (or words) that represents a month name. E.g. "March"
- EndOfString = 6, // End of string
- DayOfWeekToken = 7, // A word (or words) that represents a day of week name. E.g. "Monday" or "Mon"
- TimeZoneToken = 8, // A word that represents a timezone name. E.g. "GMT"
- EraToken = 9, // A word that represents a era name. E.g. "A.D."
- DateWordToken = 10, // A word that can appear in a DateTime string, but serves no parsing semantics. E.g. "de" in Spanish culture.
- UnknownToken = 11, // An unknown word, which signals an error in parsing.
- HebrewNumber = 12, // A number that is composed of Hebrew text. Hebrew calendar uses Hebrew digits for year values, month values, and day values.
- JapaneseEraToken = 13, // Era name for JapaneseCalendar
- TEraToken = 14, // Era name for TaiwanCalendar
- IgnorableSymbol = 15, // A separator like "," that is equivalent to whitespace
-
- // Separator tokens.
- SEP_Unk = 0x100, // Unknown separator.
- SEP_End = 0x200, // The end of the parsing string.
- SEP_Space = 0x300, // Whitespace (including comma).
- SEP_Am = 0x400, // AM timemark. E.g. "AM"
- SEP_Pm = 0x500, // PM timemark. E.g. "PM"
- SEP_Date = 0x600, // date separator. E.g. "/"
- SEP_Time = 0x700, // time separator. E.g. ":"
- SEP_YearSuff = 0x800, // Chinese/Japanese/Korean year suffix.
- SEP_MonthSuff = 0x900, // Chinese/Japanese/Korean month suffix.
- SEP_DaySuff = 0xa00, // Chinese/Japanese/Korean day suffix.
- SEP_HourSuff = 0xb00, // Chinese/Japanese/Korean hour suffix.
- SEP_MinuteSuff = 0xc00, // Chinese/Japanese/Korean minute suffix.
- SEP_SecondSuff = 0xd00, // Chinese/Japanese/Korean second suffix.
- SEP_LocalTimeMark = 0xe00, // 'T', used in ISO 8601 format.
- SEP_DateOrOffset = 0xf00, // '-' which could be a date separator or start of a time zone offset
-
- RegularTokenMask = 0x00ff,
- SeparatorTokenMask = 0xff00,
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeStyles.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeStyles.cs
deleted file mode 100644
index 94a1eeb71f4..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DateTimeStyles.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-**
-**
-** Purpose: Contains valid formats for DateTime recognized by
-** the DateTime class' parsing code.
-**
-**
-===========================================================*/
-
-namespace System.Globalization
-{
- [Flags]
- public enum DateTimeStyles
- {
- // Bit flag indicating that leading whitespace is allowed. Character values
- // 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, and 0x0020 are considered to be
- // whitespace.
-
-
- None = 0x00000000,
-
- AllowLeadingWhite = 0x00000001,
-
- AllowTrailingWhite = 0x00000002, // Bitflag indicating trailing whitespace is allowed.
-
- AllowInnerWhite = 0x00000004,
-
- AllowWhiteSpaces = AllowLeadingWhite | AllowInnerWhite | AllowTrailingWhite,
- // When parsing a date/time string, if all year/month/day are missing, set the default date
- // to 0001/1/1, instead of the current year/month/day.
-
- NoCurrentDateDefault = 0x00000008,
- // When parsing a date/time string, if a timezone specifier ("GMT","Z","+xxxx", "-xxxx" exists), we will
- // adjust the parsed time based to GMT.
-
- AdjustToUniversal = 0x00000010,
-
- AssumeLocal = 0x00000020,
-
- AssumeUniversal = 0x00000040,
- // Attempt to preserve whether the input is unspecified, local or UTC
- RoundtripKind = 0x00000080,
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
deleted file mode 100644
index 72a572c97de..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- // This class represents a starting/ending time for a period of daylight saving time.
- public class DaylightTime
- {
- private readonly DateTime _start;
- private readonly DateTime _end;
- private readonly TimeSpan _delta;
-
- public DaylightTime(DateTime start, DateTime end, TimeSpan delta)
- {
- _start = start;
- _end = end;
- _delta = delta;
- }
-
- // The start date of a daylight saving period.
- public DateTime Start => _start;
-
- // The end date of a daylight saving period.
- public DateTime End => _end;
-
- // Delta to stardard offset in ticks.
- public TimeSpan Delta => _delta;
- }
-
- // Value type version of DaylightTime
- internal readonly struct DaylightTimeStruct
- {
- public DaylightTimeStruct(DateTime start, DateTime end, TimeSpan delta)
- {
- Start = start;
- End = end;
- Delta = delta;
- }
-
- public readonly DateTime Start;
- public readonly DateTime End;
- public readonly TimeSpan Delta;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/DigitShapes.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/DigitShapes.cs
deleted file mode 100644
index 27ff391ca72..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/DigitShapes.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public enum DigitShapes : int
- {
- Context = 0x0000, // The shape depends on the previous text in the same output.
- None = 0x0001, // Gives full Unicode compatibility.
- NativeNational = 0x0002 // National shapes
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
deleted file mode 100644
index 113fec1a7d6..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
+++ /dev/null
@@ -1,692 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public abstract class EastAsianLunisolarCalendar : Calendar
- {
- private const int LeapMonth = 0;
- private const int Jan1Month = 1;
- private const int Jan1Date = 2;
- 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 };
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunisolarCalendar;
-
- /// <summary>
- /// Return the year number in the 60-year cycle.
- /// </summary>
- public virtual int GetSexagenaryYear(DateTime time)
- {
- CheckTicksRange(time.Ticks);
-
- TimeToLunar(time, out int year, out _, out _);
- return ((year - 4) % 60) + 1;
- }
-
- /// <summary>
- /// Return the celestial year from the 60-year cycle.
- /// The returned value is from 1 ~ 10.
- /// </summary>
- public int GetCelestialStem(int sexagenaryYear)
- {
- if (sexagenaryYear < 1 || sexagenaryYear > 60)
- {
- throw new ArgumentOutOfRangeException(
- nameof(sexagenaryYear),
- sexagenaryYear,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, 60));
- }
-
- return ((sexagenaryYear - 1) % 10) + 1;
- }
-
- /// <summary>
- /// Return the Terrestial Branch from the 60-year cycle.
- /// The returned value is from 1 ~ 12.
- /// </summary>
- public int GetTerrestrialBranch(int sexagenaryYear)
- {
- if (sexagenaryYear < 1 || sexagenaryYear > 60)
- {
- throw new ArgumentOutOfRangeException(
- nameof(sexagenaryYear),
- sexagenaryYear,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, 60));
- }
-
- return ((sexagenaryYear - 1) % 12) + 1;
- }
-
- internal abstract int GetYearInfo(int LunarYear, int Index);
- internal abstract int GetYear(int year, DateTime time);
- internal abstract int GetGregorianYear(int year, int era);
-
- internal abstract int MinCalendarYear { get; }
- internal abstract int MaxCalendarYear { get; }
- internal abstract EraInfo[]? CalEraInfo { get; }
- internal abstract DateTime MinDate { get; }
- internal abstract DateTime MaxDate { get; }
-
- internal const int MaxCalendarMonth = 13;
- internal const int MaxCalendarDay = 30;
-
- internal int MinEraCalendarYear(int era)
- {
- EraInfo[]? eraInfo = CalEraInfo;
- if (eraInfo == null)
- {
- return MinCalendarYear;
- }
-
- if (era == Calendar.CurrentEra)
- {
- era = CurrentEraValue;
- }
-
- // Era has to be in the supported range otherwise we will throw exception in CheckEraRange()
- if (era == GetEra(MinDate))
- {
- return GetYear(MinCalendarYear, MinDate);
- }
-
- for (int i = 0; i < eraInfo.Length; i++)
- {
- if (era == eraInfo[i].era)
- {
- return eraInfo[i].minEraYear;
- }
- }
-
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- internal int MaxEraCalendarYear(int era)
- {
- EraInfo[]? eraInfo = CalEraInfo;
- if (eraInfo == null)
- {
- return MaxCalendarYear;
- }
-
- if (era == Calendar.CurrentEra)
- {
- era = CurrentEraValue;
- }
-
- // Era has to be in the supported range otherwise we will throw exception in CheckEraRange()
- if (era == GetEra(MaxDate))
- {
- return GetYear(MaxCalendarYear, MaxDate);
- }
-
- for (int i = 0; i < eraInfo.Length; i++)
- {
- if (era == eraInfo[i].era)
- {
- return eraInfo[i].maxEraYear;
- }
- }
-
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- internal EastAsianLunisolarCalendar()
- {
- }
-
- internal void CheckTicksRange(long ticks)
- {
- if (ticks < MinSupportedDateTime.Ticks || ticks > MaxSupportedDateTime.Ticks)
- {
- throw new ArgumentOutOfRangeException(
- "time",
- ticks,
- SR.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange,
- MinSupportedDateTime, MaxSupportedDateTime));
- }
- }
-
- internal void CheckEraRange(int era)
- {
- if (era == Calendar.CurrentEra)
- {
- era = CurrentEraValue;
- }
-
- if (era < GetEra(MinDate) || era > GetEra(MaxDate))
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- }
-
- internal int CheckYearRange(int year, int era)
- {
- CheckEraRange(era);
- year = GetGregorianYear(year, era);
-
- if (year < MinCalendarYear || year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, MinEraCalendarYear(era), MaxEraCalendarYear(era)));
- }
- return year;
- }
-
- internal int CheckYearMonthRange(int year, int month, int era)
- {
- year = CheckYearRange(year, era);
-
- if (month == 13)
- {
- // Reject if there is no leap month this year
- if (GetYearInfo(year, LeapMonth) == 0)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
- }
-
- if (month < 1 || month > 13)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
-
- return year;
- }
-
- internal int InternalGetDaysInMonth(int year, int month)
- {
- int mask = 0x8000;
-
- // convert the lunar day into a lunar month/date
- mask >>= (month - 1);
- if ((GetYearInfo(year, nDaysPerMonth) & mask) == 0)
- {
- return 29;
- }
-
- return 30;
- }
-
- /// <summary>
- /// Returns the number of days in the month given by the year and
- /// month arguments.
- /// </summary>
- public override int GetDaysInMonth(int year, int month, int era)
- {
- year = CheckYearMonthRange(year, month, era);
- return InternalGetDaysInMonth(year, month);
- }
-
- private static bool GregorianIsLeapYear(int y)
- {
- if ((y % 4) != 0)
- {
- return false;
- }
- if ((y % 100) != 0)
- {
- return true;
- }
-
- return (y % 400) == 0;
- }
-
- /// <summary>
- /// Returns the date and time converted to a DateTime value.
- /// Throws an exception if the n-tuple is invalid.
- /// </summary>
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- year = CheckYearMonthRange(year, month, era);
- int daysInMonth = InternalGetDaysInMonth(year, month);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
-
- if (!LunarToGregorian(year, month, day, out int gy, out int gm, out int gd))
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- return new DateTime(gy, gm, gd, hour, minute, second, millisecond);
- }
-
- /// <summary>
- /// Calculates lunar calendar info for the given gregorian year, month, date.
- /// The input date should be validated before calling this method.
- /// </summary>
- private void GregorianToLunar(int solarYear, int solarMonth, int solarDate, out int lunarYear, out int lunarMonth, out int lunarDate)
- {
- bool isLeapYear = GregorianIsLeapYear(solarYear);
- int jan1Month;
- int jan1Date;
-
- // Calculate the day number in the solar year.
- int solarDay = isLeapYear ? s_daysToMonth366[solarMonth - 1] : s_daysToMonth365[solarMonth - 1];
- solarDay += solarDate;
-
- // Calculate the day number in the lunar year.
- int lunarDay = solarDay;
- lunarYear = solarYear;
- if (lunarYear == (MaxCalendarYear + 1))
- {
- lunarYear--;
- lunarDay += (GregorianIsLeapYear(lunarYear) ? 366 : 365);
- jan1Month = GetYearInfo(lunarYear, Jan1Month);
- jan1Date = GetYearInfo(lunarYear, Jan1Date);
- }
- else
- {
- jan1Month = GetYearInfo(lunarYear, Jan1Month);
- jan1Date = GetYearInfo(lunarYear, Jan1Date);
-
- // check if this solar date is actually part of the previous
- // lunar year
- if ((solarMonth < jan1Month) ||
- (solarMonth == jan1Month && solarDate < jan1Date))
- {
- // the corresponding lunar day is actually part of the previous
- // lunar year
- lunarYear--;
-
- // add a solar year to the lunar day #
- lunarDay += (GregorianIsLeapYear(lunarYear) ? 366 : 365);
-
- // update the new start of year
- jan1Month = GetYearInfo(lunarYear, Jan1Month);
- jan1Date = GetYearInfo(lunarYear, Jan1Date);
- }
- }
-
- // convert solar day into lunar day.
- // subtract off the beginning part of the solar year which is not
- // 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 -= (jan1Date - 1);
-
- // convert the lunar day into a lunar month/date
- int mask = 0x8000;
- int yearInfo = GetYearInfo(lunarYear, nDaysPerMonth);
- int days = ((yearInfo & mask) != 0) ? 30 : 29;
- lunarMonth = 1;
- while (lunarDay > days)
- {
- lunarDay -= days;
- lunarMonth++;
- mask >>= 1;
- days = ((yearInfo & mask) != 0) ? 30 : 29;
- }
- lunarDate = lunarDay;
- }
-
- /// <summary>
- /// Convert from Lunar to Gregorian
- /// </summary>
- /// <remarks>
- /// Highly inefficient, but it works based on the forward conversion
- /// </remarks>
- private bool LunarToGregorian(int lunarYear, int lunarMonth, int lunarDate, out int solarYear, out int solarMonth, out int solarDay)
- {
- if (lunarDate < 1 || lunarDate > 30)
- {
- solarYear = 0;
- solarMonth = 0;
- solarDay = 0;
- return false;
- }
-
- int numLunarDays = lunarDate - 1;
-
- // Add previous months days to form the total num of days from the first of the month.
- for (int i = 1; i < lunarMonth; i++)
- {
- numLunarDays += InternalGetDaysInMonth(lunarYear, i);
- }
-
- // Get Gregorian First of year
- int jan1Month = GetYearInfo(lunarYear, Jan1Month);
- int jan1Date = GetYearInfo(lunarYear, Jan1Date);
-
- // calc the solar day of year of 1 Lunar day
- bool isLeapYear = GregorianIsLeapYear(lunarYear);
- int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365;
-
- solarDay = jan1Date;
-
- if (jan1Month > 1)
- {
- solarDay += days[jan1Month - 1];
- }
-
- // Add the actual lunar day to get the solar day we want
- solarDay += numLunarDays;
-
- if (solarDay > (365 + (isLeapYear ? 1 : 0)))
- {
- solarYear = lunarYear + 1;
- solarDay -= (365 + (isLeapYear ? 1 : 0));
- }
- else
- {
- solarYear = lunarYear;
- }
-
- for (solarMonth = 1; solarMonth < 12; solarMonth++)
- {
- if (days[solarMonth] >= solarDay)
- {
- break;
- }
- }
-
- solarDay -= days[solarMonth - 1];
- return true;
- }
-
- private DateTime LunarToTime(DateTime time, int year, int month, int day)
- {
- LunarToGregorian(year, month, day, out int gy, out int gm, out int gd);
- return GregorianCalendar.GetDefaultInstance().ToDateTime(gy, gm, gd, time.Hour, time.Minute, time.Second, time.Millisecond);
- }
-
- private void TimeToLunar(DateTime time, out int year, out int month, out int day)
- {
- Calendar gregorianCalendar = GregorianCalendar.GetDefaultInstance();
- int gy = gregorianCalendar.GetYear(time);
- int gm = gregorianCalendar.GetMonth(time);
- int gd = gregorianCalendar.GetDayOfMonth(time);
-
- GregorianToLunar(gy, gm, gd, out year, out month, out day);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding the given number of
- /// months to the specified DateTime. The result is computed by incrementing
- /// (or decrementing) the year and month parts of the specified DateTime by
- /// value months, and, if required, adjusting the day part of the
- /// resulting date downwards to the last day of the resulting month in the
- /// resulting year. The time-of-day part of the result is the same as the
- /// time-of-day part of the specified DateTime.
- /// </summary>
- public override DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- months,
- SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
- }
-
- CheckTicksRange(time.Ticks);
- TimeToLunar(time, out int y, out int m, out int d);
-
- int i = m + months;
- if (i > 0)
- {
- int monthsInYear = InternalIsLeapYear(y) ? 13 : 12;
-
- while (i - monthsInYear > 0)
- {
- i -= monthsInYear;
- y++;
- monthsInYear = InternalIsLeapYear(y) ? 13 : 12;
- }
- m = i;
- }
- else
- {
- int monthsInYear;
- while (i <= 0)
- {
- monthsInYear = InternalIsLeapYear(y - 1) ? 13 : 12;
- i += monthsInYear;
- y--;
- }
- m = i;
- }
-
- int days = InternalGetDaysInMonth(y, m);
- if (d > days)
- {
- d = days;
- }
- DateTime dt = LunarToTime(time, y, m, d);
-
- CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return dt;
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- CheckTicksRange(time.Ticks);
- TimeToLunar(time, out int y, out int m, out int d);
-
- y += years;
-
- if (m == 13 && !InternalIsLeapYear(y))
- {
- m = 12;
- d = InternalGetDaysInMonth(y, m);
- }
- int daysInMonths = InternalGetDaysInMonth(y, m);
- if (d > daysInMonths)
- {
- d = daysInMonths;
- }
-
- DateTime dt = LunarToTime(time, y, m, d);
- CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return dt;
- }
-
- /// <summary>
- /// Returns the day-of-year part of the specified DateTime. The returned value
- /// is an integer between 1 and [354|355 |383|384].
- /// </summary>
- public override int GetDayOfYear(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- TimeToLunar(time, out int y, out int m, out int d);
-
- for (int i = 1; i < m; i++)
- {
- d += InternalGetDaysInMonth(y, i);
- }
- return d;
- }
-
- /// <summary>
- /// Returns the day-of-month part of the specified DateTime. The returned
- /// value is an integer between 1 and 29 or 30.
- /// </summary>
- public override int GetDayOfMonth(DateTime time)
- {
- CheckTicksRange(time.Ticks);
-
- TimeToLunar(time, out _, out _, out int d);
-
- return d;
- }
-
- /// <summary>
- /// Returns the number of days in the year given by the year argument for the current era.
- /// </summary>
- public override int GetDaysInYear(int year, int era)
- {
- year = CheckYearRange(year, era);
-
- int days = 0;
- int monthsInYear = InternalIsLeapYear(year) ? 13 : 12;
-
- while (monthsInYear != 0)
- {
- days += InternalGetDaysInMonth(year, monthsInYear--);
- }
-
- return days;
- }
-
- /// <summary>
- /// Returns the month part of the specified DateTime.
- /// The returned value is an integer between 1 and 13.
- /// </summary>
- public override int GetMonth(DateTime time)
- {
- CheckTicksRange(time.Ticks);
-
- TimeToLunar(time, out _, out int m, out _);
-
- return m;
- }
-
- /// <summary>
- /// Returns the year part of the specified DateTime.
- /// The returned value is an integer between 1 and MaxCalendarYear.
- /// </summary>
- public override int GetYear(DateTime time)
- {
- CheckTicksRange(time.Ticks);
-
- TimeToLunar(time, out int y, out _, out _);
-
- return GetYear(y, time);
- }
-
- /// <summary>
- /// Returns the day-of-week part of the specified DateTime. The returned value
- /// is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
- /// Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
- /// Thursday, 5 indicates Friday, and 6 indicates Saturday.
- /// </summary>
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return (DayOfWeek)((int)(time.Ticks / Calendar.TicksPerDay + 1) % 7);
- }
-
- /// <summary>
- /// Returns the number of months in the specified year and era.
- /// </summary>
- public override int GetMonthsInYear(int year, int era)
- {
- year = CheckYearRange(year, era);
- return InternalIsLeapYear(year) ? 13 : 12;
- }
-
- /// <summary>
- /// Checks whether a given day in the specified era is a leap day.
- /// This method returns true if the date is a leap day, or false if not.
- /// </summary>
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- year = CheckYearMonthRange(year, month, era);
- int daysInMonth = InternalGetDaysInMonth(year, month);
-
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
-
- int m = GetYearInfo(year, LeapMonth);
- return (m != 0) && (month == (m + 1));
- }
-
- /// <summary>
- /// Checks whether a given month in the specified era is a leap month.
- /// This method returns true if month is a leap month, or false if not.
- /// </summary>
- public override bool IsLeapMonth(int year, int month, int era)
- {
- year = CheckYearMonthRange(year, month, era);
- int m = GetYearInfo(year, LeapMonth);
- return (m != 0) && (month == (m + 1));
- }
-
- /// <summary>
- /// Returns the leap month in a calendar year of the specified era. This method returns 0
- /// if this year is not a leap year.
- /// </summary>
- public override int GetLeapMonth(int year, int era)
- {
- year = CheckYearRange(year, era);
- int month = GetYearInfo(year, LeapMonth);
- return month > 0 ? month + 1 : 0;
- }
-
- internal bool InternalIsLeapYear(int year)
- {
- return GetYearInfo(year, LeapMonth) != 0;
- }
-
- /// <summary>
- /// Checks whether a given year in the specified era is a leap year.
- /// This method returns true if year is a leap year, or false if not.
- /// </summary>
- public override bool IsLeapYear(int year, int era)
- {
- year = CheckYearRange(year, era);
- return InternalIsLeapYear(year);
- }
-
- private const int DefaultGregorianTwoDigitYearMax = 2029;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(BaseCalendarID, GetYear(new DateTime(DefaultGregorianTwoDigitYearMax, 1, 1)));
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.ArgumentOutOfRange_NeedNonNegNum);
- }
-
- year = base.ToFourDigitYear(year);
- CheckYearRange(year, CurrentEra);
- return year;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/GlobalizationExtensions.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/GlobalizationExtensions.cs
deleted file mode 100644
index 2e61b5394ab..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/GlobalizationExtensions.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public static class GlobalizationExtensions
- {
- public static StringComparer GetStringComparer(this CompareInfo compareInfo, CompareOptions options)
- {
- if (compareInfo == null)
- {
- throw new ArgumentNullException(nameof(compareInfo));
- }
-
- if (options == CompareOptions.Ordinal)
- {
- return StringComparer.Ordinal;
- }
-
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return StringComparer.OrdinalIgnoreCase;
- }
-
- return new CultureAwareComparer(compareInfo, options);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
deleted file mode 100644
index 6767b9a26a2..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
+++ /dev/null
@@ -1,488 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// This calendar recognizes two era values:
- /// 0 CurrentEra (AD)
- /// 1 BeforeCurrentEra (BC)
- /// </remarks>
- public class GregorianCalendar : Calendar
- {
- public const int ADEra = 1;
-
- // This is the min Gregorian year can be represented by the DateTime class.
- // The limitation is derived from the DateTime class.
- internal const int MinYear = 1;
-
- // This is the max Gregorian year can be represented by the DateTime class.
- // The limitation is derived from the DateTime class.
- internal const int MaxYear = 9999;
-
- private GregorianCalendarTypes _type;
-
- private static readonly int[] DaysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
-
- private static readonly int[] DaysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
-
- private static volatile Calendar? s_defaultInstance;
-
- public override DateTime MinSupportedDateTime => DateTime.MinValue;
-
- public override DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- /// <summary>
- /// Internal method to provide a default intance of GregorianCalendar.
- /// Used by NLS+ implementation
- /// </summary>
- internal static Calendar GetDefaultInstance() => s_defaultInstance ??= new GregorianCalendar();
-
- public GregorianCalendar() : this(GregorianCalendarTypes.Localized)
- {
- }
-
- public GregorianCalendar(GregorianCalendarTypes type)
- {
- if (type < GregorianCalendarTypes.Localized || type > GregorianCalendarTypes.TransliteratedFrench)
- {
- throw new ArgumentOutOfRangeException(
- nameof(type),
- type,
- SR.Format(SR.ArgumentOutOfRange_Range, GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench));
- }
-
- _type = type;
- }
-
- public virtual GregorianCalendarTypes CalendarType
- {
- get => _type;
- set
- {
- VerifyWritable();
- if (value < GregorianCalendarTypes.Localized || value > GregorianCalendarTypes.TransliteratedFrench)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench));
- }
-
- _type = value;
- }
- }
-
- internal override CalendarId ID =>
- // By returning different ID for different variations of GregorianCalendar,
- // we can support the Transliterated Gregorian calendar.
- // DateTimeFormatInfo will use this ID to get formatting information about
- // the calendar.
- (CalendarId)_type;
-
- /// <summary>
- /// Gets the absolute date for the given Gregorian date. The absolute date means
- /// the number of days from January 1st, 1 A.D.
- /// </summary>
- /// <remarks>
- /// This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars.
- /// Number of Days in Prior Years (both common and leap years) +
- /// Number of Days in Prior Months of Current Year +
- /// Number of Days in Current Month
- /// </remarks>
- internal static long GetAbsoluteDate(int year, int month, int day)
- {
- if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12)
- {
- int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
- if (day >= 1 && (day <= days[month] - days[month - 1]))
- {
- int y = year - 1;
- return y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
- }
- }
-
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- /// <summary>
- /// Returns the tick count corresponding to the given year, month, and day.
- /// Will check the if the parameters are valid.
- /// </summary>
- internal virtual long DateToTicks(int year, int month, int day)
- {
- return GetAbsoluteDate(year, month, day) * TicksPerDay;
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding the given number of
- /// months to the specified DateTime. The result is computed by incrementing
- /// (or decrementing) the year and month parts of the specified DateTime by
- /// value months, and, if required, adjusting the day part of the
- /// resulting date downwards to the last day of the resulting month in the
- /// resulting year. The time-of-day part of the result is the same as the
- /// time-of-day part of the specified DateTime.
- ///
- /// In more precise terms, considering the specified DateTime to be of the
- /// form y / m / d + t, where y is the
- /// year, m is the month, d is the day, and t is the
- /// time-of-day, the result is y1 / m1 / d1 + t,
- /// where y1 and m1 are computed by adding value months
- /// to y and m, and d1 is the largest value less than
- /// or equal to d that denotes a valid day in month m1 of year
- /// y1.
- /// </summary>
- public override DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- months,
- SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
- }
-
- time.GetDatePart(out int y, out int m, out int d);
- int i = m - 1 + months;
- if (i >= 0)
- {
- m = i % 12 + 1;
- y += i / 12;
- }
- else
- {
- m = 12 + (i + 1) % 12;
- y += (i - 11) / 12;
- }
-
- int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
- int days = (daysArray[m] - daysArray[m - 1]);
-
- if (d > days)
- {
- d = days;
- }
- long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay;
- Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
-
- return new DateTime(ticks);
- }
-
- /// <summary>
- /// Returns the DateTime resulting from adding the given number of
- /// years to the specified DateTime. The result is computed by incrementing
- /// (or decrementing) the year part of the specified DateTime by value
- /// years. If the month and day of the specified DateTime is 2/29, and if the
- /// resulting year is not a leap year, the month and day of the resulting
- /// DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
- /// parts of the result are the same as those of the specified DateTime.
- /// </summary>
- public override DateTime AddYears(DateTime time, int years)
- {
- return AddMonths(time, years * 12);
- }
-
- /// <summary>
- /// Returns the day-of-month part of the specified DateTime. The returned
- /// value is an integer between 1 and 31.
- /// </summary>
- public override int GetDayOfMonth(DateTime time) => time.Day;
-
- /// <summary>
- /// Returns the day-of-week part of the specified DateTime. The returned value
- /// is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
- /// Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
- /// Thursday, 5 indicates Friday, and 6 indicates Saturday.
- /// </summary>
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
- }
-
- /// <summary>
- /// Returns the day-of-year part of the specified DateTime. The returned value
- /// is an integer between 1 and 366.
- /// </summary>
- public override int GetDayOfYear(DateTime time) => time.DayOfYear;
-
- /// <summary>
- /// Returns the number of days in the month given by the year and
- /// month arguments.
- /// </summary>
- public override int GetDaysInMonth(int year, int month, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
-
- int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365);
- return days[month] - days[month - 1];
- }
-
- /// <summary>
- /// Returns the number of days in the year given by the year argument for
- /// the current era.
- /// </summary>
- public override int GetDaysInYear(int year, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
-
- return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365;
- }
-
- public override int GetEra(DateTime time) => ADEra;
-
- public override int[] Eras => new int[] { ADEra };
-
- /// <summary>
- /// Returns the month part of the specified DateTime.
- /// The returned value is an integer between 1 and 12.
- /// </summary>
- public override int GetMonth(DateTime time) => time.Month;
-
- /// <summary>
- /// Returns the number of months in the specified year and era.
- /// </summary>
- public override int GetMonthsInYear(int year, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
-
- return 12;
- }
-
- /// <summary>
- /// Returns the year part of the specified DateTime. The returned value is an
- /// integer between 1 and 9999.
- /// </summary>
- public override int GetYear(DateTime time) => time.Year;
-
- internal override bool IsValidYear(int year, int era) => year >= 1 && year <= MaxYear;
-
- internal override bool IsValidDay(int year, int month, int day, int era)
- {
- if ((era != CurrentEra && era != ADEra) ||
- year < 1 || year > MaxYear ||
- month < 1 || month > 12 ||
- day < 1)
- {
- return false;
- }
-
- int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
- return day <= (days[month] - days[month - 1]);
- }
-
- /// <summary>
- /// Checks whether a given day in the specified era is a leap day. This method returns true if
- /// the date is a leap day, or false if not.
- /// </summary>
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, 12));
- }
-
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
- if (day < 1 || day > GetDaysInMonth(year, month))
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, GetDaysInMonth(year, month)));
- }
-
- return IsLeapYear(year) && month == 2 && day == 29;
- }
-
- /// <summary>
- /// Returns the leap month in a calendar year of the specified era.
- /// This method returns 0 if this calendar does not have leap month, or
- /// this year is not a leap year.
- /// </summary>
- public override int GetLeapMonth(int year, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
-
- return 0;
- }
-
- /// <summary>
- /// Checks whether a given month in the specified era is a leap month.
- /// This method returns true if month is a leap month, or false if not.
- /// </summary>
- public override bool IsLeapMonth(int year, int month, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, 12));
- }
-
- return false;
- }
-
- /// <summary>
- /// Checks whether a given year in the specified era is a leap year. This method returns true if
- /// year is a leap year, or false if not.
- /// </summary>
- public override bool IsLeapYear(int year, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < 1 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
-
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
- }
-
- /// <summary>
- /// Returns the date and time converted to a DateTime value.
- /// Throws an exception if the n-tuple is invalid.
- /// </summary>
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- if (era != CurrentEra && era != ADEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
-
- return new DateTime(year, month, day, hour, minute, second, millisecond);
- }
-
- internal override bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
- {
- if (era != CurrentEra && era != ADEra)
- {
- result = DateTime.MinValue;
- return false;
- }
-
- return DateTime.TryCreate(year, month, day, hour, minute, second, millisecond, out result);
- }
-
- private const int DefaultTwoDigitYearMax = 2029;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxYear));
- }
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- if (year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
-
- return base.ToFourDigitYear(year);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
deleted file mode 100644
index 589a8b662f0..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
+++ /dev/null
@@ -1,660 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- // Gregorian Calendars use Era Info
- internal class EraInfo
- {
- internal int era; // The value of the era.
- internal long ticks; // The time in ticks when the era starts
- internal int yearOffset; // The offset to Gregorian year when the era starts.
- // Gregorian Year = Era Year + yearOffset
- // Era Year = Gregorian Year - yearOffset
- internal int minEraYear; // Min year value in this era. Generally, this value is 1, but this may
- // be affected by the DateTime.MinValue;
- internal int maxEraYear; // Max year value in this era. (== the year length of the era + 1)
-
- internal string? eraName; // The era name
- internal string? abbrevEraName; // Abbreviated Era Name
- internal string? englishEraName; // English era name
-
- internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear)
- {
- this.era = era;
- this.yearOffset = yearOffset;
- this.minEraYear = minEraYear;
- this.maxEraYear = maxEraYear;
- this.ticks = new DateTime(startYear, startMonth, startDay).Ticks;
- }
-
- internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear,
- string eraName, string abbrevEraName, string englishEraName)
- {
- this.era = era;
- this.yearOffset = yearOffset;
- this.minEraYear = minEraYear;
- this.maxEraYear = maxEraYear;
- this.ticks = new DateTime(startYear, startMonth, startDay).Ticks;
- this.eraName = eraName;
- this.abbrevEraName = abbrevEraName;
- this.englishEraName = englishEraName;
- }
- }
-
- // This calendar recognizes two era values:
- // 0 CurrentEra (AD)
- // 1 BeforeCurrentEra (BC)
- internal class GregorianCalendarHelper
- {
- // 1 tick = 100ns = 10E-7 second
- // Number of ticks per time unit
- internal const long TicksPerMillisecond = 10000;
- internal const long TicksPerSecond = TicksPerMillisecond * 1000;
- internal const long TicksPerMinute = TicksPerSecond * 60;
- internal const long TicksPerHour = TicksPerMinute * 60;
- internal const long TicksPerDay = TicksPerHour * 24;
-
- // Number of milliseconds per time unit
- internal const int MillisPerSecond = 1000;
- internal const int MillisPerMinute = MillisPerSecond * 60;
- internal const int MillisPerHour = MillisPerMinute * 60;
- internal const int MillisPerDay = MillisPerHour * 24;
-
- // Number of days in a non-leap year
- internal const int DaysPerYear = 365;
- // Number of days in 4 years
- internal const int DaysPer4Years = DaysPerYear * 4 + 1;
- // Number of days in 100 years
- internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
- // Number of days in 400 years
- internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
-
- // Number of days from 1/1/0001 to 1/1/10000
- internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
-
- internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
-
- internal const int DatePartYear = 0;
- internal const int DatePartDayOfYear = 1;
- internal const int DatePartMonth = 2;
- internal const int DatePartDay = 3;
-
- //
- // This is the max Gregorian year can be represented by DateTime class. The limitation
- // is derived from DateTime class.
- //
- 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
- };
-
- internal int m_maxYear;
- internal int m_minYear;
- internal Calendar m_Cal;
-
- internal EraInfo[] m_EraInfo;
- internal int[]? m_eras = null;
-
- // Construct an instance of gregorian calendar.
- internal GregorianCalendarHelper(Calendar cal, EraInfo[] eraInfo)
- {
- m_Cal = cal;
- m_EraInfo = eraInfo;
- m_maxYear = m_EraInfo[0].maxEraYear;
- m_minYear = m_EraInfo[0].minEraYear;
- }
-
- // EraInfo.yearOffset: The offset to Gregorian year when the era starts. Gregorian Year = Era Year + yearOffset
- // Era Year = Gregorian Year - yearOffset
- // EraInfo.minEraYear: Min year value in this era. Generally, this value is 1, but this may be affected by the DateTime.MinValue;
- // EraInfo.maxEraYear: Max year value in this era. (== the year length of the era + 1)
- private int GetYearOffset(int year, int era, bool throwOnError)
- {
- if (year < 0)
- {
- if (throwOnError)
- {
- throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- return -1;
- }
-
- if (era == Calendar.CurrentEra)
- {
- era = m_Cal.CurrentEraValue;
- }
-
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- if (era == m_EraInfo[i].era)
- {
- if (year >= m_EraInfo[i].minEraYear)
- {
- if (year <= m_EraInfo[i].maxEraYear)
- {
- return m_EraInfo[i].yearOffset;
- }
- else if (!LocalAppContextSwitches.EnforceJapaneseEraYearRanges)
- {
- // If we got the year number exceeding the era max year number, this still possible be valid as the date can be created before
- // introducing new eras after the era we are checking. we'll loop on the eras after the era we have and ensure the year
- // can exist in one of these eras. otherwise, we'll throw.
- // Note, we always return the offset associated with the requested era.
- //
- // Here is some example:
- // if we are getting the era number 4 (Heisei) and getting the year number 32. if the era 4 has year range from 1 to 31
- // then year 32 exceeded the range of era 4 and we'll try to find out if the years difference (32 - 31 = 1) would lay in
- // the subsequent eras (e.g era 5 and up)
-
- int remainingYears = year - m_EraInfo[i].maxEraYear;
-
- for (int j = i - 1; j >= 0; j--)
- {
- if (remainingYears <= m_EraInfo[j].maxEraYear)
- {
- return m_EraInfo[i].yearOffset;
- }
- remainingYears -= m_EraInfo[j].maxEraYear;
- }
- }
- }
-
- if (throwOnError)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- SR.Format(
- SR.ArgumentOutOfRange_Range,
- m_EraInfo[i].minEraYear,
- m_EraInfo[i].maxEraYear));
- }
-
- break; // no need to iterate more on eras.
- }
- }
-
- if (throwOnError)
- {
- throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
- }
- return -1;
- }
-
- /*=================================GetGregorianYear==========================
- **Action: Get the Gregorian year value for the specified year in an era.
- **Returns: The Gregorian year value.
- **Arguments:
- ** year the year value in Japanese calendar
- ** era the Japanese emperor era value.
- **Exceptions:
- ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
- ============================================================================*/
-
- internal int GetGregorianYear(int year, int era)
- {
- return GetYearOffset(year, era, throwOnError: true) + year;
- }
-
- internal bool IsValidYear(int year, int era)
- {
- return GetYearOffset(year, era, throwOnError: false) >= 0;
- }
-
- // Returns a given date part of this DateTime. This method is used
- // to compute the year, day-of-year, month, or day part.
- internal virtual int GetDatePart(long ticks, int part)
- {
- CheckTicksRange(ticks);
- // n = number of days since 1/1/0001
- int n = (int)(ticks / TicksPerDay);
- // y400 = number of whole 400-year periods since 1/1/0001
- int y400 = n / DaysPer400Years;
- // n = day number within 400-year period
- n -= y400 * DaysPer400Years;
- // y100 = number of whole 100-year periods within 400-year period
- int y100 = n / DaysPer100Years;
- // Last 100-year period has an extra day, so decrement result if 4
- if (y100 == 4) y100 = 3;
- // n = day number within 100-year period
- n -= y100 * DaysPer100Years;
- // y4 = number of whole 4-year periods within 100-year period
- int y4 = n / DaysPer4Years;
- // n = day number within 4-year period
- n -= y4 * DaysPer4Years;
- // y1 = number of whole years within 4-year period
- int y1 = n / DaysPerYear;
- // Last year has an extra day, so decrement result if 4
- if (y1 == 4) y1 = 3;
- // If year was requested, compute and return it
- if (part == DatePartYear)
- {
- return y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1;
- }
- // n = day number within year
- n -= y1 * DaysPerYear;
- // If day-of-year was requested, return it
- if (part == DatePartDayOfYear)
- {
- return n + 1;
- }
- // 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;
- // All months have less than 32 days, so n >> 5 is a good conservative
- // estimate for the month
- int m = (n >> 5) + 1;
- // m = 1-based month number
- while (n >= days[m]) m++;
- // If month was requested, return it
- if (part == DatePartMonth) return m;
- // Return 1-based day-of-month
- return n - days[m - 1] + 1;
- }
-
- /*=================================GetAbsoluteDate==========================
- **Action: Gets the absolute date for the given Gregorian date. The absolute date means
- ** the number of days from January 1st, 1 A.D.
- **Returns: the absolute date
- **Arguments:
- ** year the Gregorian year
- ** month the Gregorian month
- ** day the day
- **Exceptions:
- ** ArgumentOutOfRangException if year, month, day value is valid.
- **Note:
- ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars.
- ** Number of Days in Prior Years (both common and leap years) +
- ** Number of Days in Prior Months of Current Year +
- ** Number of Days in Current Month
- **
- ============================================================================*/
-
- internal static long GetAbsoluteDate(int year, int month, int day)
- {
- if (year >= 1 && year <= 9999 && month >= 1 && month <= 12)
- {
- int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
- if (day >= 1 && (day <= days[month] - days[month - 1]))
- {
- int y = year - 1;
- int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
- return absoluteDate;
- }
- }
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- // Returns the tick count corresponding to the given year, month, and day.
- // Will check the if the parameters are valid.
- internal static long DateToTicks(int year, int month, int day)
- {
- return GetAbsoluteDate(year, month, day) * TicksPerDay;
- }
-
- // Return the tick count corresponding to the given hour, minute, second.
- // Will check the if the parameters are valid.
- internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
- {
- // TimeSpan.TimeToTicks is a family access function which does no error checking, so
- // we need to put some error checking out here.
- if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60)
- {
- if (millisecond < 0 || millisecond >= MillisPerSecond)
- {
- throw new ArgumentOutOfRangeException(
- nameof(millisecond),
- SR.Format(
- SR.ArgumentOutOfRange_Range,
- 0,
- MillisPerSecond - 1));
- }
- return InternalGlobalizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
- }
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
- }
-
- internal void CheckTicksRange(long ticks)
- {
- if (ticks < m_Cal.MinSupportedDateTime.Ticks || ticks > m_Cal.MaxSupportedDateTime.Ticks)
- {
- throw new ArgumentOutOfRangeException(
- "time",
- SR.Format(
- CultureInfo.InvariantCulture,
- SR.ArgumentOutOfRange_CalendarRange,
- m_Cal.MinSupportedDateTime,
- m_Cal.MaxSupportedDateTime));
- }
- }
-
- // Returns the DateTime resulting from adding the given number of
- // months to the specified DateTime. The result is computed by incrementing
- // (or decrementing) the year and month parts of the specified DateTime by
- // value months, and, if required, adjusting the day part of the
- // resulting date downwards to the last day of the resulting month in the
- // resulting year. The time-of-day part of the result is the same as the
- // time-of-day part of the specified DateTime.
- //
- // In more precise terms, considering the specified DateTime to be of the
- // form y / m / d + t, where y is the
- // year, m is the month, d is the day, and t is the
- // time-of-day, the result is y1 / m1 / d1 + t,
- // where y1 and m1 are computed by adding value months
- // to y and m, and d1 is the largest value less than
- // or equal to d that denotes a valid day in month m1 of year
- // y1.
- //
- public DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- SR.Format(
- SR.ArgumentOutOfRange_Range,
- -120000,
- 120000));
- }
- CheckTicksRange(time.Ticks);
-
- int y = GetDatePart(time.Ticks, DatePartYear);
- int m = GetDatePart(time.Ticks, DatePartMonth);
- int d = GetDatePart(time.Ticks, DatePartDay);
- int i = m - 1 + months;
- if (i >= 0)
- {
- m = i % 12 + 1;
- y += i / 12;
- }
- else
- {
- m = 12 + (i + 1) % 12;
- y += (i - 11) / 12;
- }
- int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
- int days = (daysArray[m] - daysArray[m - 1]);
-
- if (d > days)
- {
- d = days;
- }
- long ticks = DateToTicks(y, m, d) + (time.Ticks % TicksPerDay);
- Calendar.CheckAddResult(ticks, m_Cal.MinSupportedDateTime, m_Cal.MaxSupportedDateTime);
- return new DateTime(ticks);
- }
-
- // Returns the DateTime resulting from adding the given number of
- // years to the specified DateTime. The result is computed by incrementing
- // (or decrementing) the year part of the specified DateTime by value
- // years. If the month and day of the specified DateTime is 2/29, and if the
- // resulting year is not a leap year, the month and day of the resulting
- // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
- // parts of the result are the same as those of the specified DateTime.
- //
- public DateTime AddYears(DateTime time, int years)
- {
- return AddMonths(time, years * 12);
- }
-
- // Returns the day-of-month part of the specified DateTime. The returned
- // value is an integer between 1 and 31.
- //
- public int GetDayOfMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDay);
- }
-
- // Returns the day-of-week part of the specified DateTime. The returned value
- // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
- // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
- // Thursday, 5 indicates Friday, and 6 indicates Saturday.
- //
- public DayOfWeek GetDayOfWeek(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return (DayOfWeek)((time.Ticks / TicksPerDay + 1) % 7);
- }
-
- // Returns the day-of-year part of the specified DateTime. The returned value
- // is an integer between 1 and 366.
- //
- public int GetDayOfYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDayOfYear);
- }
-
- // Returns the number of days in the month given by the year and
- // month arguments.
- //
- public int GetDaysInMonth(int year, int month, int era)
- {
- //
- // Convert year/era value to Gregorain year value.
- //
- year = GetGregorianYear(year, era);
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(nameof(month), SR.ArgumentOutOfRange_Month);
- }
- int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365);
- return days[month] - days[month - 1];
- }
-
- // Returns the number of days in the year given by the year argument for the current era.
- //
-
- public int GetDaysInYear(int year, int era)
- {
- //
- // Convert year/era value to Gregorain year value.
- //
- year = GetGregorianYear(year, era);
- return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365;
- }
-
- // Returns the era for the specified DateTime value.
- public int GetEra(DateTime time)
- {
- long ticks = time.Ticks;
- // The assumption here is that m_EraInfo is listed in reverse order.
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- if (ticks >= m_EraInfo[i].ticks)
- {
- return m_EraInfo[i].era;
- }
- }
- throw new ArgumentOutOfRangeException(nameof(time), SR.ArgumentOutOfRange_Era);
- }
-
- public int[] Eras
- {
- get
- {
- if (m_eras == null)
- {
- m_eras = new int[m_EraInfo.Length];
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- m_eras[i] = m_EraInfo[i].era;
- }
- }
- return (int[])m_eras.Clone();
- }
- }
-
- // Returns the month part of the specified DateTime. The returned value is an
- // integer between 1 and 12.
- //
- public int GetMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartMonth);
- }
-
- // Returns the number of months in the specified year and era.
- // Always return 12.
- public int GetMonthsInYear(int year, int era)
- {
- ValidateYearInEra(year, era);
- return 12;
- }
-
- // Returns the year part of the specified DateTime. The returned value is an
- // integer between 1 and 9999.
- //
- public int GetYear(DateTime time)
- {
- long ticks = time.Ticks;
- int year = GetDatePart(ticks, DatePartYear);
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- if (ticks >= m_EraInfo[i].ticks)
- {
- return year - m_EraInfo[i].yearOffset;
- }
- }
- throw new ArgumentException(SR.Argument_NoEra);
- }
-
- // Returns the year that match the specified Gregorian year. The returned value is an
- // integer between 1 and 9999.
- //
- public int GetYear(int year, DateTime time)
- {
- long ticks = time.Ticks;
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- // while calculating dates with JapaneseLuniSolarCalendar, we can run into cases right after the start of the era
- // and still belong to the month which is started in previous era. Calculating equivalent calendar date will cause
- // using the new era info which will have the year offset equal to the year we are calculating year = m_EraInfo[i].yearOffset
- // which will end up with zero as calendar year.
- // We should use the previous era info instead to get the right year number. Example of such date is Feb 2nd 1989
- if (ticks >= m_EraInfo[i].ticks && year > m_EraInfo[i].yearOffset)
- {
- return year - m_EraInfo[i].yearOffset;
- }
- }
- throw new ArgumentException(SR.Argument_NoEra);
- }
-
- // Checks whether a given day in the specified era is a leap day. This method returns true if
- // the date is a leap day, or false if not.
- //
- public bool IsLeapDay(int year, int month, int day, int era)
- {
- // year/month/era checking is done in GetDaysInMonth()
- if (day < 1 || day > GetDaysInMonth(year, month, era))
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- SR.Format(
- SR.ArgumentOutOfRange_Range,
- 1,
- GetDaysInMonth(year, month, era)));
- }
-
- if (!IsLeapYear(year, era))
- {
- return false;
- }
-
- if (month == 2 && day == 29)
- {
- return true;
- }
-
- return false;
- }
-
- // Giving the calendar year and era, ValidateYearInEra will validate the existence of the input year in the input era.
- // This method will throw if the year or the era is invalid.
- public void ValidateYearInEra(int year, int era) => GetYearOffset(year, era, throwOnError: true);
-
- // Returns the leap month in a calendar year of the specified era.
- // This method always returns 0 as all calendars using this method don't have leap months.
- public int GetLeapMonth(int year, int era)
- {
- ValidateYearInEra(year, era);
- return 0;
- }
-
- // Checks whether a given month in the specified era is a leap month.
- // This method always returns false as all calendars using this method don't have leap months.
- public bool IsLeapMonth(int year, int month, int era)
- {
- ValidateYearInEra(year, era);
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- SR.Format(
- SR.ArgumentOutOfRange_Range,
- 1,
- 12));
- }
- return false;
- }
-
- // Checks whether a given year in the specified era is a leap year. This method returns true if
- // year is a leap year, or false if not.
- //
- public bool IsLeapYear(int year, int era)
- {
- year = GetGregorianYear(year, era);
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
- }
-
- // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
- //
- public DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- year = GetGregorianYear(year, era);
- long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second, millisecond);
- CheckTicksRange(ticks);
- return new DateTime(ticks);
- }
-
- public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
- {
- CheckTicksRange(time.Ticks);
- // Use GregorianCalendar to get around the problem that the implmentation in Calendar.GetWeekOfYear()
- // can call GetYear() that exceeds the supported range of the Gregorian-based calendars.
- return GregorianCalendar.GetDefaultInstance().GetWeekOfYear(time, rule, firstDayOfWeek);
- }
-
- public int ToFourDigitYear(int year, int twoDigitYearMax)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year),
- SR.ArgumentOutOfRange_NeedPosNum);
- }
-
- if (year < 100)
- {
- int y = year % 100;
- return (twoDigitYearMax / 100 - (y > twoDigitYearMax % 100 ? 1 : 0)) * 100 + y;
- }
-
- if (year < m_minYear || year > m_maxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- SR.Format(SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear));
- }
- // If the year value is above 100, just return the year value. Don't have to do
- // the TwoDigitYearMax comparison.
- return year;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarTypes.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarTypes.cs
deleted file mode 100644
index 46f13b00e06..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarTypes.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- // Note: The values of the members of this enum must match the coresponding values
- // in the CalendarId enum (since we cast between GregorianCalendarTypes and CalendarId).
- public enum GregorianCalendarTypes
- {
- Localized = CalendarId.GREGORIAN,
- USEnglish = CalendarId.GREGORIAN_US,
- MiddleEastFrench = CalendarId.GREGORIAN_ME_FRENCH,
- Arabic = CalendarId.GREGORIAN_ARABIC,
- TransliteratedEnglish = CalendarId.GREGORIAN_XLIT_ENGLISH,
- TransliteratedFrench = CalendarId.GREGORIAN_XLIT_FRENCH,
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
deleted file mode 100644
index 477c1ed8d93..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
+++ /dev/null
@@ -1,904 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Rules for the Hebrew calendar:
- /// - The Hebrew calendar is both a Lunar (months) and Solar (years)
- /// calendar, but allows for a week of seven days.
- /// - Days begin at sunset.
- /// - Leap Years occur in the 3, 6, 8, 11, 14, 17, &amp; 19th years of a
- /// 19-year cycle. Year = leap iff ((7y+1) mod 19 &lt; 7).
- /// - There are 12 months in a common year and 13 months in a leap year.
- /// - In a common year, the 6th month, Adar, has 29 days. In a leap
- /// year, the 6th month, Adar I, has 30 days and the leap month,
- /// Adar II, has 29 days.
- /// - Common years have 353-355 days. Leap years have 383-385 days.
- /// - The Hebrew new year (Rosh HaShanah) begins on the 1st of Tishri,
- /// the 7th month in the list below.
- /// - The new year may not begin on Sunday, Wednesday, or Friday.
- /// - If the new year would fall on a Tuesday and the conjunction of
- /// the following year were at midday or later, the new year is
- /// delayed until Thursday.
- /// - If the new year would fall on a Monday after a leap year, the
- /// new year is delayed until Tuesday.
- /// - The length of the 8th and 9th months vary from year to year,
- /// depending on the overall length of the year.
- /// - The length of a year is determined by the dates of the new
- /// years (Tishri 1) preceding and following the year in question.
- /// - The 2th month is long (30 days) if the year has 355 or 385 days.
- /// - The 3th month is short (29 days) if the year has 353 or 383 days.
- /// - The Hebrew months are:
- /// 1. Tishri (30 days)
- /// 2. Heshvan (29 or 30 days)
- /// 3. Kislev (29 or 30 days)
- /// 4. Teveth (29 days)
- /// 5. Shevat (30 days)
- /// 6. Adar I (30 days)
- /// 7. Adar {II} (29 days, this only exists if that year is a leap year)
- /// 8. Nisan (30 days)
- /// 9. Iyyar (29 days)
- /// 10. Sivan (30 days)
- /// 11. Tammuz (29 days)
- /// 12. Av (30 days)
- /// 13. Elul (29 days)
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1583/01/01 2239/09/29
- /// Hebrew 5343/04/07 5999/13/29
- ///
- /// Includes CHebrew implemetation;i.e All the code necessary for converting
- /// Gregorian to Hebrew Lunar from 1583 to 2239.
- /// </remarks>
- public class HebrewCalendar : Calendar
- {
- public static readonly int HebrewEra = 1;
-
- private const int DatePartYear = 0;
- private const int DatePartMonth = 2;
- private const int DatePartDay = 3;
-
- // Hebrew Translation Table.
- //
- // This table is used to get the following Hebrew calendar information for a
- // given Gregorian year:
- // 1. The day of the Hebrew month corresponding to Gregorian January 1st
- // for a given Gregorian year.
- // 2. The month of the Hebrew month corresponding to Gregorian January 1st
- // for a given Gregorian year.
- // The information is not directly in the table. Instead, the info is decoded
- // by special values (numbers above 29 and below 1).
- // 3. The type of the Hebrew year for a given Gregorian year.
- //
- // More notes:
- // This table includes 2 numbers for each year.
- // The offset into the table determines the year. (offset 0 is Gregorian year 1500)
- // 1st number determines the day of the Hebrew month coresponeds to January 1st.
- // 2nd number determines the type of the Hebrew year. (the type determines how
- // many days are there in the year.)
- //
- // normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
- // Leap years : 4 = 383 5 384 6 = 385 days.
- //
- // A 99 means the year is not supported for translation.
- // for convenience the table was defined for 750 year,
- // but only 640 years are supported. (from 1583 to 2239)
- // the years before 1582 (starting of Georgian calendar)
- // and after 2239, are filled with 99.
- //
- // Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
- // That's why, there no nead to specify the lunar month in the table.
- // There are exceptions, these are coded by giving numbers above 29 and below 1.
- // Actual decoding is takenig place whenever fetching information from the table.
- // The function for decoding is in GetLunarMonthDay().
- //
- // Example:
- // The data for 2000 - 2005 A.D. is:
- // 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004
- //
- // For year 2000, we know it has a Hebrew year type 6, which means it has 385 days.
- // And 1/1/2000 A.D. is Hebrew year 5760, 23rd day of 4th month.
- //
- // Jewish Era in use today is dated from the supposed year of the
- // Creation with its beginning in 3761 B.C.
- //
- // The Hebrew year of Gregorian 1st year AD.
- // 0001/01/01 AD is Hebrew 3760/01/01
- private const int HebrewYearOf1AD = 3760;
-
- private const int FirstGregorianTableYear = 1583; // == Hebrew Year 5343
- private const int LastGregorianTableYear = 2239; // == Hebrew Year 5999
-
- private const int TableSize = (LastGregorianTableYear - FirstGregorianTableYear);
-
- private const int MinHebrewYear = HebrewYearOf1AD + FirstGregorianTableYear; // == 5343
- private const int MaxHebrewYear = HebrewYearOf1AD + LastGregorianTableYear; // == 5999
-
- private static ReadOnlySpan<byte> HebrewTable => new byte[] // rely on C# compiler optimization to reference static data
- {
- 7, 3, 17, 3, // 1583-1584 (Hebrew year: 5343 - 5344)
- 0, 4, 11, 2, 21, 6, 1, 3, 13, 2, // 1585-1589
- 25, 4, 5, 3, 16, 2, 27, 6, 9, 1, // 1590-1594
- 20, 2, 0, 6, 11, 3, 23, 4, 4, 2, // 1595-1599
- 14, 3, 27, 4, 8, 2, 18, 3, 28, 6, // 1600
- 11, 1, 22, 5, 2, 3, 12, 3, 25, 4, // 1605
- 6, 2, 16, 3, 26, 6, 8, 2, 20, 1, // 1610
- 0, 6, 11, 2, 24, 4, 4, 3, 15, 2, // 1615
- 25, 6, 8, 1, 19, 2, 29, 6, 9, 3, // 1620
- 22, 4, 3, 2, 13, 3, 25, 4, 6, 3, // 1625
- 17, 2, 27, 6, 7, 3, 19, 2, 31, 4, // 1630
- 11, 3, 23, 4, 5, 2, 15, 3, 25, 6, // 1635
- 6, 2, 19, 1, 29, 6, 10, 2, 22, 4, // 1640
- 3, 3, 14, 2, 24, 6, 6, 1, 17, 3, // 1645
- 28, 5, 8, 3, 20, 1, 32, 5, 12, 3, // 1650
- 22, 6, 4, 1, 16, 2, 26, 6, 6, 3, // 1655
- 17, 2, 0, 4, 10, 3, 22, 4, 3, 2, // 1660
- 14, 3, 24, 6, 5, 2, 17, 1, 28, 6, // 1665
- 9, 2, 19, 3, 31, 4, 13, 2, 23, 6, // 1670
- 3, 3, 15, 1, 27, 5, 7, 3, 17, 3, // 1675
- 29, 4, 11, 2, 21, 6, 3, 1, 14, 2, // 1680
- 25, 6, 5, 3, 16, 2, 28, 4, 9, 3, // 1685
- 20, 2, 0, 6, 12, 1, 23, 6, 4, 2, // 1690
- 14, 3, 26, 4, 8, 2, 18, 3, 0, 4, // 1695
- 10, 3, 21, 5, 1, 3, 13, 1, 24, 5, // 1700
- 5, 3, 15, 3, 27, 4, 8, 2, 19, 3, // 1705
- 29, 6, 10, 2, 22, 4, 3, 3, 14, 2, // 1710
- 26, 4, 6, 3, 18, 2, 28, 6, 10, 1, // 1715
- 20, 6, 2, 2, 12, 3, 24, 4, 5, 2, // 1720
- 16, 3, 28, 4, 8, 3, 19, 2, 0, 6, // 1725
- 12, 1, 23, 5, 3, 3, 14, 3, 26, 4, // 1730
- 7, 2, 17, 3, 28, 6, 9, 2, 21, 4, // 1735
- 1, 3, 13, 2, 25, 4, 5, 3, 16, 2, // 1740
- 27, 6, 9, 1, 19, 3, 0, 5, 11, 3, // 1745
- 23, 4, 4, 2, 14, 3, 25, 6, 7, 1, // 1750
- 18, 2, 28, 6, 9, 3, 21, 4, 2, 2, // 1755
- 12, 3, 25, 4, 6, 2, 16, 3, 26, 6, // 1760
- 8, 2, 20, 1, 0, 6, 11, 2, 22, 6, // 1765
- 4, 1, 15, 2, 25, 6, 6, 3, 18, 1, // 1770
- 29, 5, 9, 3, 22, 4, 2, 3, 13, 2, // 1775
- 23, 6, 4, 3, 15, 2, 27, 4, 7, 3, // 1780
- 19, 2, 31, 4, 11, 3, 21, 6, 3, 2, // 1785
- 15, 1, 25, 6, 6, 2, 17, 3, 29, 4, // 1790
- 10, 2, 20, 6, 3, 1, 13, 3, 24, 5, // 1795
- 4, 3, 16, 1, 27, 5, 7, 3, 17, 3, // 1800
- 0, 4, 11, 2, 21, 6, 1, 3, 13, 2, // 1805
- 25, 4, 5, 3, 16, 2, 29, 4, 9, 3, // 1810
- 19, 6, 30, 2, 13, 1, 23, 6, 4, 2, // 1815
- 14, 3, 27, 4, 8, 2, 18, 3, 0, 4, // 1820
- 11, 3, 22, 5, 2, 3, 14, 1, 26, 5, // 1825
- 6, 3, 16, 3, 28, 4, 10, 2, 20, 6, // 1830
- 30, 3, 11, 2, 24, 4, 4, 3, 15, 2, // 1835
- 25, 6, 8, 1, 19, 2, 29, 6, 9, 3, // 1840
- 22, 4, 3, 2, 13, 3, 25, 4, 7, 2, // 1845
- 17, 3, 27, 6, 9, 1, 21, 5, 1, 3, // 1850
- 11, 3, 23, 4, 5, 2, 15, 3, 25, 6, // 1855
- 6, 2, 19, 1, 29, 6, 10, 2, 22, 4, // 1860
- 3, 3, 14, 2, 24, 6, 6, 1, 18, 2, // 1865
- 28, 6, 8, 3, 20, 4, 2, 2, 12, 3, // 1870
- 24, 4, 4, 3, 16, 2, 26, 6, 6, 3, // 1875
- 17, 2, 0, 4, 10, 3, 22, 4, 3, 2, // 1880
- 14, 3, 24, 6, 5, 2, 17, 1, 28, 6, // 1885
- 9, 2, 21, 4, 1, 3, 13, 2, 23, 6, // 1890
- 5, 1, 15, 3, 27, 5, 7, 3, 19, 1, // 1895
- 0, 5, 10, 3, 22, 4, 2, 3, 13, 2, // 1900
- 24, 6, 4, 3, 15, 2, 27, 4, 8, 3, // 1905
- 20, 4, 1, 2, 11, 3, 22, 6, 3, 2, // 1910
- 15, 1, 25, 6, 7, 2, 17, 3, 29, 4, // 1915
- 10, 2, 21, 6, 1, 3, 13, 1, 24, 5, // 1920
- 5, 3, 15, 3, 27, 4, 8, 2, 19, 6, // 1925
- 1, 1, 12, 2, 22, 6, 3, 3, 14, 2, // 1930
- 26, 4, 6, 3, 18, 2, 28, 6, 10, 1, // 1935
- 20, 6, 2, 2, 12, 3, 24, 4, 5, 2, // 1940
- 16, 3, 28, 4, 9, 2, 19, 6, 30, 3, // 1945
- 12, 1, 23, 5, 3, 3, 14, 3, 26, 4, // 1950
- 7, 2, 17, 3, 28, 6, 9, 2, 21, 4, // 1955
- 1, 3, 13, 2, 25, 4, 5, 3, 16, 2, // 1960
- 27, 6, 9, 1, 19, 6, 30, 2, 11, 3, // 1965
- 23, 4, 4, 2, 14, 3, 27, 4, 7, 3, // 1970
- 18, 2, 28, 6, 11, 1, 22, 5, 2, 3, // 1975
- 12, 3, 25, 4, 6, 2, 16, 3, 26, 6, // 1980
- 8, 2, 20, 4, 30, 3, 11, 2, 24, 4, // 1985
- 4, 3, 15, 2, 25, 6, 8, 1, 18, 3, // 1990
- 29, 5, 9, 3, 22, 4, 3, 2, 13, 3, // 1995
- 23, 6, 6, 1, 17, 2, 27, 6, 7, 3, // 2000 - 2004
- 20, 4, 1, 2, 11, 3, 23, 4, 5, 2, // 2005 - 2009
- 15, 3, 25, 6, 6, 2, 19, 1, 29, 6, // 2010
- 10, 2, 20, 6, 3, 1, 14, 2, 24, 6, // 2015
- 4, 3, 17, 1, 28, 5, 8, 3, 20, 4, // 2020
- 1, 3, 12, 2, 22, 6, 2, 3, 14, 2, // 2025
- 26, 4, 6, 3, 17, 2, 0, 4, 10, 3, // 2030
- 20, 6, 1, 2, 14, 1, 24, 6, 5, 2, // 2035
- 15, 3, 28, 4, 9, 2, 19, 6, 1, 1, // 2040
- 12, 3, 23, 5, 3, 3, 15, 1, 27, 5, // 2045
- 7, 3, 17, 3, 29, 4, 11, 2, 21, 6, // 2050
- 1, 3, 12, 2, 25, 4, 5, 3, 16, 2, // 2055
- 28, 4, 9, 3, 19, 6, 30, 2, 12, 1, // 2060
- 23, 6, 4, 2, 14, 3, 26, 4, 8, 2, // 2065
- 18, 3, 0, 4, 10, 3, 22, 5, 2, 3, // 2070
- 14, 1, 25, 5, 6, 3, 16, 3, 28, 4, // 2075
- 9, 2, 20, 6, 30, 3, 11, 2, 23, 4, // 2080
- 4, 3, 15, 2, 27, 4, 7, 3, 19, 2, // 2085
- 29, 6, 11, 1, 21, 6, 3, 2, 13, 3, // 2090
- 25, 4, 6, 2, 17, 3, 27, 6, 9, 1, // 2095
- 20, 5, 30, 3, 10, 3, 22, 4, 3, 2, // 2100
- 14, 3, 24, 6, 5, 2, 17, 1, 28, 6, // 2105
- 9, 2, 21, 4, 1, 3, 13, 2, 23, 6, // 2110
- 5, 1, 16, 2, 27, 6, 7, 3, 19, 4, // 2115
- 30, 2, 11, 3, 23, 4, 3, 3, 14, 2, // 2120
- 25, 6, 5, 3, 16, 2, 28, 4, 9, 3, // 2125
- 21, 4, 2, 2, 12, 3, 23, 6, 4, 2, // 2130
- 16, 1, 26, 6, 8, 2, 20, 4, 30, 3, // 2135
- 11, 2, 22, 6, 4, 1, 14, 3, 25, 5, // 2140
- 6, 3, 18, 1, 29, 5, 9, 3, 22, 4, // 2145
- 2, 3, 13, 2, 23, 6, 4, 3, 15, 2, // 2150
- 27, 4, 7, 3, 20, 4, 1, 2, 11, 3, // 2155
- 21, 6, 3, 2, 15, 1, 25, 6, 6, 2, // 2160
- 17, 3, 29, 4, 10, 2, 20, 6, 3, 1, // 2165
- 13, 3, 24, 5, 4, 3, 17, 1, 28, 5, // 2170
- 8, 3, 18, 6, 1, 1, 12, 2, 22, 6, // 2175
- 2, 3, 14, 2, 26, 4, 6, 3, 17, 2, // 2180
- 28, 6, 10, 1, 20, 6, 1, 2, 12, 3, // 2185
- 24, 4, 5, 2, 15, 3, 28, 4, 9, 2, // 2190
- 19, 6, 33, 3, 12, 1, 23, 5, 3, 3, // 2195
- 13, 3, 25, 4, 6, 2, 16, 3, 26, 6, // 2200
- 8, 2, 20, 4, 30, 3, 11, 2, 24, 4, // 2205
- 4, 3, 15, 2, 25, 6, 8, 1, 18, 6, // 2210
- 33, 2, 9, 3, 22, 4, 3, 2, 13, 3, // 2215
- 25, 4, 6, 3, 17, 2, 27, 6, 9, 1, // 2220
- 21, 5, 1, 3, 11, 3, 23, 4, 5, 2, // 2225
- 15, 3, 25, 6, 6, 2, 19, 4, 33, 3, // 2230
- 10, 2, 22, 4, 3, 3, 14, 2, 24, 6, // 2235
- 6, 1 // 2240 (Hebrew year: 6000)
- };
-
- private const int MaxMonthPlusOne = 14;
-
- // The lunar calendar has 6 different variations of month lengths
- // within a year.
- private static ReadOnlySpan<byte> LunarMonthLen => new byte[] // rely on C# compiler optimization to reference static data
- {
- 0, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0,
- 0, 30, 29, 29, 29, 30, 29, 30, 29, 30, 29, 30, 29, 0, // 3 common year variations
- 0, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 0,
- 0, 30, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 0,
- 0, 30, 29, 29, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, // 3 leap year variations
- 0, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29,
- 0, 30, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29
- };
-
- private static readonly DateTime s_calendarMinValue = new DateTime(1583, 1, 1);
-
- // Gregorian 2239/9/29 = Hebrew 5999/13/29 (last day in Hebrew year 5999).
- // We can only format/parse Hebrew numbers up to 999, so we limit the max range to Hebrew year 5999.
- private static readonly DateTime s_calendarMaxValue = new DateTime((new DateTime(2239, 9, 29, 23, 59, 59, 999)).Ticks + 9999);
-
- public override DateTime MinSupportedDateTime => s_calendarMinValue;
-
- public override DateTime MaxSupportedDateTime => s_calendarMaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunisolarCalendar;
-
- public HebrewCalendar()
- {
- }
-
- internal override CalendarId ID => CalendarId.HEBREW;
-
- private static void CheckHebrewYearValue(int y, int era, string varName)
- {
- CheckEraRange(era);
- if (y > MaxHebrewYear || y < MinHebrewYear)
- {
- throw new ArgumentOutOfRangeException(
- varName,
- y,
- SR.Format(SR.ArgumentOutOfRange_Range, MinHebrewYear, MaxHebrewYear));
- }
- }
-
- /// <summary>
- /// Check if the Hebrew month value is valid.
- /// </summary>
- /// <remarks>
- /// Call CheckHebrewYearValue() before calling this to verify the year value is supported.
- /// </remarks>
- private void CheckHebrewMonthValue(int year, int month, int era)
- {
- int monthsInYear = GetMonthsInYear(year, era);
- if (month < 1 || month > monthsInYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, monthsInYear));
- }
- }
-
- /// <summary>
- /// Check if the Hebrew day value is valid.
- /// </summary>
- /// <remarks>
- /// Call CheckHebrewYearValue()/CheckHebrewMonthValue() before calling this to verify the year/month values are valid.
- /// </remarks>
- private void CheckHebrewDayValue(int year, int month, int day, int era)
- {
- int daysInMonth = GetDaysInMonth(year, month, era);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, daysInMonth));
- }
- }
-
- private static void CheckEraRange(int era)
- {
- if (era != CurrentEra && era != HebrewEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- }
-
- private static void CheckTicksRange(long ticks)
- {
- if (ticks < s_calendarMinValue.Ticks || ticks > s_calendarMaxValue.Ticks)
- {
- throw new ArgumentOutOfRangeException(
- "time",
- ticks,
- // Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar.
- SR.Format(
- CultureInfo.InvariantCulture,
- SR.ArgumentOutOfRange_CalendarRange,
- s_calendarMinValue,
- s_calendarMaxValue));
- }
- }
-
- private static int GetResult(DateBuffer result, int part)
- {
- return part switch
- {
- DatePartYear => result.year,
- DatePartMonth => result.month,
- DatePartDay => result.day,
- _ => throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing),
- };
- }
-
- /// <summary>
- /// Using the Hebrew table (HebrewTable) to get the Hebrew month/day value for Gregorian January 1st
- /// in a given Gregorian year.
- /// Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
- /// That's why, there no nead to specify the lunar month in the table. There are exceptions, and these
- /// are coded by giving numbers above 29 and below 1.
- /// Actual decoding is takenig place in the switch statement below.
- /// </summary>
- /// <returns>
- /// The Hebrew year type. The value is from 1 to 6.
- /// normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
- /// Leap years : 4 = 383 5 384 6 = 385 days.
- /// </returns>
- internal static int GetLunarMonthDay(int gregorianYear, DateBuffer lunarDate)
- {
- // Get the offset into the LunarMonthLen array and the lunar day
- // for January 1st.
- int index = gregorianYear - FirstGregorianTableYear;
- if (index < 0 || index > TableSize)
- {
- throw new ArgumentOutOfRangeException(nameof(gregorianYear));
- }
-
- index *= 2;
- lunarDate.day = HebrewTable[index];
-
- // Get the type of the year. The value is from 1 to 6
- int lunarYearType = HebrewTable[index + 1];
-
- // Get the Lunar Month.
- switch (lunarDate.day)
- {
- case 0: // 1/1 is on Shvat 1
- lunarDate.month = 5;
- lunarDate.day = 1;
- break;
- case 30: // 1/1 is on Kislev 30
- lunarDate.month = 3;
- break;
- case 31: // 1/1 is on Shvat 2
- lunarDate.month = 5;
- lunarDate.day = 2;
- break;
- case 32: // 1/1 is on Shvat 3
- lunarDate.month = 5;
- lunarDate.day = 3;
- break;
- case 33: // 1/1 is on Kislev 29
- lunarDate.month = 3;
- lunarDate.day = 29;
- break;
- default: // 1/1 is on Tevet (This is the general case)
- lunarDate.month = 4;
- break;
- }
-
- return lunarYearType;
- }
-
- /// <summary>
- /// Returns a given date part of this DateTime. This method is used
- /// to compute the year, day-of-year, month, or day part.
- /// </summary>
- internal virtual int GetDatePart(long ticks, int part)
- {
- // The Gregorian year, month, day value for ticks.
- int gregorianYear, gregorianMonth, gregorianDay;
- int hebrewYearType; // lunar year type
- long AbsoluteDate; // absolute date - absolute date 1/1/1600
-
- // Make sure we have a valid Gregorian date that will fit into our
- // Hebrew conversion limits.
- CheckTicksRange(ticks);
-
- DateTime time = new DateTime(ticks);
-
- // Save the Gregorian date values.
- time.GetDatePart(out gregorianYear, out gregorianMonth, out gregorianDay);
-
- DateBuffer lunarDate = new DateBuffer(); // lunar month and day for Jan 1
-
- // From the table looking-up value of HebrewTable[index] (stored in lunarDate.day), we get the
- // lunar month and lunar day where the Gregorian date 1/1 falls.
- lunarDate.year = gregorianYear + HebrewYearOf1AD;
- hebrewYearType = GetLunarMonthDay(gregorianYear, lunarDate);
-
- // This is the buffer used to store the result Hebrew date.
- DateBuffer result = new DateBuffer();
-
- // Store the values for the start of the new year - 1/1.
- result.year = lunarDate.year;
- result.month = lunarDate.month;
- result.day = lunarDate.day;
-
- // Get the absolute date from 1/1/1600.
- AbsoluteDate = GregorianCalendar.GetAbsoluteDate(gregorianYear, gregorianMonth, gregorianDay);
-
- // If the requested date was 1/1, then we're done.
- if ((gregorianMonth == 1) && (gregorianDay == 1))
- {
- return GetResult(result, part);
- }
-
- // Calculate the number of days between 1/1 and the requested date.
- long numDays = AbsoluteDate - GregorianCalendar.GetAbsoluteDate(gregorianYear, 1, 1);
-
- // If the requested date is within the current lunar month, then
- // we're done.
- if ((numDays + (long)lunarDate.day) <= (long)(LunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month]))
- {
- result.day += (int)numDays;
- return GetResult(result, part);
- }
-
- // Adjust for the current partial month.
- result.month++;
- result.day = 1;
-
- // Adjust the Lunar Month and Year (if necessary) based on the number
- // of days between 1/1 and the requested date.
- // Assumes Jan 1 can never translate to the last Lunar month, which
- // is true.
- numDays -= (long)(LunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month] - lunarDate.day);
- Debug.Assert(numDays >= 1, "NumDays >= 1");
-
- // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month
- // and day.
- if (numDays > 1)
- {
- // See if we're on the correct Lunar month.
- while (numDays > (long)(LunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month]))
- {
- // Adjust the number of days and move to the next month.
- numDays -= (long)(LunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month++]);
-
- // See if we need to adjust the Year.
- // Must handle both 12 and 13 month years.
- if ((result.month > 13) || (LunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month] == 0))
- {
- // Adjust the Year.
- result.year++;
- hebrewYearType = HebrewTable[(gregorianYear + 1 - FirstGregorianTableYear) * 2 + 1];
-
- // Adjust the Month.
- result.month = 1;
- }
- }
-
- // Found the right Lunar month.
- result.day += (int)(numDays - 1);
- }
-
- return GetResult(result, part);
- }
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- try
- {
- int y = GetDatePart(time.Ticks, DatePartYear);
- int m = GetDatePart(time.Ticks, DatePartMonth);
- int d = GetDatePart(time.Ticks, DatePartDay);
-
- int monthsInYear;
- int i;
- if (months >= 0)
- {
- i = m + months;
- while (i > (monthsInYear = GetMonthsInYear(y, CurrentEra)))
- {
- y++;
- i -= monthsInYear;
- }
- }
- else
- {
- if ((i = m + months) <= 0)
- {
- months = -months;
- months -= m;
- y--;
-
- while (months > (monthsInYear = GetMonthsInYear(y, CurrentEra)))
- {
- y--;
- months -= monthsInYear;
- }
- monthsInYear = GetMonthsInYear(y, CurrentEra);
- i = monthsInYear - months;
- }
- }
-
- int days = GetDaysInMonth(y, i);
- if (d > days)
- {
- d = days;
- }
-
- return new DateTime(ToDateTime(y, i, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay));
- }
- // We expect ArgumentException and ArgumentOutOfRangeException (which is subclass of ArgumentException)
- // If exception is thrown in the calls above, we are out of the supported range of this calendar.
- catch (ArgumentException)
- {
- throw new ArgumentOutOfRangeException(nameof(months), months, SR.ArgumentOutOfRange_AddValue);
- }
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- int y = GetDatePart(time.Ticks, DatePartYear);
- int m = GetDatePart(time.Ticks, DatePartMonth);
- int d = GetDatePart(time.Ticks, DatePartDay);
-
- y += years;
- CheckHebrewYearValue(y, Calendar.CurrentEra, nameof(years));
-
- int months = GetMonthsInYear(y, CurrentEra);
- if (m > months)
- {
- m = months;
- }
-
- int days = GetDaysInMonth(y, m);
- if (d > days)
- {
- d = days;
- }
-
- long ticks = ToDateTime(y, m, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay);
- Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return new DateTime(ticks);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDay);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- // If we calculate back, the Hebrew day of week for Gregorian 0001/1/1 is Monday (1).
- // Therfore, the fomula is:
- return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
- }
-
- internal static int GetHebrewYearType(int year, int era)
- {
- CheckHebrewYearValue(year, era, nameof(year));
- // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear.
- // So we need to convert year (Hebrew year value) to Gregorian Year below.
- return HebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1];
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- // Get Hebrew year value of the specified time.
- int year = GetYear(time);
- DateTime beginOfYearDate;
- if (year == 5343)
- {
- // Gregorian 1583/01/01 corresponds to Hebrew 5343/04/07 (MinSupportedDateTime)
- // To figure out the Gregorian date associated with Hebrew 5343/01/01, we need to
- // count the days from 5343/01/01 to 5343/04/07 and subtract that from Gregorian
- // 1583/01/01.
- // 1. Tishri (30 days)
- // 2. Heshvan (30 days since 5343 has 355 days)
- // 3. Kislev (30 days since 5343 has 355 days)
- // 96 days to get from 5343/01/01 to 5343/04/07
- // Gregorian 1583/01/01 - 96 days = 1582/9/27
-
- // the beginning of Hebrew year 5343 corresponds to Gregorian September 27, 1582.
- beginOfYearDate = new DateTime(1582, 9, 27);
- }
- else
- {
- // following line will fail when year is 5343 (first supported year)
- beginOfYearDate = ToDateTime(year, 1, 1, 0, 0, 0, 0, CurrentEra);
- }
-
- return (int)((time.Ticks - beginOfYearDate.Ticks) / TicksPerDay) + 1;
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- CheckEraRange(era);
- int hebrewYearType = GetHebrewYearType(year, era);
- CheckHebrewMonthValue(year, month, era);
-
- Debug.Assert(hebrewYearType >= 1 && hebrewYearType <= 6,
- "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year);
- int monthDays = LunarMonthLen[hebrewYearType * MaxMonthPlusOne + month];
- if (monthDays == 0)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
-
- return monthDays;
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- CheckEraRange(era);
- // normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
- // Leap years : 4 = 383 5 384 6 = 385 days.
-
- // LunarYearType is from 1 to 6
- int LunarYearType = GetHebrewYearType(year, era);
- if (LunarYearType < 4)
- {
- // common year: LunarYearType = 1, 2, 3
- return 352 + LunarYearType;
- }
-
- return 382 + (LunarYearType - 3);
- }
-
- public override int GetEra(DateTime time) => HebrewEra;
-
- public override int[] Eras => new int[] { HebrewEra };
-
- public override int GetMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartMonth);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- return IsLeapYear(year, era) ? 13 : 12;
- }
-
- public override int GetYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartYear);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- if (IsLeapMonth(year, month, era))
- {
- // Every day in a leap month is a leap day.
- CheckHebrewDayValue(year, month, day, era);
- return true;
- }
- else if (IsLeapYear(year, Calendar.CurrentEra))
- {
- // There is an additional day in the 6th month in the leap year (the extra day is the 30th day in the 6th month),
- // so we should return true for 6/30 if that's in a leap year.
- if (month == 6 && day == 30)
- {
- return true;
- }
- }
-
- CheckHebrewDayValue(year, month, day, era);
- return false;
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- // Year/era values are checked in IsLeapYear().
- if (IsLeapYear(year, era))
- {
- // The 7th month in a leap year is a leap month.
- return 7;
- }
- return 0;
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- // Year/era values are checked in IsLeapYear().
- bool isLeapYear = IsLeapYear(year, era);
- CheckHebrewMonthValue(year, month, era);
-
- // The 7th month in a leap year is a leap month.
- return isLeapYear && month == 7;
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- CheckHebrewYearValue(year, era, nameof(year));
- return ((7 * (long)year + 1) % 19) < 7;
- }
-
- /// <summary>
- /// (month1, day1) - (month2, day2)
- /// </summary>
- private static int GetDayDifference(int lunarYearType, int month1, int day1, int month2, int day2)
- {
- if (month1 == month2)
- {
- return day1 - day2;
- }
-
- // Make sure that (month1, day1) < (month2, day2)
- bool swap = (month1 > month2);
- if (swap)
- {
- // (month1, day1) < (month2, day2). Swap the values.
- // The result will be a negative number.
- int tempMonth, tempDay;
- tempMonth = month1; tempDay = day1;
- month1 = month2; day1 = day2;
- month2 = tempMonth; day2 = tempDay;
- }
-
- // Get the number of days from (month1,day1) to (month1, end of month1)
- int days = LunarMonthLen[lunarYearType * MaxMonthPlusOne + month1] - day1;
-
- // Move to next month.
- month1++;
-
- // Add up the days.
- while (month1 < month2)
- {
- days += LunarMonthLen[lunarYearType * MaxMonthPlusOne + month1++];
- }
- days += day2;
-
- return swap ? days : -days;
- }
-
- /// <summary>
- /// Convert Hebrew date to Gregorian date.
- /// The algorithm is like this:
- /// The hebrew year has an offset to the Gregorian year, so we can guess the Gregorian year for
- /// the specified Hebrew year. That is, GreogrianYear = HebrewYear - FirstHebrewYearOf1AD.
- ///
- /// From the Gregorian year and HebrewTable, we can get the Hebrew month/day value
- /// of the Gregorian date January 1st. Let's call this month/day value [hebrewDateForJan1]
- ///
- /// If the requested Hebrew month/day is less than [hebrewDateForJan1], we know the result
- /// Gregorian date falls in previous year. So we decrease the Gregorian year value, and
- /// retrieve the Hebrew month/day value of the Gregorian date january 1st again.
- ///
- /// Now, we get the answer of the Gregorian year.
- ///
- /// The next step is to get the number of days between the requested Hebrew month/day
- /// and [hebrewDateForJan1]. When we get that, we can create the DateTime by adding/subtracting
- /// the ticks value of the number of days.
- /// </summary>
- private static DateTime HebrewToGregorian(int hebrewYear, int hebrewMonth, int hebrewDay, int hour, int minute, int second, int millisecond)
- {
- // Get the rough Gregorian year for the specified hebrewYear.
- int gregorianYear = hebrewYear - HebrewYearOf1AD;
-
- DateBuffer hebrewDateOfJan1 = new DateBuffer(); // year value is unused.
- int lunarYearType = GetLunarMonthDay(gregorianYear, hebrewDateOfJan1);
-
- if ((hebrewMonth == hebrewDateOfJan1.month) && (hebrewDay == hebrewDateOfJan1.day))
- {
- return new DateTime(gregorianYear, 1, 1, hour, minute, second, millisecond);
- }
-
- int days = GetDayDifference(lunarYearType, hebrewMonth, hebrewDay, hebrewDateOfJan1.month, hebrewDateOfJan1.day);
-
- DateTime gregorianNewYear = new DateTime(gregorianYear, 1, 1);
- return new DateTime(gregorianNewYear.Ticks + days * TicksPerDay + TimeToTicks(hour, minute, second, millisecond));
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- CheckHebrewYearValue(year, era, nameof(year));
- CheckHebrewMonthValue(year, month, era);
- CheckHebrewDayValue(year, month, day, era);
- DateTime dt = HebrewToGregorian(year, month, day, hour, minute, second, millisecond);
- CheckTicksRange(dt.Ticks);
- return dt;
- }
-
- private const int DefaultTwoDigitYearMax = 5790;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value == 99)
- {
- // Do nothing here. Year 99 is allowed so that TwoDitYearMax is disabled.
- }
- else
- {
- CheckHebrewYearValue(value, HebrewEra, nameof(value));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
-
- if (year < 100)
- {
- return base.ToFourDigitYear(year);
- }
-
- if (year > MaxHebrewYear || year < MinHebrewYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, MinHebrewYear, MaxHebrewYear));
- }
- return year;
- }
-
- internal class DateBuffer
- {
- internal int year;
- internal int month;
- internal int day;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
deleted file mode 100644
index 41cf1d2bf49..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
+++ /dev/null
@@ -1,447 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Text;
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- ////////////////////////////////////////////////////////////////////////////
- //
- // Used in HebrewNumber.ParseByChar to maintain the context information (
- // the state in the state machine and current Hebrew number values, etc.)
- // when parsing Hebrew number character by character.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal struct HebrewNumberParsingContext
- {
- // The current state of the state machine for parsing Hebrew numbers.
- internal HebrewNumber.HS state;
- // The current value of the Hebrew number.
- // The final value is determined when state is FoundEndOfHebrewNumber.
- internal int result;
-
- public HebrewNumberParsingContext(int result)
- {
- // Set the start state of the state machine for parsing Hebrew numbers.
- state = HebrewNumber.HS.Start;
- this.result = result;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Please see ParseByChar() for comments about different states defined here.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal enum HebrewNumberParsingState
- {
- InvalidHebrewNumber,
- NotHebrewDigit,
- FoundEndOfHebrewNumber,
- ContinueParsing,
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // class HebrewNumber
- //
- // Provides static methods for formatting integer values into
- // Hebrew text and parsing Hebrew number text.
- //
- // Limitations:
- // Parse can only handle value 1 ~ 999.
- // Append() can only handle 1 ~ 999. If value is greater than 5000,
- // 5000 will be subtracted from the value.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal static class HebrewNumber
- {
- ////////////////////////////////////////////////////////////////////////////
- //
- // Append
- //
- // Converts the given number to Hebrew letters according to the numeric
- // value of each Hebrew letter, appending to the supplied StringBuilder.
- // Basically, this converts the lunar year and the lunar month to letters.
- //
- // The character of a year is described by three letters of the Hebrew
- // alphabet, the first and third giving, respectively, the days of the
- // weeks on which the New Year occurs and Passover begins, while the
- // second is the initial of the Hebrew word for defective, normal, or
- // complete.
- //
- // Defective Year : Both Heshvan and Kislev are defective (353 or 383 days)
- // Normal Year : Heshvan is defective, Kislev is full (354 or 384 days)
- // Complete Year : Both Heshvan and Kislev are full (355 or 385 days)
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal static void Append(StringBuilder outputBuffer, int Number)
- {
- Debug.Assert(outputBuffer != null);
- int outputBufferStartingLength = outputBuffer.Length;
-
- char cTens = '\x0';
- char cUnits; // tens and units chars
- int Hundreds, Tens; // hundreds and tens values
-
- //
- // Adjust the number if greater than 5000.
- //
- if (Number > 5000)
- {
- Number -= 5000;
- }
-
- Debug.Assert(Number > 0 && Number <= 999, "Number is out of range.");
-
- //
- // Get the Hundreds.
- //
- Hundreds = Number / 100;
-
- if (Hundreds > 0)
- {
- Number -= Hundreds * 100;
- // \x05e7 = 100
- // \x05e8 = 200
- // \x05e9 = 300
- // \x05ea = 400
- // If the number is greater than 400, use the multiples of 400.
- for (int i = 0; i < (Hundreds / 4); i++)
- {
- outputBuffer.Append('\x05ea');
- }
-
- int remains = Hundreds % 4;
- if (remains > 0)
- {
- outputBuffer.Append((char)((int)'\x05e6' + remains));
- }
- }
-
- //
- // Get the Tens.
- //
- Tens = Number / 10;
- Number %= 10;
-
- switch (Tens)
- {
- case (0):
- cTens = '\x0';
- break;
- case (1):
- cTens = '\x05d9'; // Hebrew Letter Yod
- break;
- case (2):
- cTens = '\x05db'; // Hebrew Letter Kaf
- break;
- case (3):
- cTens = '\x05dc'; // Hebrew Letter Lamed
- break;
- case (4):
- cTens = '\x05de'; // Hebrew Letter Mem
- break;
- case (5):
- cTens = '\x05e0'; // Hebrew Letter Nun
- break;
- case (6):
- cTens = '\x05e1'; // Hebrew Letter Samekh
- break;
- case (7):
- cTens = '\x05e2'; // Hebrew Letter Ayin
- break;
- case (8):
- cTens = '\x05e4'; // Hebrew Letter Pe
- break;
- case (9):
- cTens = '\x05e6'; // Hebrew Letter Tsadi
- break;
- }
-
- //
- // Get the Units.
- //
- cUnits = (char)(Number > 0 ? ((int)'\x05d0' + Number - 1) : 0);
-
- if ((cUnits == '\x05d4') && // Hebrew Letter He (5)
- (cTens == '\x05d9'))
- { // Hebrew Letter Yod (10)
- cUnits = '\x05d5'; // Hebrew Letter Vav (6)
- cTens = '\x05d8'; // Hebrew Letter Tet (9)
- }
-
- if ((cUnits == '\x05d5') && // Hebrew Letter Vav (6)
- (cTens == '\x05d9'))
- { // Hebrew Letter Yod (10)
- cUnits = '\x05d6'; // Hebrew Letter Zayin (7)
- cTens = '\x05d8'; // Hebrew Letter Tet (9)
- }
-
- //
- // Copy the appropriate info to the given buffer.
- //
-
- if (cTens != '\x0')
- {
- outputBuffer.Append(cTens);
- }
-
- if (cUnits != '\x0')
- {
- outputBuffer.Append(cUnits);
- }
-
- if (outputBuffer.Length - outputBufferStartingLength > 1)
- {
- outputBuffer.Insert(outputBuffer.Length - 1, '"');
- }
- else
- {
- outputBuffer.Append('\'');
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Token used to tokenize a Hebrew word into tokens so that we can use in the
- // state machine.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- private enum HebrewToken : short
- {
- Invalid = -1,
- Digit400 = 0,
- Digit200_300 = 1,
- Digit100 = 2,
- Digit10 = 3, // 10 ~ 90
- Digit1 = 4, // 1, 2, 3, 4, 5, 8,
- Digit6_7 = 5,
- Digit7 = 6,
- Digit9 = 7,
- SingleQuote = 8,
- DoubleQuote = 9,
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // This class is used to map a token into its Hebrew digit value.
- //
- ////////////////////////////////////////////////////////////////////////////
-
- private struct HebrewValue
- {
- internal HebrewToken token;
- internal short value;
- internal HebrewValue(HebrewToken token, short value)
- {
- this.token = token;
- this.value = value;
- }
- }
-
- //
- // Map a Hebrew character from U+05D0 ~ U+05EA to its digit value.
- // The value is -1 if the Hebrew character does not have a associated value.
- //
- private static readonly HebrewValue[] s_hebrewValues = {
- new HebrewValue(HebrewToken.Digit1, 1), // '\x05d0
- new HebrewValue(HebrewToken.Digit1, 2), // '\x05d1
- new HebrewValue(HebrewToken.Digit1, 3), // '\x05d2
- new HebrewValue(HebrewToken.Digit1, 4), // '\x05d3
- new HebrewValue(HebrewToken.Digit1, 5), // '\x05d4
- new HebrewValue(HebrewToken.Digit6_7, 6), // '\x05d5
- new HebrewValue(HebrewToken.Digit6_7, 7), // '\x05d6
- new HebrewValue(HebrewToken.Digit1, 8), // '\x05d7
- new HebrewValue(HebrewToken.Digit9, 9), // '\x05d8
- new HebrewValue(HebrewToken.Digit10, 10), // '\x05d9; // Hebrew Letter Yod
- new HebrewValue(HebrewToken.Invalid, -1), // '\x05da;
- new HebrewValue(HebrewToken.Digit10, 20), // '\x05db; // Hebrew Letter Kaf
- new HebrewValue(HebrewToken.Digit10, 30), // '\x05dc; // Hebrew Letter Lamed
- new HebrewValue(HebrewToken.Invalid, -1), // '\x05dd;
- new HebrewValue(HebrewToken.Digit10, 40), // '\x05de; // Hebrew Letter Mem
- new HebrewValue(HebrewToken.Invalid, -1), // '\x05df;
- new HebrewValue(HebrewToken.Digit10, 50), // '\x05e0; // Hebrew Letter Nun
- new HebrewValue(HebrewToken.Digit10, 60), // '\x05e1; // Hebrew Letter Samekh
- new HebrewValue(HebrewToken.Digit10, 70), // '\x05e2; // Hebrew Letter Ayin
- new HebrewValue(HebrewToken.Invalid, -1), // '\x05e3;
- new HebrewValue(HebrewToken.Digit10, 80), // '\x05e4; // Hebrew Letter Pe
- new HebrewValue(HebrewToken.Invalid, -1), // '\x05e5;
- new HebrewValue(HebrewToken.Digit10, 90), // '\x05e6; // Hebrew Letter Tsadi
- new HebrewValue(HebrewToken.Digit100, 100), // '\x05e7;
- new HebrewValue(HebrewToken.Digit200_300, 200), // '\x05e8;
- new HebrewValue(HebrewToken.Digit200_300, 300), // '\x05e9;
- new HebrewValue(HebrewToken.Digit400, 400), // '\x05ea;
- };
-
- private const int minHebrewNumberCh = 0x05d0;
- private static readonly char s_maxHebrewNumberCh = (char)(minHebrewNumberCh + s_hebrewValues.Length - 1);
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Hebrew number parsing State
- // The current state and the next token will lead to the next state in the state machine.
- // DQ = Double Quote
- //
- ////////////////////////////////////////////////////////////////////////////
-
- internal enum HS : sbyte
- {
- _err = -1, // an error state
- Start = 0,
- S400 = 1, // a Hebrew digit 400
- S400_400 = 2, // Two Hebrew digit 400
- S400_X00 = 3, // Two Hebrew digit 400 and followed by 100
- S400_X0 = 4, // Hebrew digit 400 and followed by 10 ~ 90
- X00_DQ = 5, // A hundred number and followed by a double quote.
- S400_X00_X0 = 6,
- X0_DQ = 7, // A two-digit number and followed by a double quote.
- X = 8, // A single digit Hebrew number.
- X0 = 9, // A two-digit Hebrew number
- X00 = 10, // A three-digit Hebrew number
- S400_DQ = 11, // A Hebrew digit 400 and followed by a double quote.
- S400_400_DQ = 12,
- S400_400_100 = 13,
- S9 = 14, // Hebrew digit 9
- X00_S9 = 15, // A hundered number and followed by a digit 9
- S9_DQ = 16, // Hebrew digit 9 and followed by a double quote
- END = 100, // A terminial state is reached.
- }
-
- //
- // The state machine for Hebrew number pasing.
- //
- private static readonly HS[] s_numberPasingState =
- {
- // 400 300/200 100 90~10 8~1 6, 7, 9, ' "
- /* 0 */
- HS.S400, HS.X00, HS.X00, HS.X0, HS.X, HS.X, HS.X, HS.S9, HS._err, HS._err,
- /* 1: S400 */
- HS.S400_400, HS.S400_X00, HS.S400_X00, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.S400_DQ,
- /* 2: S400_400 */
- HS._err, HS._err, HS.S400_400_100, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.S400_400_DQ,
- /* 3: S400_X00 */
- HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ,
- /* 4: S400_X0 */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ,
- /* 5: X00_DQ */
- HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
- /* 6: S400_X00_X0 */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ,
- /* 7: X0_DQ */
- HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
- /* 8: X */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS._err,
- /* 9: X0 */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.X0_DQ,
- /* 10: X00 */
- HS._err, HS._err, HS._err, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.X00_DQ,
- /* 11: S400_DQ */
- HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
- /* 12: S400_400_DQ*/
- HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
- /* 13: S400_400_100*/
- HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ,
- /* 14: S9 */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.S9_DQ,
- /* 15: X00_S9 */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.S9_DQ,
- /* 16: S9_DQ */
- HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS._err, HS._err, HS._err
- };
-
- // Count of valid HebrewToken, column count in the NumberPasingState array
- private const int HebrewTokenCount = 10;
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Actions:
- // Parse the Hebrew number by passing one character at a time.
- // The state between characters are maintained at HebrewNumberPasingContext.
- // Returns:
- // Return a enum of HebrewNumberParsingState.
- // NotHebrewDigit: The specified ch is not a valid Hebrew digit.
- // InvalidHebrewNumber: After parsing the specified ch, it will lead into
- // an invalid Hebrew number text.
- // FoundEndOfHebrewNumber: A terminal state is reached. This means that
- // we find a valid Hebrew number text after the specified ch is parsed.
- // ContinueParsing: The specified ch is a valid Hebrew digit, and
- // it will lead into a valid state in the state machine, we should
- // continue to parse incoming characters.
- //
- ////////////////////////////////////////////////////////////////////////
-
- internal static HebrewNumberParsingState ParseByChar(char ch, ref HebrewNumberParsingContext context)
- {
- Debug.Assert(s_numberPasingState.Length == HebrewTokenCount * ((int)HS.S9_DQ + 1));
-
- HebrewToken token;
- if (ch == '\'')
- {
- token = HebrewToken.SingleQuote;
- }
- else if (ch == '\"')
- {
- token = HebrewToken.DoubleQuote;
- }
- else
- {
- int index = (int)ch - minHebrewNumberCh;
- if (index >= 0 && index < s_hebrewValues.Length)
- {
- token = s_hebrewValues[index].token;
- if (token == HebrewToken.Invalid)
- {
- return HebrewNumberParsingState.NotHebrewDigit;
- }
- context.result += s_hebrewValues[index].value;
- }
- else
- {
- // Not in valid Hebrew digit range.
- return HebrewNumberParsingState.NotHebrewDigit;
- }
- }
- context.state = s_numberPasingState[(int)context.state * (int)HebrewTokenCount + (int)token];
- if (context.state == HS._err)
- {
- // Invalid Hebrew state. This indicates an incorrect Hebrew number.
- return HebrewNumberParsingState.InvalidHebrewNumber;
- }
- if (context.state == HS.END)
- {
- // Reach a terminal state.
- return HebrewNumberParsingState.FoundEndOfHebrewNumber;
- }
- // We should continue to parse.
- return HebrewNumberParsingState.ContinueParsing;
- }
-
- ////////////////////////////////////////////////////////////////////////
- //
- // Actions:
- // Check if the ch is a valid Hebrew number digit.
- // This function will return true if the specified char is a legal Hebrew
- // digit character, single quote, or double quote.
- // Returns:
- // true if the specified character is a valid Hebrew number character.
- //
- ////////////////////////////////////////////////////////////////////////
-
- internal static bool IsDigit(char ch)
- {
- if (ch >= minHebrewNumberCh && ch <= s_maxHebrewNumberCh)
- {
- return s_hebrewValues[ch - minHebrewNumberCh].value >= 0;
- }
- return ch == '\'' || ch == '\"';
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Unix.cs
deleted file mode 100644
index a6e8f73d3e4..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Unix.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public partial class HijriCalendar : Calendar
- {
- private static int GetHijriDateAdjustment()
- {
- // this setting is not supported on Unix, so always return 0
- return 0;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
deleted file mode 100644
index d8f69fb5bb3..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Internal.Win32;
-
-namespace System.Globalization
-{
- public partial class HijriCalendar : Calendar
- {
- private int GetHijriDateAdjustment()
- {
- if (_hijriAdvance == int.MinValue)
- {
- // Never been set before. Use the system value from registry.
- _hijriAdvance = GetAdvanceHijriDate();
- }
- return _hijriAdvance;
- }
-
- private const string InternationalRegKey = "Control Panel\\International";
- private const string HijriAdvanceRegKeyEntry = "AddHijriDate";
-
- /*=================================GetAdvanceHijriDate==========================
- **Action: Gets the AddHijriDate value from the registry.
- **Returns:
- **Arguments: None.
- **Exceptions:
- **Note:
- ** The HijriCalendar has a user-overidable calculation. That is, use can set a value from the control
- ** panel, so that the calculation of the Hijri Calendar can move ahead or backwards from -2 to +2 days.
- **
- ** The valid string values in the registry are:
- ** "AddHijriDate-2" => Add -2 days to the current calculated Hijri date.
- ** "AddHijriDate" => Add -1 day to the current calculated Hijri date.
- ** "" => Add 0 day to the current calculated Hijri date.
- ** "AddHijriDate+1" => Add +1 days to the current calculated Hijri date.
- ** "AddHijriDate+2" => Add +2 days to the current calculated Hijri date.
- ============================================================================*/
- private static int GetAdvanceHijriDate()
- {
- using (RegistryKey? key = Registry.CurrentUser.OpenSubKey(InternationalRegKey))
- {
- // Abort if we didn't find anything
- if (key == null)
- {
- return 0;
- }
-
- object? value = key.GetValue(HijriAdvanceRegKeyEntry);
- if (value == null)
- {
- return 0;
- }
-
- int hijriAdvance = 0;
- string? str = value.ToString();
- if (string.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0)
- {
- if (str!.Length == HijriAdvanceRegKeyEntry.Length)
- hijriAdvance = -1;
- else
- {
- try
- {
- int advance = int.Parse(str.AsSpan(HijriAdvanceRegKeyEntry.Length), provider: CultureInfo.InvariantCulture);
- if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri))
- {
- hijriAdvance = advance;
- }
- }
- // If we got garbage from registry just ignore it.
- // hijriAdvance = 0 because of declaraction assignment up above.
- catch (ArgumentException) { }
- catch (FormatException) { }
- catch (OverflowException) { }
- }
- }
- return hijriAdvance;
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
deleted file mode 100644
index 4a4c667a5d5..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
+++ /dev/null
@@ -1,473 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Rules for the Hijri calendar:
- /// - The Hijri calendar is a strictly Lunar calendar.
- /// - Days begin at sunset.
- /// - Islamic Year 1 (Muharram 1, 1 A.H.) is equivalent to absolute date
- /// 227015 (Friday, July 16, 622 C.E. - Julian).
- /// - Leap Years occur in the 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, &amp; 29th
- /// years of a 30-year cycle. Year = leap iff ((11y+14) mod 30 &lt; 11).
- /// - There are 12 months which contain alternately 30 and 29 days.
- /// - The 12th month, Dhu al-Hijjah, contains 30 days instead of 29 days
- /// in a leap year.
- /// - Common years have 354 days. Leap years have 355 days.
- /// - There are 10,631 days in a 30-year cycle.
- /// - The Islamic months are:
- /// 1. Muharram (30 days) 7. Rajab (30 days)
- /// 2. Safar (29 days) 8. Sha'ban (29 days)
- /// 3. Rabi I (30 days) 9. Ramadan (30 days)
- /// 4. Rabi II (29 days) 10. Shawwal (29 days)
- /// 5. Jumada I (30 days) 11. Dhu al-Qada (30 days)
- /// 6. Jumada II (29 days) 12. Dhu al-Hijjah (29 days) {30}
- ///
- /// NOTENOTE
- /// The calculation of the HijriCalendar is based on the absolute date. And the
- /// absolute date means the number of days from January 1st, 1 A.D.
- /// Therefore, we do not support the days before the January 1st, 1 A.D.
- ///
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 0622/07/18 9999/12/31
- /// Hijri 0001/01/01 9666/04/03
- /// </remarks>
-
- public partial class HijriCalendar : Calendar
- {
- public static readonly int HijriEra = 1;
-
- private const int DatePartYear = 0;
- private const int DatePartDayOfYear = 1;
- private const int DatePartMonth = 2;
- private const int DatePartDay = 3;
-
- 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 int _hijriAdvance = int.MinValue;
-
- // DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3).
- private const int MaxCalendarYear = 9666;
- private const int MaxCalendarMonth = 4;
-
- // Hijri calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 7, day: 18)
- // This is the minimal Gregorian date that we support in the HijriCalendar.
- private static readonly DateTime s_calendarMinValue = new DateTime(622, 7, 18);
- private static readonly DateTime s_calendarMaxValue = DateTime.MaxValue;
-
- public override DateTime MinSupportedDateTime => s_calendarMinValue;
-
- public override DateTime MaxSupportedDateTime => s_calendarMaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunarCalendar;
-
- public HijriCalendar()
- {
- }
-
- internal override CalendarId ID => CalendarId.HIJRI;
-
- protected override int DaysInYearBeforeMinSupportedYear =>
- // the year before the 1st year of the cycle would have been the 30th year
- // of the previous cycle which is not a leap year. Common years have 354 days.
- 354;
-
- private long GetAbsoluteDateHijri(int y, int m, int d)
- {
- return (long)(DaysUpToHijriYear(y) + s_hijriMonthDays[m - 1] + d - 1 - HijriAdjustment);
- }
-
- private long DaysUpToHijriYear(int HijriYear)
- {
- // Compute the number of years up to the current 30 year cycle.
- int numYear30 = ((HijriYear - 1) / 30) * 30;
-
- // Compute the number of years left. This is the number of years
- // into the 30 year cycle for the given year.
- int numYearsLeft = HijriYear - numYear30 - 1;
-
- // Compute the number of absolute days up to the given year.
- long numDays = ((numYear30 * 10631L) / 30L) + 227013L;
- while (numYearsLeft > 0)
- {
- // Common year is 354 days, and leap year is 355 days.
- numDays += 354 + (IsLeapYear(numYearsLeft, CurrentEra) ? 1 : 0);
- numYearsLeft--;
- }
-
- return numDays;
- }
-
- public int HijriAdjustment
- {
- get
- {
- if (_hijriAdvance == int.MinValue)
- {
- // Never been set before. Use the system value from registry.
- _hijriAdvance = GetHijriDateAdjustment();
- }
-
- return _hijriAdvance;
- }
-
- set
- {
- if (value < MinAdvancedHijri || value > MaxAdvancedHijri)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, MinAdvancedHijri, MaxAdvancedHijri));
- }
-
- VerifyWritable();
- _hijriAdvance = value;
- }
- }
-
- internal static void CheckTicksRange(long ticks)
- {
- if (ticks < s_calendarMinValue.Ticks || ticks > s_calendarMaxValue.Ticks)
- {
- throw new ArgumentOutOfRangeException(
- "time",
- ticks,
- SR.Format(
- CultureInfo.InvariantCulture,
- SR.ArgumentOutOfRange_CalendarRange,
- s_calendarMinValue,
- s_calendarMaxValue));
- }
- }
-
- internal static void CheckEraRange(int era)
- {
- if (era != CurrentEra && era != HijriEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- }
-
- internal static void CheckYearRange(int year, int era)
- {
- CheckEraRange(era);
- if (year < 1 || year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear));
- }
- }
-
- internal static void CheckYearMonthRange(int year, int month, int era)
- {
- CheckYearRange(year, era);
- if (year == MaxCalendarYear)
- {
- if (month > MaxCalendarMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxCalendarMonth));
- }
- }
-
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
- }
-
- /// <summary>
- /// First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
- /// Use the formula (((AbsoluteDate - 227013) * 30) / 10631) + 1, we can a rough value for the Hijri year.
- /// In order to get the exact Hijri year, we compare the exact absolute date for HijriYear and (HijriYear + 1).
- /// From here, we can get the correct Hijri year.
- /// </summary>
- internal virtual int GetDatePart(long ticks, int part)
- {
- CheckTicksRange(ticks);
-
- // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
- // 1/1/0001 is absolute date 1.
- long numDays = ticks / GregorianCalendar.TicksPerDay + 1;
-
- // See how much we need to backup or advance
- numDays += HijriAdjustment;
-
- // Calculate the appromixate Hijri Year from this magic formula.
- int hijriYear = (int)(((numDays - 227013) * 30) / 10631) + 1;
-
- long daysToHijriYear = DaysUpToHijriYear(hijriYear); // The absolute date for HijriYear
- long daysOfHijriYear = GetDaysInYear(hijriYear, CurrentEra); // The number of days for (HijriYear+1) year.
-
- if (numDays < daysToHijriYear)
- {
- daysToHijriYear -= daysOfHijriYear;
- hijriYear--;
- }
- else if (numDays == daysToHijriYear)
- {
- hijriYear--;
- daysToHijriYear -= GetDaysInYear(hijriYear, CurrentEra);
- }
- else
- {
- if (numDays > daysToHijriYear + daysOfHijriYear)
- {
- daysToHijriYear += daysOfHijriYear;
- hijriYear++;
- }
- }
- if (part == DatePartYear)
- {
- return hijriYear;
- }
-
- // Calculate the Hijri Month.
- int hijriMonth = 1;
- numDays -= daysToHijriYear;
-
- if (part == DatePartDayOfYear)
- {
- return (int)numDays;
- }
-
- while ((hijriMonth <= 12) && (numDays > s_hijriMonthDays[hijriMonth - 1]))
- {
- hijriMonth++;
- }
- hijriMonth--;
-
- if (part == DatePartMonth)
- {
- return hijriMonth;
- }
-
- // Calculate the Hijri Day.
- int hijriDay = (int)(numDays - s_hijriMonthDays[hijriMonth - 1]);
-
- if (part == DatePartDay)
- {
- return hijriDay;
- }
-
- // Incorrect part value.
- throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
- }
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- months,
- SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
- }
-
- // Get the date in Hijri calendar.
- int y = GetDatePart(time.Ticks, DatePartYear);
- int m = GetDatePart(time.Ticks, DatePartMonth);
- int d = GetDatePart(time.Ticks, DatePartDay);
- int i = m - 1 + months;
- if (i >= 0)
- {
- m = i % 12 + 1;
- y += i / 12;
- }
- else
- {
- m = 12 + (i + 1) % 12;
- y += (i - 11) / 12;
- }
-
- int days = GetDaysInMonth(y, m);
- if (d > days)
- {
- d = days;
- }
-
- long ticks = GetAbsoluteDateHijri(y, m, d) * TicksPerDay + (time.Ticks % TicksPerDay);
- Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return new DateTime(ticks);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return AddMonths(time, years * 12);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDay);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDayOfYear);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- CheckYearMonthRange(year, month, era);
- if (month == 12)
- {
- // For the 12th month, leap year has 30 days, and common year has 29 days.
- return IsLeapYear(year, CurrentEra) ? 30 : 29;
- }
-
- // Other months contain 30 and 29 days alternatively. The 1st month has 30 days.
- return ((month % 2) == 1) ? 30 : 29;
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- CheckYearRange(year, era);
- // Common years have 354 days. Leap years have 355 days.
- return IsLeapYear(year, CurrentEra) ? 355 : 354;
- }
-
- public override int GetEra(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return HijriEra;
- }
-
- public override int[] Eras => new int[] { HijriEra };
-
- public override int GetMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartMonth);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- CheckYearRange(year, era);
- return 12;
- }
-
- public override int GetYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartYear);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- // The year/month/era value checking is done in GetDaysInMonth().
- int daysInMonth = GetDaysInMonth(year, month, era);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
-
- return IsLeapYear(year, era) && month == 12 && day == 30;
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- CheckYearRange(year, era);
- return 0;
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- CheckYearMonthRange(year, month, era);
- return false;
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- CheckYearRange(year, era);
- return (((year * 11) + 14) % 30) < 11;
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- // The year/month/era checking is done in GetDaysInMonth().
- int daysInMonth = GetDaysInMonth(year, month, era);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
-
- long lDate = GetAbsoluteDateHijri(year, month, day);
- if (lDate < 0)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond));
- }
-
- private const int DefaultTwoDigitYearMax = 1451;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
-
- if (year < 100)
- {
- return base.ToFourDigitYear(year);
- }
-
- if (year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear));
- }
- return year;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs
deleted file mode 100644
index 1c0a909abbc..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using static System.Globalization.GregorianCalendar;
-
-namespace System.Globalization
-{
- public static class ISOWeek
- {
- private const int WeeksInLongYear = 53;
- private const int WeeksInShortYear = 52;
-
- private const int MinWeek = 1;
- private const int MaxWeek = WeeksInLongYear;
-
- public static int GetWeekOfYear(DateTime date)
- {
- int week = GetWeekNumber(date);
-
- if (week < MinWeek)
- {
- // If the week number obtained equals 0, it means that the
- // given date belongs to the preceding (week-based) year.
- return GetWeeksInYear(date.Year - 1);
- }
-
- if (week > GetWeeksInYear(date.Year))
- {
- // If a week number of 53 is obtained, one must check that
- // the date is not actually in week 1 of the following year.
- return MinWeek;
- }
-
- return week;
- }
-
- public static int GetYear(DateTime date)
- {
- int week = GetWeekNumber(date);
-
- if (week < MinWeek)
- {
- // If the week number obtained equals 0, it means that the
- // given date belongs to the preceding (week-based) year.
- return date.Year - 1;
- }
-
- if (week > GetWeeksInYear(date.Year))
- {
- // If a week number of 53 is obtained, one must check that
- // the date is not actually in week 1 of the following year.
- return date.Year + 1;
- }
-
- return date.Year;
- }
-
- // The year parameter represents an ISO week-numbering year (also called ISO year informally).
- // Each week's year is the Gregorian year in which the Thursday falls.
- // The first week of the year, hence, always contains 4 January.
- // ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
- public static DateTime GetYearStart(int year)
- {
- return ToDateTime(year, MinWeek, DayOfWeek.Monday);
- }
-
- // The year parameter represents an ISO week-numbering year (also called ISO year informally).
- // Each week's year is the Gregorian year in which the Thursday falls.
- // The first week of the year, hence, always contains 4 January.
- // ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
- public static DateTime GetYearEnd(int year)
- {
- return ToDateTime(year, GetWeeksInYear(year), DayOfWeek.Sunday);
- }
-
- // From https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year:
- //
- // The long years, with 53 weeks in them, can be described by any of the following equivalent definitions:
- //
- // - Any year starting on Thursday and any leap year starting on Wednesday.
- // - Any year ending on Thursday and any leap year ending on Friday.
- // - Years in which 1 January and 31 December (in common years) or either (in leap years) are Thursdays.
- //
- // All other week-numbering years are short years and have 52 weeks.
- public static int GetWeeksInYear(int year)
- {
- if (year < MinYear || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
- }
-
- static int P(int y) => (y + (y / 4) - (y / 100) + (y / 400)) % 7;
-
- if (P(year) == 4 || P(year - 1) == 3)
- {
- return WeeksInLongYear;
- }
-
- return WeeksInShortYear;
- }
-
- // From https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year,_week_number_and_weekday:
- //
- // This method requires that one know the weekday of 4 January of the year in question.
- // Add 3 to the number of this weekday, giving a correction to be used for dates within this year.
- //
- // Multiply the week number by 7, then add the weekday. From this sum subtract the correction for the year.
- // The result is the ordinal date, which can be converted into a calendar date.
- //
- // If the ordinal date thus obtained is zero or negative, the date belongs to the previous calendar year.
- // If greater than the number of days in the year, to the following year.
- public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek)
- {
- if (year < MinYear || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
- }
-
- if (week < MinWeek || week > MaxWeek)
- {
- throw new ArgumentOutOfRangeException(nameof(week), SR.ArgumentOutOfRange_Week_ISO);
- }
-
- // We allow 7 for convenience in cases where a user already has a valid ISO
- // day of week value for Sunday. This means that both 0 and 7 will map to Sunday.
- // The GetWeekday method will normalize this into the 1-7 range required by ISO.
- if ((int)dayOfWeek < 0 || (int)dayOfWeek > 7)
- {
- throw new ArgumentOutOfRangeException(nameof(dayOfWeek), SR.ArgumentOutOfRange_DayOfWeek);
- }
-
- var jan4 = new DateTime(year, month: 1, day: 4);
-
- int correction = GetWeekday(jan4.DayOfWeek) + 3;
-
- int ordinal = (week * 7) + GetWeekday(dayOfWeek) - correction;
-
- return new DateTime(year, month: 1, day: 1).AddDays(ordinal - 1);
- }
-
- // From https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_of_a_given_date:
- //
- // Using ISO weekday numbers (running from 1 for Monday to 7 for Sunday),
- // subtract the weekday from the ordinal date, then add 10. Divide the result by 7.
- // Ignore the remainder; the quotient equals the week number.
- //
- // If the week number thus obtained equals 0, it means that the given date belongs to the preceding (week-based) year.
- // If a week number of 53 is obtained, one must check that the date is not actually in week 1 of the following year.
- private static int GetWeekNumber(DateTime date)
- {
- return (date.DayOfYear - GetWeekday(date.DayOfWeek) + 10) / 7;
- }
-
- // Day of week in ISO is represented by an integer from 1 through 7, beginning with Monday and ending with Sunday.
- // This matches the underlying values of the DayOfWeek enum, except for Sunday, which needs to be converted.
- private static int GetWeekday(DayOfWeek dayOfWeek)
- {
- return dayOfWeek == DayOfWeek.Sunday ? 7 : (int)dayOfWeek;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
deleted file mode 100644
index 4c6ee2c4041..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- public sealed partial class IdnMapping
- {
- private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(unicodeString != null && unicodeString.Length >= count);
-
- uint flags = Flags;
- CheckInvalidIdnCharacters(unicode, count, flags, nameof(unicode));
-
- const int StackallocThreshold = 512;
- // Each unicode character is represented by up to 3 ASCII chars
- // and the whole string is prefixed by "xn--" (length 4)
- int estimatedLength = (int)Math.Min(count * 3L + 4, StackallocThreshold);
- int actualLength;
- if (estimatedLength < StackallocThreshold)
- {
- char* outputStack = stackalloc char[estimatedLength];
- actualLength = Interop.Globalization.ToAscii(flags, unicode, count, outputStack, estimatedLength);
- if (actualLength > 0 && actualLength <= estimatedLength)
- {
- return GetStringForOutput(unicodeString, unicode, count, outputStack, actualLength);
- }
- }
- else
- {
- actualLength = Interop.Globalization.ToAscii(flags, unicode, count, null, 0);
- }
- if (actualLength == 0)
- {
- throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(unicode));
- }
-
- char[] outputHeap = new char[actualLength];
- fixed (char* pOutputHeap = &outputHeap[0])
- {
- actualLength = Interop.Globalization.ToAscii(flags, unicode, count, pOutputHeap, actualLength);
- if (actualLength == 0 || actualLength > outputHeap.Length)
- {
- throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(unicode));
- }
- return GetStringForOutput(unicodeString, unicode, count, pOutputHeap, actualLength);
- }
- }
-
- private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(asciiString != null && asciiString.Length >= count);
-
- uint flags = Flags;
- CheckInvalidIdnCharacters(ascii, count, flags, nameof(ascii));
-
- const int StackAllocThreshold = 512;
- if (count < StackAllocThreshold)
- {
- char* output = stackalloc char[count];
- return GetUnicodeCore(asciiString, ascii, count, flags, output, count, reattempt: true);
- }
- else
- {
- char[] output = new char[count];
- fixed (char* pOutput = &output[0])
- {
- return GetUnicodeCore(asciiString, ascii, count, flags, pOutput, count, reattempt: true);
- }
- }
- }
-
- private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count, uint flags, char* output, int outputLength, bool reattempt)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(asciiString != null && asciiString.Length >= count);
-
- int realLen = Interop.Globalization.ToUnicode(flags, ascii, count, output, outputLength);
-
- if (realLen == 0)
- {
- throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(ascii));
- }
- else if (realLen <= outputLength)
- {
- return GetStringForOutput(asciiString, ascii, count, output, realLen);
- }
- else if (reattempt)
- {
- char[] newOutput = new char[realLen];
- fixed (char* pNewOutput = newOutput)
- {
- return GetUnicodeCore(asciiString, ascii, count, flags, pNewOutput, realLen, reattempt: false);
- }
- }
-
- throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(ascii));
- }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
-
- private uint Flags
- {
- get
- {
- int flags =
- (AllowUnassigned ? Interop.Globalization.AllowUnassigned : 0) |
- (UseStd3AsciiRules ? Interop.Globalization.UseStd3AsciiRules : 0);
- return (uint)flags;
- }
- }
-
- /// <summary>
- /// ICU doesn't check for invalid characters unless the STD3 rules option
- /// is enabled.
- ///
- /// To match Windows behavior, we walk the string ourselves looking for these
- /// bad characters so we can continue to throw ArgumentException in these cases.
- /// </summary>
- private static unsafe void CheckInvalidIdnCharacters(char* s, int count, uint flags, string paramName)
- {
- if ((flags & Interop.Globalization.UseStd3AsciiRules) == 0)
- {
- for (int i = 0; i < count; i++)
- {
- char c = s[i];
-
- // These characters are prohibited regardless of the UseStd3AsciiRules property.
- // See https://msdn.microsoft.com/en-us/library/system.globalization.idnmapping.usestd3asciirules(v=vs.110).aspx
- if (c <= 0x1F || c == 0x7F)
- {
- throw new ArgumentException(SR.Argument_IdnIllegalName, paramName);
- }
- }
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
deleted file mode 100644
index 6a97c04ebf6..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
+++ /dev/null
@@ -1,129 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.InteropServices;
-
-namespace System.Globalization
-{
- public sealed partial class IdnMapping
- {
- private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(unicodeString != null && unicodeString.Length >= count);
-
- uint flags = Flags;
-
- // Determine the required length
- int length = Interop.Normaliz.IdnToAscii(flags, unicode, count, null, 0);
- if (length == 0)
- {
- ThrowForZeroLength(unicode: true);
- }
-
- // Do the conversion
- const int StackAllocThreshold = 512; // arbitrary limit to switch from stack to heap allocation
- if (length < StackAllocThreshold)
- {
- char* output = stackalloc char[length];
- return GetAsciiCore(unicodeString, unicode, count, flags, output, length);
- }
- else
- {
- char[] output = new char[length];
- fixed (char* pOutput = &output[0])
- {
- return GetAsciiCore(unicodeString, unicode, count, flags, pOutput, length);
- }
- }
- }
-
- private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count, uint flags, char* output, int outputLength)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(unicodeString != null && unicodeString.Length >= count);
-
- int length = Interop.Normaliz.IdnToAscii(flags, unicode, count, output, outputLength);
- if (length == 0)
- {
- ThrowForZeroLength(unicode: true);
- }
- Debug.Assert(length == outputLength);
- return GetStringForOutput(unicodeString, unicode, count, output, length);
- }
-
- private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(asciiString != null && asciiString.Length >= count);
-
- uint flags = Flags;
-
- // Determine the required length
- int length = Interop.Normaliz.IdnToUnicode(flags, ascii, count, null, 0);
- if (length == 0)
- {
- ThrowForZeroLength(unicode: false);
- }
-
- // Do the conversion
- const int StackAllocThreshold = 512; // arbitrary limit to switch from stack to heap allocation
- if (length < StackAllocThreshold)
- {
- char* output = stackalloc char[length];
- return GetUnicodeCore(asciiString, ascii, count, flags, output, length);
- }
- else
- {
- char[] output = new char[length];
- fixed (char* pOutput = &output[0])
- {
- return GetUnicodeCore(asciiString, ascii, count, flags, pOutput, length);
- }
- }
- }
-
- private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count, uint flags, char* output, int outputLength)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(asciiString != null && asciiString.Length >= count);
-
- int length = Interop.Normaliz.IdnToUnicode(flags, ascii, count, output, outputLength);
- if (length == 0)
- {
- ThrowForZeroLength(unicode: false);
- }
- Debug.Assert(length == outputLength);
- return GetStringForOutput(asciiString, ascii, count, output, length);
- }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
-
- private uint Flags
- {
- get
- {
- int flags =
- (AllowUnassigned ? Interop.Normaliz.IDN_ALLOW_UNASSIGNED : 0) |
- (UseStd3AsciiRules ? Interop.Normaliz.IDN_USE_STD3_ASCII_RULES : 0);
- return (uint)flags;
- }
- }
-
- [DoesNotReturn]
- private static void ThrowForZeroLength(bool unicode)
- {
- int lastError = Marshal.GetLastWin32Error();
-
- throw new ArgumentException(
- lastError == Interop.Errors.ERROR_INVALID_NAME ? SR.Argument_IdnIllegalName :
- (unicode ? SR.Argument_InvalidCharSequenceNoIndex : SR.Argument_IdnBadPunycode),
- unicode ? "unicode" : "ascii");
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
deleted file mode 100644
index 2035932a82e..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
+++ /dev/null
@@ -1,871 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// This file contains the IDN functions and implementation.
-//
-// This allows encoding of non-ASCII domain names in a "punycode" form,
-// for example:
-//
-// \u5B89\u5BA4\u5948\u7F8E\u6075-with-SUPER-MONKEYS
-//
-// is encoded as:
-//
-// xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n
-//
-// Additional options are provided to allow unassigned IDN characters and
-// to validate according to the Std3ASCII Rules (like DNS names).
-//
-// There are also rules regarding bidirectionality of text and the length
-// of segments.
-//
-// For additional rules see also:
-// RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
-// RFC 3491 - Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN)
-// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
-
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Text;
-
-namespace System.Globalization
-{
- // IdnMapping class used to map names to Punycode
- public sealed partial class IdnMapping
- {
- private bool _allowUnassigned;
- private bool _useStd3AsciiRules;
-
- public IdnMapping()
- {
- }
-
- public bool AllowUnassigned
- {
- get => _allowUnassigned;
- set => _allowUnassigned = value;
- }
-
- public bool UseStd3AsciiRules
- {
- get => _useStd3AsciiRules;
- set => _useStd3AsciiRules = value;
- }
-
- // Gets ASCII (Punycode) version of the string
- public string GetAscii(string unicode) =>
- GetAscii(unicode, 0);
-
- public string GetAscii(string unicode, int index)
- {
- if (unicode == null)
- throw new ArgumentNullException(nameof(unicode));
- return GetAscii(unicode, index, unicode.Length - index);
- }
-
- public string GetAscii(string unicode, int index, int count)
- {
- if (unicode == null)
- throw new ArgumentNullException(nameof(unicode));
- if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
- if (index > unicode.Length)
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- if (index > unicode.Length - count)
- throw new ArgumentOutOfRangeException(nameof(unicode), SR.ArgumentOutOfRange_IndexCountBuffer);
-
- if (count == 0)
- {
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
- }
- if (unicode[index + count - 1] == 0)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, index + count - 1), nameof(unicode));
- }
-
- if (GlobalizationMode.Invariant)
- {
- return GetAsciiInvariant(unicode, index, count);
- }
-
- unsafe
- {
- fixed (char* pUnicode = unicode)
- {
- return GetAsciiCore(unicode, pUnicode + index, count);
- }
- }
- }
-
- // Gets Unicode version of the string. Normalized and limited to IDNA characters.
- public string GetUnicode(string ascii) =>
- GetUnicode(ascii, 0);
-
- public string GetUnicode(string ascii, int index)
- {
- if (ascii == null)
- throw new ArgumentNullException(nameof(ascii));
- return GetUnicode(ascii, index, ascii.Length - index);
- }
-
- public string GetUnicode(string ascii, int index, int count)
- {
- if (ascii == null)
- throw new ArgumentNullException(nameof(ascii));
- if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
- if (index > ascii.Length)
- throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
- if (index > ascii.Length - count)
- throw new ArgumentOutOfRangeException(nameof(ascii), SR.ArgumentOutOfRange_IndexCountBuffer);
-
- // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ.
- // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null.
- // The Win32 APIs fail on an embedded null, but not on a terminating null.
- if (count > 0 && ascii[index + count - 1] == (char)0)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
-
- if (GlobalizationMode.Invariant)
- {
- return GetUnicodeInvariant(ascii, index, count);
- }
-
- unsafe
- {
- fixed (char* pAscii = ascii)
- {
- return GetUnicodeCore(ascii, pAscii + index, count);
- }
- }
- }
-
- public override bool Equals(object? obj) =>
- obj is IdnMapping that &&
- _allowUnassigned == that._allowUnassigned &&
- _useStd3AsciiRules == that._useStd3AsciiRules;
-
- public override int GetHashCode() =>
- (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000);
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static unsafe string GetStringForOutput(string originalString, char* input, int inputLength, char* output, int outputLength) =>
- originalString.Length == inputLength && new ReadOnlySpan<char>(input, inputLength).SequenceEqual(new ReadOnlySpan<char>(output, outputLength)) ?
- originalString :
- new string(output, 0, outputLength);
-
- //
- // Invariant implementation
- //
-
- private const char c_delimiter = '-';
- private const string c_strAcePrefix = "xn--";
- private const int c_labelLimit = 63; // Not including dots
- private const int c_defaultNameLimit = 255; // Including dots
- private const int c_initialN = 0x80;
- private const int c_maxint = 0x7ffffff;
- private const int c_initialBias = 72;
- private const int c_punycodeBase = 36;
- private const int c_tmin = 1;
- private const int c_tmax = 26;
- private const int c_skew = 38;
- private const int c_damp = 700;
-
- // Legal "dot" separators (i.e: . in www.microsoft.com)
- private static readonly char[] s_dotSeparators = { '.', '\u3002', '\uFF0E', '\uFF61' };
-
- private string GetAsciiInvariant(string unicode, int index, int count)
- {
- if (index > 0 || count < unicode.Length)
- {
- unicode = unicode.Substring(index, count);
- }
-
- // Check for ASCII only string, which will be unchanged
- if (ValidateStd3AndAscii(unicode, UseStd3AsciiRules, true))
- {
- return unicode;
- }
-
- // Cannot be null terminated (normalization won't help us with this one, and
- // may have returned false before checking the whole string above)
- Debug.Assert(count >= 1, "[IdnMapping.GetAscii] Expected 0 length strings to fail before now.");
- if (unicode[^1] <= 0x1f)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, unicode.Length - 1), nameof(unicode));
- }
-
- // May need to check Std3 rules again for non-ascii
- if (UseStd3AsciiRules)
- {
- ValidateStd3AndAscii(unicode, true, false);
- }
-
- // Go ahead and encode it
- return PunycodeEncode(unicode);
- }
-
- // See if we're only ASCII
- private static bool ValidateStd3AndAscii(string unicode, bool bUseStd3, bool bCheckAscii)
- {
- // If its empty, then its too small
- if (unicode.Length == 0)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
-
- int iLastDot = -1;
-
- // Loop the whole string
- for (int i = 0; i < unicode.Length; i++)
- {
- // Aren't allowing control chars (or 7f, but idn tables catch that, they don't catch \0 at end though)
- if (unicode[i] <= 0x1f)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequence, i), nameof(unicode));
- }
-
- // If its Unicode or a control character, return false (non-ascii)
- if (bCheckAscii && unicode[i] >= 0x7f)
- return false;
-
- // Check for dots
- if (IsDot(unicode[i]))
- {
- // Can't have 2 dots in a row
- if (i == iLastDot + 1)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
-
- // If its too far between dots then fail
- if (i - iLastDot > c_labelLimit + 1)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
-
- // If validating Std3, then char before dot can't be - char
- if (bUseStd3 && i > 0)
- ValidateStd3(unicode[i - 1], true);
-
- // Remember where the last dot is
- iLastDot = i;
- continue;
- }
-
- // If necessary, make sure its a valid std3 character
- if (bUseStd3)
- {
- ValidateStd3(unicode[i], i == iLastDot + 1);
- }
- }
-
- // If we never had a dot, then we need to be shorter than the label limit
- if (iLastDot == -1 && unicode.Length > c_labelLimit)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
-
- // Need to validate entire string length, 1 shorter if last char wasn't a dot
- if (unicode.Length > c_defaultNameLimit - (IsDot(unicode[^1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
- c_defaultNameLimit - (IsDot(unicode[^1]) ? 0 : 1)), nameof(unicode));
-
- // If last char wasn't a dot we need to check for trailing -
- if (bUseStd3 && !IsDot(unicode[^1]))
- ValidateStd3(unicode[^1], true);
-
- return true;
- }
-
- /* PunycodeEncode() converts Unicode to Punycode. The input */
- /* is represented as an array of Unicode code points (not code */
- /* units; surrogate pairs are not allowed), and the output */
- /* will be represented as an array of ASCII code points. The */
- /* output string is *not* null-terminated; it will contain */
- /* zeros if and only if the input contains zeros. (Of course */
- /* the caller can leave room for a terminator and add one if */
- /* needed.) The input_length is the number of code points in */
- /* the input. The output_length is an in/out argument: the */
- /* caller passes in the maximum number of code points that it */
-
- /* can receive, and on successful return it will contain the */
- /* number of code points actually output. The case_flags array */
- /* holds input_length boolean values, where nonzero suggests that */
- /* the corresponding Unicode character be forced to uppercase */
- /* after being decoded (if possible), and zero suggests that */
- /* it be forced to lowercase (if possible). ASCII code points */
- /* are encoded literally, except that ASCII letters are forced */
- /* to uppercase or lowercase according to the corresponding */
- /* uppercase flags. If case_flags is a null pointer then ASCII */
- /* letters are left as they are, and other code points are */
- /* treated as if their uppercase flags were zero. The return */
- /* value can be any of the punycode_status values defined above */
- /* except punycode_bad_input; if not punycode_success, then */
- /* output_size and output might contain garbage. */
- private static string PunycodeEncode(string unicode)
- {
- // 0 length strings aren't allowed
- if (unicode.Length == 0)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
-
- StringBuilder output = new StringBuilder(unicode.Length);
- int iNextDot = 0;
- int iAfterLastDot = 0;
- int iOutputAfterLastDot = 0;
-
- // Find the next dot
- while (iNextDot < unicode.Length)
- {
- // Find end of this segment
- iNextDot = unicode.IndexOfAny(s_dotSeparators, iAfterLastDot);
- Debug.Assert(iNextDot <= unicode.Length, "[IdnMapping.punycode_encode]IndexOfAny is broken");
- if (iNextDot < 0)
- iNextDot = unicode.Length;
-
- // Only allowed to have empty . section at end (www.microsoft.com.)
- if (iNextDot == iAfterLastDot)
- {
- // Only allowed to have empty sections as trailing .
- if (iNextDot != unicode.Length)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
- // Last dot, stop
- break;
- }
-
- // We'll need an Ace prefix
- output.Append(c_strAcePrefix);
-
- // Everything resets every segment.
- bool bRightToLeft = false;
-
- // Check for RTL. If right-to-left, then 1st & last chars must be RTL
- BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(unicode, iAfterLastDot);
- if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)
- {
- // It has to be right to left.
- bRightToLeft = true;
-
- // Check last char
- int iTest = iNextDot - 1;
- if (char.IsLowSurrogate(unicode, iTest))
- {
- iTest--;
- }
-
- eBidi = CharUnicodeInfo.GetBidiCategory(unicode, iTest);
- if (eBidi != BidiCategory.RightToLeft && eBidi != BidiCategory.RightToLeftArabic)
- {
- // Oops, last wasn't RTL, last should be RTL if first is RTL
- throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(unicode));
- }
- }
-
- // Handle the basic code points
- int basicCount;
- int numProcessed = 0; // Num code points that have been processed so far (this segment)
- for (basicCount = iAfterLastDot; basicCount < iNextDot; basicCount++)
- {
- // Can't be lonely surrogate because it would've thrown in normalization
- Debug.Assert(!char.IsLowSurrogate(unicode, basicCount), "[IdnMapping.punycode_encode]Unexpected low surrogate");
-
- // Double check our bidi rules
- BidiCategory testBidi = CharUnicodeInfo.GetBidiCategory(unicode, basicCount);
-
- // If we're RTL, we can't have LTR chars
- if (bRightToLeft && testBidi == BidiCategory.LeftToRight)
- {
- // Oops, throw error
- throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(unicode));
- }
-
- // If we're not RTL we can't have RTL chars
- if (!bRightToLeft && (testBidi == BidiCategory.RightToLeft || testBidi == BidiCategory.RightToLeftArabic))
- {
- // Oops, throw error
- throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(unicode));
- }
-
- // If its basic then add it
- if (Basic(unicode[basicCount]))
- {
- output.Append(EncodeBasic(unicode[basicCount]));
- numProcessed++;
- }
- // If its a surrogate, skip the next since our bidi category tester doesn't handle it.
- else if (char.IsSurrogatePair(unicode, basicCount))
- basicCount++;
- }
-
- int numBasicCodePoints = numProcessed; // number of basic code points
-
- // Stop if we ONLY had basic code points
- if (numBasicCodePoints == iNextDot - iAfterLastDot)
- {
- // Get rid of xn-- and this segments done
- output.Remove(iOutputAfterLastDot, c_strAcePrefix.Length);
- }
- else
- {
- // If it has some non-basic code points the input cannot start with xn--
- if (unicode.Length - iAfterLastDot >= c_strAcePrefix.Length &&
- unicode.Substring(iAfterLastDot, c_strAcePrefix.Length).Equals(
- c_strAcePrefix, StringComparison.OrdinalIgnoreCase))
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(unicode));
-
- // Need to do ACE encoding
- int numSurrogatePairs = 0; // number of surrogate pairs so far
-
- // Add a delimiter (-) if we had any basic code points (between basic and encoded pieces)
- if (numBasicCodePoints > 0)
- {
- output.Append(c_delimiter);
- }
-
- // Initialize the state
- int n = c_initialN;
- int delta = 0;
- int bias = c_initialBias;
-
- // Main loop
- while (numProcessed < (iNextDot - iAfterLastDot))
- {
- /* All non-basic code points < n have been */
- /* handled already. Find the next larger one: */
- int j;
- int m;
- int test = 0;
- for (m = c_maxint, j = iAfterLastDot;
- j < iNextDot;
- j += IsSupplementary(test) ? 2 : 1)
- {
- test = char.ConvertToUtf32(unicode, j);
- if (test >= n && test < m) m = test;
- }
-
- /* Increase delta enough to advance the decoder's */
- /* <n,i> state to <m,0>, but guard against overflow: */
- delta += (int)((m - n) * ((numProcessed - numSurrogatePairs) + 1));
- Debug.Assert(delta > 0, "[IdnMapping.cs]1 punycode_encode - delta overflowed int");
- n = m;
-
- for (j = iAfterLastDot; j < iNextDot; j += IsSupplementary(test) ? 2 : 1)
- {
- // Make sure we're aware of surrogates
- test = char.ConvertToUtf32(unicode, j);
-
- // Adjust for character position (only the chars in our string already, some
- // haven't been processed.
-
- if (test < n)
- {
- delta++;
- Debug.Assert(delta > 0, "[IdnMapping.cs]2 punycode_encode - delta overflowed int");
- }
-
- if (test == n)
- {
- // Represent delta as a generalized variable-length integer:
- int q, k;
- for (q = delta, k = c_punycodeBase; ; k += c_punycodeBase)
- {
- int t = k <= bias ? c_tmin : k >= bias + c_tmax ? c_tmax : k - bias;
- if (q < t) break;
- Debug.Assert(c_punycodeBase != t, "[IdnMapping.punycode_encode]Expected c_punycodeBase (36) to be != t");
- output.Append(EncodeDigit(t + (q - t) % (c_punycodeBase - t)));
- q = (q - t) / (c_punycodeBase - t);
- }
-
- output.Append(EncodeDigit(q));
- bias = Adapt(delta, (numProcessed - numSurrogatePairs) + 1, numProcessed == numBasicCodePoints);
- delta = 0;
- numProcessed++;
-
- if (IsSupplementary(m))
- {
- numProcessed++;
- numSurrogatePairs++;
- }
- }
- }
- ++delta;
- ++n;
- Debug.Assert(delta > 0, "[IdnMapping.cs]3 punycode_encode - delta overflowed int");
- }
- }
-
- // Make sure its not too big
- if (output.Length - iOutputAfterLastDot > c_labelLimit)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(unicode));
-
- // Done with this segment, add dot if necessary
- if (iNextDot != unicode.Length)
- output.Append('.');
-
- iAfterLastDot = iNextDot + 1;
- iOutputAfterLastDot = output.Length;
- }
-
- // Throw if we're too long
- if (output.Length > c_defaultNameLimit - (IsDot(unicode[^1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
- c_defaultNameLimit - (IsDot(unicode[^1]) ? 0 : 1)), nameof(unicode));
- // Return our output string
- return output.ToString();
- }
-
- // Is it a dot?
- // are we U+002E (., full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), or
- // U+FF61 (halfwidth ideographic full stop).
- // Note: IDNA Normalization gets rid of dots now, but testing for last dot is before normalization
- private static bool IsDot(char c) =>
- c == '.' || c == '\u3002' || c == '\uFF0E' || c == '\uFF61';
-
- private static bool IsSupplementary(int cTest) =>
- cTest >= 0x10000;
-
- private static bool Basic(uint cp) =>
- // Is it in ASCII range?
- cp < 0x80;
-
- // Validate Std3 rules for a character
- private static void ValidateStd3(char c, bool bNextToDot)
- {
- // Check for illegal characters
- if (c <= ',' || c == '/' || (c >= ':' && c <= '@') || // Lots of characters not allowed
- (c >= '[' && c <= '`') || (c >= '{' && c <= (char)0x7F) ||
- (c == '-' && bNextToDot))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadStd3, c), nameof(c));
- }
-
- private string GetUnicodeInvariant(string ascii, int index, int count)
- {
- if (index > 0 || count < ascii.Length)
- {
- // We're only using part of the string
- ascii = ascii.Substring(index, count);
- }
- // Convert Punycode to Unicode
- string strUnicode = PunycodeDecode(ascii);
-
- // Output name MUST obey IDNA rules & round trip (casing differences are allowed)
- if (!ascii.Equals(GetAscii(strUnicode), StringComparison.OrdinalIgnoreCase))
- throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(ascii));
-
- return strUnicode;
- }
-
- /* PunycodeDecode() converts Punycode to Unicode. The input is */
- /* represented as an array of ASCII code points, and the output */
- /* will be represented as an array of Unicode code points. The */
- /* input_length is the number of code points in the input. The */
- /* output_length is an in/out argument: the caller passes in */
- /* the maximum number of code points that it can receive, and */
- /* on successful return it will contain the actual number of */
- /* code points output. The case_flags array needs room for at */
- /* least output_length values, or it can be a null pointer if the */
- /* case information is not needed. A nonzero flag suggests that */
- /* the corresponding Unicode character be forced to uppercase */
- /* by the caller (if possible), while zero suggests that it be */
- /* forced to lowercase (if possible). ASCII code points are */
- /* output already in the proper case, but their flags will be set */
- /* appropriately so that applying the flags would be harmless. */
- /* The return value can be any of the punycode_status values */
- /* defined above; if not punycode_success, then output_length, */
- /* output, and case_flags might contain garbage. On success, the */
- /* decoder will never need to write an output_length greater than */
- /* input_length, because of how the encoding is defined. */
-
- private static string PunycodeDecode(string ascii)
- {
- // 0 length strings aren't allowed
- if (ascii.Length == 0)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(ascii));
-
- // Throw if we're too long
- if (ascii.Length > c_defaultNameLimit - (IsDot(ascii[^1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
- c_defaultNameLimit - (IsDot(ascii[^1]) ? 0 : 1)), nameof(ascii));
-
- // output stringbuilder
- StringBuilder output = new StringBuilder(ascii.Length);
-
- // Dot searching
- int iNextDot = 0;
- int iAfterLastDot = 0;
- int iOutputAfterLastDot = 0;
-
- while (iNextDot < ascii.Length)
- {
- // Find end of this segment
- iNextDot = ascii.IndexOf('.', iAfterLastDot);
- if (iNextDot < 0 || iNextDot > ascii.Length)
- iNextDot = ascii.Length;
-
- // Only allowed to have empty . section at end (www.microsoft.com.)
- if (iNextDot == iAfterLastDot)
- {
- // Only allowed to have empty sections as trailing .
- if (iNextDot != ascii.Length)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(ascii));
-
- // Last dot, stop
- break;
- }
-
- // In either case it can't be bigger than segment size
- if (iNextDot - iAfterLastDot > c_labelLimit)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(ascii));
-
- // See if this section's ASCII or ACE
- if (ascii.Length < c_strAcePrefix.Length + iAfterLastDot ||
- string.Compare(ascii, iAfterLastDot, c_strAcePrefix, 0, c_strAcePrefix.Length, StringComparison.OrdinalIgnoreCase) != 0)
- {
- // Its ASCII, copy it
- output.Append(ascii, iAfterLastDot, iNextDot - iAfterLastDot);
- }
- else
- {
- // Not ASCII, bump up iAfterLastDot to be after ACE Prefix
- iAfterLastDot += c_strAcePrefix.Length;
-
- // Get number of basic code points (where delimiter is)
- // numBasicCodePoints < 0 if there're no basic code points
- int iTemp = ascii.LastIndexOf(c_delimiter, iNextDot - 1);
-
- // Trailing - not allowed
- if (iTemp == iNextDot - 1)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
-
- int numBasicCodePoints;
- if (iTemp <= iAfterLastDot)
- numBasicCodePoints = 0;
- else
- {
- numBasicCodePoints = iTemp - iAfterLastDot;
-
- // Copy all the basic code points, making sure they're all in the allowed range,
- // and losing the casing for all of them.
- for (int copyAscii = iAfterLastDot; copyAscii < iAfterLastDot + numBasicCodePoints; copyAscii++)
- {
- // Make sure we don't allow unicode in the ascii part
- if (ascii[copyAscii] > 0x7f)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
-
- // When appending make sure they get lower cased
- output.Append((char)(ascii[copyAscii] >= 'A' && ascii[copyAscii] <= 'Z' ? ascii[copyAscii] - 'A' + 'a' : ascii[copyAscii]));
- }
- }
-
- // Get ready for main loop. Start at beginning if we didn't have any
- // basic code points, otherwise start after the -.
- // asciiIndex will be next character to read from ascii
- int asciiIndex = iAfterLastDot + (numBasicCodePoints > 0 ? numBasicCodePoints + 1 : 0);
-
- // initialize our state
- int n = c_initialN;
- int bias = c_initialBias;
- int i = 0;
-
- int w, k;
-
- // no Supplementary characters yet
- int numSurrogatePairs = 0;
-
- // Main loop, read rest of ascii
- while (asciiIndex < iNextDot)
- {
- /* Decode a generalized variable-length integer into delta, */
- /* which gets added to i. The overflow checking is easier */
- /* if we increase i as we go, then subtract off its starting */
- /* value at the end to obtain delta. */
- int oldi = i;
-
- for (w = 1, k = c_punycodeBase; ; k += c_punycodeBase)
- {
- // Check to make sure we aren't overrunning our ascii string
- if (asciiIndex >= iNextDot)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
-
- // decode the digit from the next char
- int digit = DecodeDigit(ascii[asciiIndex++]);
-
- Debug.Assert(w > 0, "[IdnMapping.punycode_decode]Expected w > 0");
- if (digit > (c_maxint - i) / w)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
-
- i += (int)(digit * w);
- int t = k <= bias ? c_tmin : k >= bias + c_tmax ? c_tmax : k - bias;
- if (digit < t)
- break;
- Debug.Assert(c_punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != c_punycodeBase (36)");
- if (w > c_maxint / (c_punycodeBase - t))
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
- w *= (c_punycodeBase - t);
- }
-
- bias = Adapt(i - oldi, (output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1, oldi == 0);
-
- /* i was supposed to wrap around from output.Length to 0, */
- /* incrementing n each time, so we'll fix that now: */
- Debug.Assert((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1 > 0,
- "[IdnMapping.punycode_decode]Expected to have added > 0 characters this segment");
- if (i / ((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1) > c_maxint - n)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
- n += (int)(i / (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1));
- i %= (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1);
-
- // Make sure n is legal
- if (n < 0 || n > 0x10ffff || (n >= 0xD800 && n <= 0xDFFF))
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
-
- // insert n at position i of the output: Really tricky if we have surrogates
- int iUseInsertLocation;
- string strTemp = char.ConvertFromUtf32(n);
-
- // If we have supplimentary characters
- if (numSurrogatePairs > 0)
- {
- // Hard way, we have supplimentary characters
- int iCount;
- for (iCount = i, iUseInsertLocation = iOutputAfterLastDot; iCount > 0; iCount--, iUseInsertLocation++)
- {
- // If its a surrogate, we have to go one more
- if (iUseInsertLocation >= output.Length)
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
- if (char.IsSurrogate(output[iUseInsertLocation]))
- iUseInsertLocation++;
- }
- }
- else
- {
- // No Supplementary chars yet, just add i
- iUseInsertLocation = iOutputAfterLastDot + i;
- }
-
- // Insert it
- output.Insert(iUseInsertLocation, strTemp);
-
- // If it was a surrogate increment our counter
- if (IsSupplementary(n))
- numSurrogatePairs++;
-
- // Index gets updated
- i++;
- }
-
- // Do BIDI testing
- bool bRightToLeft = false;
-
- // Check for RTL. If right-to-left, then 1st & last chars must be RTL
- BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output, iOutputAfterLastDot);
- if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)
- {
- // It has to be right to left.
- bRightToLeft = true;
- }
-
- // Check the rest of them to make sure RTL/LTR is consistent
- for (int iTest = iOutputAfterLastDot; iTest < output.Length; iTest++)
- {
- // This might happen if we run into a pair
- if (char.IsLowSurrogate(output[iTest]))
- continue;
-
- // Check to see if its LTR
- eBidi = CharUnicodeInfo.GetBidiCategory(output, iTest);
- if ((bRightToLeft && eBidi == BidiCategory.LeftToRight) ||
- (!bRightToLeft && (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)))
- throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(ascii));
- }
-
- // Its also a requirement that the last one be RTL if 1st is RTL
- if (bRightToLeft && eBidi != BidiCategory.RightToLeft && eBidi != BidiCategory.RightToLeftArabic)
- {
- // Oops, last wasn't RTL, last should be RTL if first is RTL
- throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(ascii));
- }
- }
-
- // See if this label was too long
- if (iNextDot - iAfterLastDot > c_labelLimit)
- throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(ascii));
-
- // Done with this segment, add dot if necessary
- if (iNextDot != ascii.Length)
- output.Append('.');
-
- iAfterLastDot = iNextDot + 1;
- iOutputAfterLastDot = output.Length;
- }
-
- // Throw if we're too long
- if (output.Length > c_defaultNameLimit - (IsDot(output[output.Length - 1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize, c_defaultNameLimit - (IsDot(output[output.Length - 1]) ? 0 : 1)), nameof(ascii));
-
- // Return our output string
- return output.ToString();
- }
-
- // DecodeDigit(cp) returns the numeric value of a basic code */
- // point (for use in representing integers) in the range 0 to */
- // c_punycodeBase-1, or <0 if cp is does not represent a value. */
-
- private static int DecodeDigit(char cp)
- {
- if (cp >= '0' && cp <= '9')
- return cp - '0' + 26;
-
- // Two flavors for case differences
- if (cp >= 'a' && cp <= 'z')
- return cp - 'a';
-
- if (cp >= 'A' && cp <= 'Z')
- return cp - 'A';
-
- // Expected 0-9, A-Z or a-z, everything else is illegal
- throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(cp));
- }
-
- private static int Adapt(int delta, int numpoints, bool firsttime)
- {
- uint k;
-
- delta = firsttime ? delta / c_damp : delta / 2;
- Debug.Assert(numpoints != 0, "[IdnMapping.adapt]Expected non-zero numpoints.");
- delta += delta / numpoints;
-
- for (k = 0; delta > ((c_punycodeBase - c_tmin) * c_tmax) / 2; k += c_punycodeBase)
- {
- delta /= c_punycodeBase - c_tmin;
- }
-
- Debug.Assert(delta + c_skew != 0, "[IdnMapping.adapt]Expected non-zero delta+skew.");
- return (int)(k + (c_punycodeBase - c_tmin + 1) * delta / (delta + c_skew));
- }
-
- /* EncodeBasic(bcp,flag) forces a basic code point to lowercase */
- /* if flag is false, uppercase if flag is true, and returns */
- /* the resulting code point. The code point is unchanged if it */
- /* is caseless. The behavior is undefined if bcp is not a basic */
- /* code point. */
-
- private static char EncodeBasic(char bcp)
- {
- if (HasUpperCaseFlag(bcp))
- bcp += (char)('a' - 'A');
-
- return bcp;
- }
-
- // Return whether a punycode code point is flagged as being upper case.
- private static bool HasUpperCaseFlag(char punychar) =>
- punychar >= 'A' && punychar <= 'Z';
-
- /* EncodeDigit(d,flag) returns the basic code point whose value */
- /* (when used for representing integers) is d, which needs to be in */
- /* the range 0 to punycodeBase-1. The lowercase form is used unless flag is */
- /* true, in which case the uppercase form is used. */
-
- private static char EncodeDigit(int d)
- {
- Debug.Assert(d >= 0 && d < c_punycodeBase, "[IdnMapping.encode_digit]Expected 0 <= d < punycodeBase");
- // 26-35 map to ASCII 0-9
- if (d > 25) return (char)(d - 26 + '0');
-
- // 0-25 map to a-z or A-Z
- return (char)(d + 'a');
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
deleted file mode 100644
index c49b34accd7..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- internal static class InternalGlobalizationHelper
- {
- // Copied from the TimeSpan to be used inside the globalization code and avoid internal dependency on TimeSpan class
- internal static long TimeToTicks(int hour, int minute, int second)
- {
- // totalSeconds is bounded by 2^31 * 2^12 + 2^31 * 2^8 + 2^31,
- // which is less than 2^44, meaning we won't overflow totalSeconds.
- long totalSeconds = (long)hour * 3600 + (long)minute * 60 + (long)second;
- if (totalSeconds > MaxSeconds || totalSeconds < MinSeconds)
- throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
- return totalSeconds * TicksPerSecond;
- }
-
-
- //
- // Define needed constants so globalization code can be independant from any other types
- //
-
- internal const long TicksPerMillisecond = 10000;
- internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
- internal const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
- internal const long MaxSeconds = long.MaxValue / TicksPerSecond;
- internal const long MinSeconds = long.MinValue / TicksPerSecond;
- private const int DaysPerYear = 365;
- private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
- private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
- private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097
- private const int DaysTo10000 = DaysPer400Years * 25 - 366; // 3652059
- private const long TicksPerMinute = TicksPerSecond * 60;
- private const long TicksPerHour = TicksPerMinute * 60;
- private const long TicksPerDay = TicksPerHour * 24;
- internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
- internal const long MinTicks = 0;
- internal const long MaxMilliSeconds = long.MaxValue / TicksPerMillisecond;
- internal const long MinMilliSeconds = long.MinValue / TicksPerMillisecond;
-
- internal const int StringBuilderDefaultCapacity = 16;
-
- internal const long MaxOffset = TimeSpan.TicksPerHour * 14;
- internal const long MinOffset = -MaxOffset;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Unix.cs
deleted file mode 100644
index 0bbebba7742..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Unix.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- public partial class JapaneseCalendar : Calendar
- {
- private static EraInfo[]? GetJapaneseEras()
- {
- if (GlobalizationMode.Invariant)
- {
- return null;
- }
-
- string[]? eraNames;
- if (!CalendarData.EnumCalendarInfo("ja-JP", CalendarId.JAPAN, CalendarDataType.EraNames, out eraNames))
- {
- return null;
- }
-
- string[]? abbrevEnglishEraNames;
- if (!CalendarData.EnumCalendarInfo("en", CalendarId.JAPAN, CalendarDataType.AbbrevEraNames, out abbrevEnglishEraNames))
- {
- return null;
- }
-
- List<EraInfo> eras = new List<EraInfo>();
- int lastMaxYear = GregorianCalendar.MaxYear;
-
- int latestEra = Interop.Globalization.GetLatestJapaneseEra();
- for (int i = latestEra; i >= 0; i--)
- {
- DateTime dt;
- if (!GetJapaneseEraStartDate(i, out dt))
- {
- return null;
- }
-
- if (dt < s_calendarMinValue)
- {
- // only populate the Eras that are valid JapaneseCalendar date times
- break;
- }
-
- eras.Add(new EraInfo(i, dt.Year, dt.Month, dt.Day, dt.Year - 1, 1, lastMaxYear - dt.Year + 1,
- eraNames![i], GetAbbreviatedEraName(eraNames, i), abbrevEnglishEraNames![i]));
-
- lastMaxYear = dt.Year;
- }
-
- // remap the Era numbers, now that we know how many there will be
- for (int i = 0; i < eras.Count; i++)
- {
- eras[i].era = eras.Count - i;
- }
-
- return eras.ToArray();
- }
-
- // PAL Layer ends here
-
- private static string GetAbbreviatedEraName(string[] eraNames, int eraIndex)
- {
- // This matches the behavior on Win32 - only returning the first character of the era name.
- // See Calendar.EraAsString(Int32) - https://msdn.microsoft.com/en-us/library/windows/apps/br206751.aspx
- return eraNames[eraIndex].Substring(0, 1);
- }
-
- private static bool GetJapaneseEraStartDate(int era, out DateTime dateTime)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- dateTime = default(DateTime);
-
- int startYear;
- int startMonth;
- int startDay;
- bool result = Interop.Globalization.GetJapaneseEraStartDate(
- era,
- out startYear,
- out startMonth,
- out startDay);
-
- if (result)
- {
- dateTime = new DateTime(startYear, startMonth, startDay);
- }
-
- return result;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
deleted file mode 100644
index e70dc510804..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Internal.Win32;
-
-namespace System.Globalization
-{
- public partial class JapaneseCalendar : Calendar
- {
- private const string JapaneseErasHive = @"System\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras";
-
- // We know about 5 built-in eras, however users may add additional era(s) from the
- // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
- //
- // Registry values look like:
- // yyyy.mm.dd=era_abbrev_english_englishabbrev
- //
- // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
- // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
- // era is the Japanese Era name
- // abbrev is the Abbreviated Japanese Era Name
- // english is the English name for the Era (unused)
- // englishabbrev is the Abbreviated English name for the era.
- // . is a delimiter, but the value of . doesn't matter.
- // '_' marks the space between the japanese era name, japanese abbreviated era name
- // english name, and abbreviated english names.
- private static EraInfo[]? GetJapaneseEras()
- {
- // Look in the registry key and see if we can find any ranges
- int iFoundEras = 0;
- EraInfo[]? registryEraRanges = null;
-
- try
- {
- // Need to access registry
- using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(JapaneseErasHive))
- {
- // Abort if we didn't find anything
- if (key == null) return null;
-
- // Look up the values in our reg key
- string[] valueNames = key.GetValueNames();
- if (valueNames != null && valueNames.Length > 0)
- {
- registryEraRanges = new EraInfo[valueNames.Length];
-
- // Loop through the registry and read in all the values
- for (int i = 0; i < valueNames.Length; i++)
- {
- // See if the era is a valid date
- EraInfo? era = GetEraFromValue(valueNames[i], key.GetValue(valueNames[i])?.ToString());
-
- // continue if not valid
- if (era == null) continue;
-
- // Remember we found one.
- registryEraRanges[iFoundEras] = era;
- iFoundEras++;
- }
- }
- }
- }
- catch (System.Security.SecurityException)
- {
- // If we weren't allowed to read, then just ignore the error
- return null;
- }
- catch (System.IO.IOException)
- {
- // If key is being deleted just ignore the error
- return null;
- }
- catch (System.UnauthorizedAccessException)
- {
- // Registry access rights permissions, just ignore the error
- return null;
- }
-
- //
- // If we didn't have valid eras, then fail
- // should have at least 5 eras
- //
- if (iFoundEras < 5) return null;
-
- //
- // Now we have eras, clean them up.
- //
- // Clean up array length
- Array.Resize(ref registryEraRanges, iFoundEras);
-
- // Sort them
- Array.Sort(registryEraRanges, CompareEraRanges);
-
- // Clean up era information
- for (int i = 0; i < registryEraRanges.Length; i++)
- {
- // eras count backwards from length to 1 (and are 1 based indexes into string arrays)
- registryEraRanges[i].era = registryEraRanges.Length - i;
-
- // update max era year
- if (i == 0)
- {
- // First range is 'til the end of the calendar
- registryEraRanges[0].maxEraYear = GregorianCalendar.MaxYear - registryEraRanges[0].yearOffset;
- }
- else
- {
- // Rest are until the next era (remember most recent era is first in array)
- registryEraRanges[i].maxEraYear = registryEraRanges[i - 1].yearOffset + 1 - registryEraRanges[i].yearOffset;
- }
- }
-
- // Return our ranges
- return registryEraRanges;
- }
-
- //
- // Compare two era ranges, eg just the ticks
- // Remember the era array is supposed to be in reverse chronological order
- //
- private static int CompareEraRanges(EraInfo a, EraInfo b)
- {
- return b.ticks.CompareTo(a.ticks);
- }
-
- //
- // GetEraFromValue
- //
- // Parse the registry value name/data pair into an era
- //
- // Registry values look like:
- // yyyy.mm.dd=era_abbrev_english_englishabbrev
- //
- // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
- // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
- // era is the Japanese Era name
- // abbrev is the Abbreviated Japanese Era Name
- // english is the English name for the Era (unused)
- // englishabbrev is the Abbreviated English name for the era.
- // . is a delimiter, but the value of . doesn't matter.
- // '_' marks the space between the japanese era name, japanese abbreviated era name
- // english name, and abbreviated english names.
- private static EraInfo? GetEraFromValue(string? value, string? data)
- {
- // Need inputs
- if (value == null || data == null) return null;
-
- //
- // Get Date
- //
- // Need exactly 10 characters in name for date
- // yyyy.mm.dd although the . can be any character
- if (value.Length != 10) return null;
-
- int year;
- int month;
- int day;
-
- ReadOnlySpan<char> valueSpan = value.AsSpan();
- if (!int.TryParse(valueSpan.Slice(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
- !int.TryParse(valueSpan.Slice(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
- !int.TryParse(valueSpan.Slice(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
- {
- // Couldn't convert integer, fail
- return null;
- }
-
- //
- // Get Strings
- //
- // Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups)
- string[] names = data.Split('_');
-
- // Should have exactly 4 parts
- // 0 - Era Name
- // 1 - Abbreviated Era Name
- // 2 - English Era Name
- // 3 - Abbreviated English Era Name
- if (names.Length != 4) return null;
-
- // Each part should have data in it
- if (names[0].Length == 0 ||
- names[1].Length == 0 ||
- names[2].Length == 0 ||
- names[3].Length == 0)
- return null;
-
- //
- // Now we have an era we can build
- // Note that the era # and max era year need cleaned up after sorting
- // Don't use the full English Era Name (names[2])
- //
- return new EraInfo(0, year, month, day, year - 1, 1, 0,
- names[0], names[1], names[3]);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
deleted file mode 100644
index eae8fa0bc87..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
+++ /dev/null
@@ -1,294 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <summary>
- /// JapaneseCalendar is based on Gregorian calendar. The month and day values are the same as
- /// Gregorian calendar. However, the year value is an offset to the Gregorian
- /// year based on the era.
- ///
- /// This system is adopted by Emperor Meiji in 1868. The year value is counted based on the reign of an emperor,
- /// and the era begins on the day an emperor ascends the throne and continues until his death or his abdication.
- /// The era changes at 12:00AM.
- ///
- /// For example, the current era is Reiwa. It started on 2019/5/1 A.D. Therefore, Gregorian year 2019 is also Reiwa 1st.
- /// 2019/5/1 A.D. is also Reiwa 1st 5/1.
- ///
- /// Any date in the year during which era is changed can be reckoned in either era. For example,
- /// 2019/1/1 can be 1/1 Reiwa 1st year or 1/1 Heisei 31st year.
- ///
- /// Note:
- /// The DateTime can be represented by the JapaneseCalendar are limited to two factors:
- /// 1. The min value and max value of DateTime class.
- /// 2. The available era information.
- /// </summary>
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1868/09/08 9999/12/31
- /// Japanese Meiji 01/01 Reiwa 7981/12/31
- /// </remarks>
- public partial class JapaneseCalendar : Calendar
- {
- private static readonly DateTime s_calendarMinValue = new DateTime(1868, 9, 8);
-
- public override DateTime MinSupportedDateTime => s_calendarMinValue;
-
- public override DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- // Using a field initializer rather than a static constructor so that the whole class can be lazy
- // init.
- private static volatile EraInfo[]? s_japaneseEraInfo;
-
- // m_EraInfo must be listed in reverse chronological order. The most recent era
- // should be the first element.
- // That is, m_EraInfo[0] contains the most recent era.
- //
- // We know about 4 built-in eras, however users may add additional era(s) from the
- // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
- // we don't read the registry and instead we call WinRT to get the needed informatio
- //
- // Registry values look like:
- // yyyy.mm.dd=era_abbrev_english_englishabbrev
- //
- // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
- // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
- // era is the Japanese Era name
- // abbrev is the Abbreviated Japanese Era Name
- // english is the English name for the Era (unused)
- // englishabbrev is the Abbreviated English name for the era.
- // . is a delimiter, but the value of . doesn't matter.
- // '_' marks the space between the japanese era name, japanese abbreviated era name
- // english name, and abbreviated english names.
- internal static EraInfo[] GetEraInfo()
- {
- // See if we need to build it
- return s_japaneseEraInfo ??
- (s_japaneseEraInfo = GetJapaneseEras()) ??
- // See if we have to use the built-in eras
- (s_japaneseEraInfo = new EraInfo[]
- {
- new EraInfo(5, 2019, 5, 1, 2018, 1, GregorianCalendar.MaxYear - 2018, "\x4ee4\x548c", "\x4ee4", "R"),
- new EraInfo(4, 1989, 1, 8, 1988, 1, 2019 - 1988, "\x5e73\x6210", "\x5e73", "H"),
- new EraInfo(3, 1926, 12, 25, 1925, 1, 1989 - 1925, "\x662d\x548c", "\x662d", "S"),
- new EraInfo(2, 1912, 7, 30, 1911, 1, 1926 - 1911, "\x5927\x6b63", "\x5927", "T"),
- new EraInfo(1, 1868, 1, 1, 1867, 1, 1912 - 1867, "\x660e\x6cbb", "\x660e", "M")
- });
- }
-
- internal static volatile Calendar? s_defaultInstance;
- internal GregorianCalendarHelper _helper;
-
- internal static Calendar GetDefaultInstance() => s_defaultInstance ??= new JapaneseCalendar();
-
- public JapaneseCalendar()
- {
- try
- {
- new CultureInfo("ja-JP");
- }
- catch (ArgumentException e)
- {
- throw new TypeInitializationException(this.GetType().ToString(), e);
- }
-
- _helper = new GregorianCalendarHelper(this, GetEraInfo());
- }
-
- internal override CalendarId ID => CalendarId.JAPAN;
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- return _helper.AddMonths(time, months);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return _helper.AddYears(time, years);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- return _helper.GetDaysInMonth(year, month, era);
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- return _helper.GetDaysInYear(year, era);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return _helper.GetDayOfMonth(time);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return _helper.GetDayOfWeek(time);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return _helper.GetDayOfYear(time);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- return _helper.GetMonthsInYear(year, era);
- }
-
- public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
- {
- return _helper.GetWeekOfYear(time, rule, firstDayOfWeek);
- }
-
- public override int GetEra(DateTime time)
- {
- return _helper.GetEra(time);
- }
-
- public override int GetMonth(DateTime time)
- {
- return _helper.GetMonth(time);
- }
-
- public override int GetYear(DateTime time)
- {
- return _helper.GetYear(time);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- return _helper.IsLeapDay(year, month, day, era);
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- return _helper.IsLeapYear(year, era);
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- return _helper.GetLeapMonth(year, era);
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- return _helper.IsLeapMonth(year, month, era);
- }
-
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- return _helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era);
- }
-
- /// <summary>
- /// For Japanese calendar, four digit year is not used. Few emperors will live for more than one hundred years.
- /// Therefore, for any two digit number, we just return the original number.
- /// </summary>
- public override int ToFourDigitYear(int year)
- {
- if (year <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedPosNum);
- }
- if (year > _helper.MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, _helper.MaxYear));
- }
-
- return year;
- }
-
-
- public override int[] Eras => _helper.Eras;
-
- /// <summary>
- /// Return the various era strings
- /// Note: The arrays are backwards of the eras
- /// </summary>
- internal static string[] EraNames()
- {
- EraInfo[] eras = GetEraInfo();
- string[] eraNames = new string[eras.Length];
-
- for (int i = 0; i < eras.Length; i++)
- {
- // Strings are in chronological order, eras are backwards order.
- eraNames[i] = eras[eras.Length - i - 1].eraName!;
- }
-
- return eraNames;
- }
-
- internal static string[] AbbrevEraNames()
- {
- EraInfo[] eras = GetEraInfo();
- string[] erasAbbrev = new string[eras.Length];
-
- for (int i = 0; i < eras.Length; i++)
- {
- // Strings are in chronological order, eras are backwards order.
- erasAbbrev[i] = eras[eras.Length - i - 1].abbrevEraName!;
- }
-
- return erasAbbrev;
- }
-
- internal static string[] EnglishEraNames()
- {
- EraInfo[] eras = GetEraInfo();
- string[] erasEnglish = new string[eras.Length];
-
- for (int i = 0; i < eras.Length; i++)
- {
- // Strings are in chronological order, eras are backwards order.
- erasEnglish[i] = eras[eras.Length - i - 1].englishEraName!;
- }
-
- return erasEnglish;
- }
-
- private const int DefaultTwoDigitYearMax = 99;
-
- internal override bool IsValidYear(int year, int era)
- {
- return _helper.IsValidYear(year, era);
- }
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > _helper.MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, _helper.MaxYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
deleted file mode 100644
index 67162a8c541..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1960/01/28 2050/01/22
- /// JapaneseLunisolar 1960/01/01 2049/12/29
- /// </remarks>
- public class JapaneseLunisolarCalendar : EastAsianLunisolarCalendar
- {
- public const int JapaneseEra = 1;
-
- private readonly GregorianCalendarHelper _helper;
-
- private const int MinLunisolarYear = 1960;
- private const int MaxLunisolarYear = 2049;
-
- private static readonly DateTime s_minDate = new DateTime(1960, 1, 28);
- private static readonly DateTime s_maxDate = new DateTime((new DateTime(2050, 1, 22, 23, 59, 59, 999)).Ticks + 9999);
-
- public override DateTime MinSupportedDateTime => s_minDate;
-
- public override DateTime MaxSupportedDateTime => s_maxDate;
-
- protected override int DaysInYearBeforeMinSupportedYear =>
- // 1959 from ChineseLunisolarCalendar
- 354;
-
- // Data for years 1960-2049 matches output of Calendrical Calculations [1] and published calendar tables [2].
- // [1] Reingold, Edward M, and Nachum Dershowitz. Calendrical Calculations: The Ultimate Edition. Cambridge [etc.: Cambridge University Press, 2018. Print.
- // [2] Nishizawa, Yūsō. Rekijitsu Taikan: Meiji Kaireki 1873-Nen-2100-Nen Shinkyūreki, Kanshi Kyūsei Rokuyō Taishō. Tōkyō: Shin Jinbutsu Ōraisha, 1994. Print.
- private static readonly int[,] s_yinfo =
- {
-/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
-1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1965 */ { 00, 02, 02, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
-1966 */ { 03, 01, 22, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1968 */ { 07, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1970 */ { 00, 02, 06, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
-1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1973 */ { 00, 02, 03, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
-1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1976 */ { 08, 01, 31, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1978 */ { 00, 02, 07, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
-1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1982 */ { 04, 01, 25, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1987 */ { 06, 01, 29, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1988 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1989 */ { 00, 02, 06, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1990 */ { 05, 01, 27, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-1995 */ { 08, 01, 31, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1996 */ { 00, 02, 19, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
-1997 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1998 */ { 05, 01, 28, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-2001 */ { 04, 01, 24, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */ { 00, 02, 09, 0b0101011011000000 }, /* 29 30 29 30 29 30 30 29 30 30 29 29 354
-2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-2012 */ { 03, 01, 23, 0b1011101001010000 }, /* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
-2013 */ { 00, 02, 10, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
-2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-2017 */ { 05, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-2019 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-2020 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-2023 */ { 02, 01, 22, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */ { 00, 02, 17, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-2027 */ { 00, 02, 07, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
-2028 */ { 05, 01, 27, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-2029 */ { 00, 02, 13, 0b1101100100110000 }, /* 30 30 29 30 30 29 29 30 29 29 30 30 355
-2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-2031 */ { 03, 01, 23, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-2036 */ { 06, 01, 28, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
-2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */ { 00, 02, 12, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
-2041 */ { 00, 02, 01, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-2046 */ { 00, 02, 06, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
-2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */ { 00, 02, 14, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
- */ };
-
- internal override int MinCalendarYear => MinLunisolarYear;
-
- internal override int MaxCalendarYear => MaxLunisolarYear;
-
- internal override DateTime MinDate => s_minDate;
-
- internal override DateTime MaxDate => s_maxDate;
-
- internal override EraInfo[]? CalEraInfo => JapaneseCalendar.GetEraInfo();
-
- internal override int GetYearInfo(int lunarYear, int index)
- {
- if (lunarYear < MinLunisolarYear || lunarYear > MaxLunisolarYear)
- {
- throw new ArgumentOutOfRangeException(
- "year",
- lunarYear,
- SR.Format(SR.ArgumentOutOfRange_Range, MinLunisolarYear, MaxLunisolarYear));
- }
-
- return s_yinfo[lunarYear - MinLunisolarYear, index];
- }
-
- internal override int GetYear(int year, DateTime time)
- {
- return _helper.GetYear(year, time);
- }
-
- internal override int GetGregorianYear(int year, int era)
- {
- return _helper.GetGregorianYear(year, era);
- }
-
- /// <summary>
- /// Trim off the eras that are before our date range
- /// </summary>
- private static EraInfo[] TrimEras(EraInfo[] baseEras)
- {
- EraInfo[] newEras = new EraInfo[baseEras.Length];
- int newIndex = 0;
-
- // Eras have most recent first, so start with that
- for (int i = 0; i < baseEras.Length; i++)
- {
- // If this one's minimum year is bigger than our maximum year
- // then we can't use it.
- if (baseEras[i].yearOffset + baseEras[i].minEraYear >= MaxLunisolarYear)
- {
- // skip this one.
- continue;
- }
-
- // If this one's maximum era is less than our minimum era
- // then we've gotten too low in the era #s, so we're done
- if (baseEras[i].yearOffset + baseEras[i].maxEraYear < MinLunisolarYear)
- {
- break;
- }
-
- // Wasn't too large or too small, can use this one
- newEras[newIndex] = baseEras[i];
- newIndex++;
- }
-
- // If we didn't copy any then something was wrong, just return base
- if (newIndex == 0) return baseEras;
-
- Array.Resize(ref newEras!, newIndex);
- return newEras;
- }
-
- public JapaneseLunisolarCalendar()
- {
- _helper = new GregorianCalendarHelper(this, TrimEras(JapaneseCalendar.GetEraInfo()));
- }
-
- public override int GetEra(DateTime time) => _helper.GetEra(time);
-
- internal override CalendarId BaseCalendarID => CalendarId.JAPAN;
-
- internal override CalendarId ID => CalendarId.JAPANESELUNISOLAR;
-
- public override int[] Eras => _helper.Eras;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
deleted file mode 100644
index fca11fe43c8..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
+++ /dev/null
@@ -1,371 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class implements the Julian calendar. In 48 B.C. Julius Caesar
- /// ordered a calendar reform, and this calendar is called Julian calendar.
- /// It consisted of a solar year of twelve months and of 365 days with an
- /// extra day every fourth year.
- /// </summary>
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 0001/01/01 9999/12/31
- /// Julia 0001/01/03 9999/10/19
- /// </remarks>
- public class JulianCalendar : Calendar
- {
- public static readonly int JulianEra = 1;
-
- private const int DatePartYear = 0;
- private const int DatePartDayOfYear = 1;
- private const int DatePartMonth = 2;
- private const int DatePartDay = 3;
-
- // Number of days in a non-leap year
- private const int JulianDaysPerYear = 365;
-
- // 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;
-
- public override DateTime MinSupportedDateTime => DateTime.MinValue;
-
- public override DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- public JulianCalendar()
- {
- // There is no system setting of TwoDigitYear max, so set the value here.
- _twoDigitYearMax = 2029;
- }
-
- internal override CalendarId ID => CalendarId.JULIAN;
-
- internal static void CheckEraRange(int era)
- {
- if (era != CurrentEra && era != JulianEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- }
-
- internal void CheckYearEraRange(int year, int era)
- {
- CheckEraRange(era);
- if (year <= 0 || year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
- }
- }
-
- internal static void CheckMonthRange(int month)
- {
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
- }
-
- /// <summary>
- /// Check for if the day value is valid.
- /// </summary>
- /// <remarks>
- /// Before calling this method, call CheckYearEraRange()/CheckMonthRange() to make
- /// sure year/month values are correct.
- /// </remarks>
- internal static void CheckDayRange(int year, int month, int day)
- {
- if (year == 1 && month == 1)
- {
- // The minimum supported Julia date is Julian 0001/01/03.
- if (day < 3)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
- }
-
- bool isLeapYear = (year % 4) == 0;
- int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365;
- int monthDays = days[month] - days[month - 1];
- if (day < 1 || day > monthDays)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, monthDays));
- }
- }
-
- /// <summary>
- /// Returns a given date part of this DateTime. This method is used
- /// to compute the year, day-of-year, month, or day part.
- /// </summary>
- internal static int GetDatePart(long ticks, int part)
- {
- // Gregorian 1/1/0001 is Julian 1/3/0001. Remember DateTime(0) is refered to Gregorian 1/1/0001.
- // The following line convert Gregorian ticks to Julian ticks.
- long julianTicks = ticks + TicksPerDay * 2;
- // n = number of days since 1/1/0001
- int n = (int)(julianTicks / TicksPerDay);
- // y4 = number of whole 4-year periods within 100-year period
- int y4 = n / JulianDaysPer4Years;
- // n = day number within 4-year period
- n -= y4 * JulianDaysPer4Years;
- // y1 = number of whole years within 4-year period
- int y1 = n / JulianDaysPerYear;
- // Last year has an extra day, so decrement result if 4
- if (y1 == 4) y1 = 3;
- // If year was requested, compute and return it
- if (part == DatePartYear)
- {
- return y4 * 4 + y1 + 1;
- }
-
- // n = day number within year
- n -= y1 * JulianDaysPerYear;
- // If day-of-year was requested, return it
- if (part == DatePartDayOfYear)
- {
- return n + 1;
- }
-
- // 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;
- // All months have less than 32 days, so n >> 5 is a good conservative
- // estimate for the month
- int m = (n >> 5) + 1;
- // m = 1-based month number
- while (n >= days[m])
- {
- m++;
- }
-
- // If month was requested, return it
- if (part == DatePartMonth)
- {
- return m;
- }
-
- // Return 1-based day-of-month
- return n - days[m - 1] + 1;
- }
-
- /// <summary>
- /// Returns the tick count corresponding to the given year, month, and day.
- /// </summary>
- internal static long DateToTicks(int year, int month, int day)
- {
- int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_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.
- // Therefore, we subtract two days in the following to convert the ticks in JulianCalendar
- // to ticks in Gregorian calendar.
- return (n - 2) * TicksPerDay;
- }
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- months,
- SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
- }
-
- int y = GetDatePart(time.Ticks, DatePartYear);
- int m = GetDatePart(time.Ticks, DatePartMonth);
- int d = GetDatePart(time.Ticks, DatePartDay);
- int i = m - 1 + months;
- if (i >= 0)
- {
- m = i % 12 + 1;
- y += i / 12;
- }
- else
- {
- m = 12 + (i + 1) % 12;
- y += (i - 11) / 12;
- }
-
- int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365;
- int days = daysArray[m] - daysArray[m - 1];
- if (d > days)
- {
- d = days;
- }
-
- long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay;
- Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return new DateTime(ticks);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return AddMonths(time, years * 12);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDay);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDayOfYear);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- CheckYearEraRange(year, era);
- CheckMonthRange(month);
- int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365;
- return days[month] - days[month - 1];
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- // Year/Era range is done in IsLeapYear().
- return IsLeapYear(year, era) ? 366 : 365;
- }
-
- public override int GetEra(DateTime time) => JulianEra;
-
- public override int GetMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartMonth);
- }
-
- public override int[] Eras => new int[] { JulianEra };
-
- public override int GetMonthsInYear(int year, int era)
- {
- CheckYearEraRange(year, era);
- return 12;
- }
-
- public override int GetYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartYear);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- CheckMonthRange(month);
- // Year/Era range check is done in IsLeapYear().
- if (IsLeapYear(year, era))
- {
- CheckDayRange(year, month, day);
- return month == 2 && day == 29;
- }
-
- CheckDayRange(year, month, day);
- return false;
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- CheckYearEraRange(year, era);
- return 0;
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- CheckYearEraRange(year, era);
- CheckMonthRange(month);
- return false;
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- CheckYearEraRange(year, era);
- return year % 4 == 0;
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- CheckYearEraRange(year, era);
- CheckMonthRange(month);
- CheckDayRange(year, month, day);
- if (millisecond < 0 || millisecond >= MillisPerSecond)
- {
- throw new ArgumentOutOfRangeException(
- nameof(millisecond),
- millisecond,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1));
- }
-
- if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
- }
-
- return new DateTime(DateToTicks(year, month, day) + (new TimeSpan(0, hour, minute, second, millisecond)).Ticks);
- }
-
- public override int TwoDigitYearMax
- {
- get => _twoDigitYearMax;
- set
- {
- VerifyWritable();
- if (value < 99 || value > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- if (year > MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 1, MaxYear));
- }
-
- return base.ToFourDigitYear(year);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
deleted file mode 100644
index d9ded694d88..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <summary>
- /// Korean calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar.
- /// That is,
- /// Korean year = Gregorian year + 2333. So 2000/01/01 A.D. is Korean 4333/01/01
- ///
- /// 0001/1/1 A.D. is Korean year 2334.
- /// </summary>
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 0001/01/01 9999/12/31
- /// Korean 2334/01/01 12332/12/31
- /// </remarks>
- public class KoreanCalendar : Calendar
- {
- public const int KoreanEra = 1;
-
- // Since
- // Gregorian Year = Era Year + yearOffset
- // Gregorian Year 1 is Korean year 2334, so that
- // 1 = 2334 + yearOffset
- // So yearOffset = -2333
- // Gregorian year 2001 is Korean year 4334.
- private static readonly EraInfo[] s_koreanEraInfo = new EraInfo[]
- {
- new EraInfo(1, 1, 1, 1, -2333, 2334, GregorianCalendar.MaxYear + 2333) // era #, start year/month/day, yearOffset, minEraYear
- };
-
- private readonly GregorianCalendarHelper _helper;
-
- public override DateTime MinSupportedDateTime => DateTime.MinValue;
-
- public override DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- public KoreanCalendar()
- {
- try
- {
- new CultureInfo("ko-KR");
- }
- catch (ArgumentException e)
- {
- throw new TypeInitializationException(GetType().ToString(), e);
- }
-
- _helper = new GregorianCalendarHelper(this, s_koreanEraInfo);
- }
-
- internal override CalendarId ID => CalendarId.KOREA;
-
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- return _helper.AddMonths(time, months);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return _helper.AddYears(time, years);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- return _helper.GetDaysInMonth(year, month, era);
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- return _helper.GetDaysInYear(year, era);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return _helper.GetDayOfMonth(time);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return _helper.GetDayOfWeek(time);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return _helper.GetDayOfYear(time);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- return _helper.GetMonthsInYear(year, era);
- }
-
- public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
- {
- return _helper.GetWeekOfYear(time, rule, firstDayOfWeek);
- }
-
- public override int GetEra(DateTime time)
- {
- return _helper.GetEra(time);
- }
-
- public override int GetMonth(DateTime time)
- {
- return _helper.GetMonth(time);
- }
-
- public override int GetYear(DateTime time)
- {
- return _helper.GetYear(time);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- return _helper.IsLeapDay(year, month, day, era);
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- return _helper.IsLeapYear(year, era);
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- return _helper.GetLeapMonth(year, era);
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- return _helper.IsLeapMonth(year, month, era);
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- return _helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era);
- }
-
- public override int[] Eras => _helper.Eras;
-
- private const int DefaultTwoDigitYearMax = 4362;
-
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > _helper.MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, _helper.MaxYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
-
- return _helper.ToFourDigitYear(year, TwoDigitYearMax);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
deleted file mode 100644
index 1d632cdc4fa..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
+++ /dev/null
@@ -1,1235 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 918/02/19 2051/02/10
- /// KoreanLunisolar 918/01/01 2050/13/29
- /// </remarks>
- public class KoreanLunisolarCalendar : EastAsianLunisolarCalendar
- {
- public const int GregorianEra = 1;
-
- private const int MinLunisolarYear = 918;
- private const int MaxLunisolarYear = 2050;
-
- private static readonly DateTime s_minDate = new DateTime(918, 2, 19);
- private static readonly DateTime s_maxDate = new DateTime((new DateTime(2051, 2, 10, 23, 59, 59, 999)).Ticks + 9999);
-
- public override DateTime MinSupportedDateTime => s_minDate;
-
- public override DateTime MaxSupportedDateTime => s_maxDate;
-
- protected override int DaysInYearBeforeMinSupportedYear =>
- // 917 -- From http://emr.cs.iit.edu/home/reingold/calendar-book/Calendrica.html
- // using ChineseLunisolar
- 384;
-
- // Data for years 1391-2050 matches that available from
- // Korea Astronomy and Space Science Institute (KASI)
- // https://astro.kasi.re.kr:444/life/pageView/5
- private static readonly int[,] s_yinfo =
- {
-/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
-0918 */ { 00, 02, 19, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-0919 */ { 00, 02, 09, 0b0100010111010000 }, /* 29 30 29 29 29 30 29 30 30 30 29 30 354
-0920 */ { 06, 01, 29, 0b1010001011011000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
-0921 */ { 00, 02, 16, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
-0922 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-0923 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-0924 */ { 00, 02, 13, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
-0925 */ { 12, 02, 01, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
-0926 */ { 00, 02, 20, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-0927 */ { 00, 02, 10, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-0928 */ { 08, 01, 31, 0b0100010110111000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
-0929 */ { 00, 02, 18, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
-0930 */ { 00, 02, 07, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-0931 */ { 05, 01, 27, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
-0932 */ { 00, 02, 14, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
-0933 */ { 00, 02, 03, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-0934 */ { 01, 01, 23, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-0935 */ { 00, 02, 11, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-0936 */ { 11, 02, 01, 0b0101001101100000 }, /* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
-0937 */ { 00, 02, 18, 0b1100101011000000 }, /* 30 30 29 29 30 29 30 29 30 30 29 29 354
-0938 */ { 00, 02, 07, 0b1110010101100000 }, /* 30 30 30 29 29 30 29 30 29 30 30 29 355
-0939 */ { 07, 01, 28, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-0940 */ { 00, 02, 16, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-0941 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-0942 */ { 03, 01, 25, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-0943 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-0944 */ { 12, 02, 02, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
-0945 */ { 00, 02, 20, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-0946 */ { 00, 02, 10, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
-0947 */ { 07, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-0948 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-0949 */ { 00, 02, 06, 0b1011001001100000 }, /* 30 29 30 30 29 29 30 29 29 30 30 29 354
-0950 */ { 05, 01, 26, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-0951 */ { 00, 02, 14, 0b1011001101110000 }, /* 30 29 30 30 29 29 30 30 29 30 30 30 356
-0953 */ { 00, 01, 05, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 355
-0953 */ { 01, 01, 23, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-0954 */ { 00, 02, 11, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-0955 */ { 09, 02, 01, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-0956 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-0957 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-0958 */ { 07, 01, 28, 0b1010101010011000 }, /* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
-0959 */ { 00, 02, 16, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-0960 */ { 00, 02, 05, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-0961 */ { 03, 01, 25, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-0962 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-0963 */ { 12, 02, 02, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-0964 */ { 00, 02, 21, 0b1010001101110000 }, /* 30 29 30 29 29 29 30 30 29 30 30 30 355
-0965 */ { 00, 02, 10, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 354
-0966 */ { 08, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-0967 */ { 00, 02, 17, 0b1101010010110000 }, /* 30 30 29 30 29 30 29 29 30 29 30 30 355
-0968 */ { 00, 02, 07, 0b0101101010010000 }, /* 29 30 29 30 30 29 30 29 30 29 29 30 354
-0969 */ { 05, 01, 26, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-0970 */ { 00, 02, 14, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-0971 */ { 00, 02, 04, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
-0972 */ { 02, 01, 24, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-0973 */ { 00, 02, 11, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
-0974 */ { 10, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-0975 */ { 00, 02, 19, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-0976 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-0977 */ { 07, 01, 27, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
-0978 */ { 00, 02, 15, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
-0979 */ { 00, 02, 05, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-0980 */ { 03, 01, 26, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-0981 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-0982 */ { 12, 02, 02, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-0983 */ { 00, 02, 21, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-0984 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-0985 */ { 09, 01, 29, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-0986 */ { 00, 02, 17, 0b1010110010100000 }, /* 30 29 30 29 30 30 29 29 30 29 30 29 354
-0987 */ { 00, 02, 06, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-0988 */ { 05, 01, 27, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-0989 */ { 00, 02, 14, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
-0990 */ { 00, 02, 04, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
-0991 */ { 02, 01, 24, 0b1001001010111000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
-0992 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-0993 */ { 10, 01, 31, 0b0110100101011000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
-0994 */ { 00, 02, 19, 0b0101100101010000 }, /* 29 30 29 30 30 29 29 30 29 30 29 30 354
-0995 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-0996 */ { 07, 01, 28, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-0997 */ { 00, 02, 15, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-0998 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-0999 */ { 03, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1000 */ { 00, 02, 13, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
-1001 */ { 12, 02, 03, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
-1002 */ { 00, 02, 21, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-1003 */ { 00, 02, 10, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1004 */ { 09, 01, 31, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1005 */ { 00, 02, 18, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1006 */ { 00, 02, 07, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-1007 */ { 05, 01, 28, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1008 */ { 00, 02, 16, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
-1009 */ { 00, 02, 04, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1010 */ { 02, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1011 */ { 00, 02, 12, 0b1011001001100000 }, /* 30 29 30 30 29 29 30 29 29 30 30 29 354
-1012 */ { 10, 02, 01, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1013 */ { 00, 02, 19, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1014 */ { 00, 02, 09, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
-1015 */ { 06, 01, 29, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1016 */ { 00, 02, 17, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1017 */ { 00, 02, 06, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1018 */ { 04, 01, 26, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1019 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1020 */ { 12, 02, 03, 0b1010101001011000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
-1021 */ { 00, 02, 21, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1022 */ { 00, 02, 10, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1023 */ { 09, 01, 31, 0b0010110110101000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
-1024 */ { 00, 02, 19, 0b0010101101010000 }, /* 29 29 30 29 30 29 30 30 29 30 29 30 354
-1025 */ { 00, 02, 07, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
-1026 */ { 05, 01, 28, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1027 */ { 00, 02, 15, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 355
-1028 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1029 */ { 02, 01, 24, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1030 */ { 00, 02, 11, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
-1031 */ { 10, 02, 01, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-1032 */ { 00, 02, 20, 0b0110011011010000 }, /* 29 30 30 29 29 30 30 29 30 30 29 30 355
-1033 */ { 00, 02, 09, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
-1034 */ { 06, 01, 29, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1035 */ { 00, 02, 17, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1036 */ { 00, 02, 06, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1037 */ { 04, 01, 25, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1038 */ { 00, 02, 13, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1039 */ { 12, 02, 02, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
-1040 */ { 00, 02, 21, 0b1011010110000000 }, /* 30 29 30 30 29 30 29 30 30 29 29 29 354
-1041 */ { 00, 02, 09, 0b1101011010110000 }, /* 30 30 29 30 29 30 30 29 30 29 30 30 356
-1042 */ { 09, 01, 31, 0b0010011011011000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
-1043 */ { 00, 02, 19, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1044 */ { 00, 02, 08, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-1045 */ { 05, 01, 27, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1046 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1047 */ { 00, 02, 04, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1048 */ { 01, 01, 24, 0b1011010101011000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
-1049 */ { 00, 02, 12, 0b0010110101010000 }, /* 29 29 30 29 30 30 29 30 29 30 29 30 354
-1050 */ { 11, 02, 01, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1051 */ { 00, 02, 20, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
-1052 */ { 00, 02, 10, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
-1053 */ { 07, 01, 29, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1054 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1055 */ { 00, 02, 06, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1056 */ { 03, 01, 26, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1057 */ { 00, 02, 13, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1058 */ { 12, 02, 02, 0b1010101101011000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
-1059 */ { 00, 02, 22, 0b0010011101010000 }, /* 29 29 30 29 29 30 30 30 29 30 29 30 354
-1060 */ { 00, 02, 11, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1061 */ { 08, 01, 30, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1062 */ { 00, 02, 18, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
-1063 */ { 00, 02, 07, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1064 */ { 05, 01, 27, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1065 */ { 00, 02, 14, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1066 */ { 00, 02, 04, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1067 */ { 01, 01, 24, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1068 */ { 00, 02, 12, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-1069 */ { 11, 02, 01, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1070 */ { 00, 02, 20, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
-1071 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1072 */ { 07, 01, 29, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1073 */ { 00, 02, 16, 0b1010101001100000 }, /* 30 29 30 29 30 29 30 29 29 30 30 29 354
-1074 */ { 00, 02, 05, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1075 */ { 04, 01, 26, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1076 */ { 00, 02, 14, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
-1077 */ { 00, 02, 02, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1078 */ { 01, 01, 23, 0b0100101110011000 }, /* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
-1079 */ { 00, 02, 11, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
-1080 */ { 09, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1081 */ { 00, 02, 18, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1082 */ { 00, 02, 07, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1083 */ { 06, 01, 27, 0b1011010101001000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
-1084 */ { 00, 02, 15, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
-1085 */ { 00, 02, 04, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
-1086 */ { 02, 01, 24, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1087 */ { 00, 02, 12, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1088 */ { 12, 02, 02, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1089 */ { 00, 02, 19, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 355
-1090 */ { 00, 02, 09, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1091 */ { 08, 01, 29, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1092 */ { 00, 02, 16, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-1093 */ { 00, 02, 05, 0b0101101101000000 }, /* 29 30 29 30 30 29 30 30 29 30 29 29 354
-1094 */ { 04, 01, 25, 0b1010101101101000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
-1095 */ { 00, 02, 14, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
-1096 */ { 00, 02, 03, 0b1110011000010000 }, /* 30 30 30 29 29 30 30 29 29 29 29 30 354
-1097 */ { 02, 01, 22, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1098 */ { 00, 02, 10, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1099 */ { 09, 01, 30, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1100 */ { 00, 02, 18, 0b0101010010100000 }, /* 29 30 29 30 29 30 29 29 30 29 30 29 353
-1101 */ { 00, 02, 07, 0b1101011001010000 }, /* 30 30 29 30 29 30 30 29 29 30 29 30 355
-1102 */ { 06, 01, 28, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1103 */ { 00, 02, 16, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
-1104 */ { 00, 02, 06, 0b0010011011010000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 354
-1105 */ { 02, 01, 25, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1106 */ { 00, 02, 13, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-1107 */ { 10, 02, 02, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1108 */ { 00, 02, 21, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1109 */ { 00, 02, 09, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1110 */ { 08, 01, 29, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1111 */ { 00, 02, 17, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1112 */ { 00, 02, 07, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1113 */ { 04, 01, 27, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1114 */ { 00, 02, 15, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
-1115 */ { 00, 02, 04, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1116 */ { 01, 01, 24, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1117 */ { 00, 02, 11, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1118 */ { 09, 01, 31, 0b0111001010101000 }, /* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
-1119 */ { 00, 02, 19, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1120 */ { 00, 02, 08, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1121 */ { 05, 01, 28, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1122 */ { 00, 02, 16, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1123 */ { 00, 02, 05, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1124 */ { 03, 01, 26, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1125 */ { 00, 02, 12, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1126 */ { 11, 02, 01, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1127 */ { 00, 02, 20, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1128 */ { 00, 02, 10, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1129 */ { 08, 01, 29, 0b1001101110010000 }, /* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
-1130 */ { 00, 02, 17, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-1131 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1132 */ { 04, 01, 27, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1133 */ { 00, 02, 14, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1134 */ { 00, 02, 03, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1135 */ { 02, 01, 23, 0b1101100100101000 }, /* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
-1136 */ { 00, 02, 11, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1137 */ { 10, 01, 30, 0b1101011010101000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
-1138 */ { 00, 02, 19, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
-1139 */ { 00, 02, 08, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1140 */ { 06, 01, 29, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1141 */ { 00, 02, 16, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1142 */ { 00, 02, 05, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1143 */ { 04, 01, 25, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1144 */ { 00, 02, 13, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1145 */ { 11, 02, 01, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1146 */ { 00, 02, 20, 0b0110101101000000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 354
-1147 */ { 00, 02, 09, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1148 */ { 08, 01, 30, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1149 */ { 00, 02, 17, 0b1001100101110000 }, /* 30 29 29 30 30 29 29 30 29 30 30 30 355
-1150 */ { 00, 02, 07, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1151 */ { 04, 01, 27, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1152 */ { 00, 02, 15, 0b0101010010110000 }, /* 29 30 29 30 29 30 29 29 30 29 30 30 354
-1153 */ { 12, 02, 03, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1154 */ { 00, 02, 21, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-1155 */ { 00, 02, 11, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
-1156 */ { 10, 01, 31, 0b1010101101101000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
-1157 */ { 00, 02, 19, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
-1158 */ { 00, 02, 08, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1159 */ { 06, 01, 28, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1160 */ { 00, 02, 16, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1161 */ { 00, 02, 04, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1162 */ { 02, 01, 24, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1163 */ { 00, 02, 12, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1164 */ { 11, 02, 02, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1165 */ { 00, 02, 20, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1166 */ { 00, 02, 10, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1167 */ { 07, 01, 30, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1168 */ { 00, 02, 18, 0b1001001001110000 }, /* 30 29 29 30 29 29 30 29 29 30 30 30 354
-1169 */ { 00, 02, 06, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1170 */ { 05, 01, 26, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1171 */ { 00, 02, 14, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1172 */ { 00, 02, 03, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1173 */ { 01, 01, 23, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1174 */ { 00, 02, 11, 0b0100110110110000 }, /* 29 30 29 29 30 30 29 30 30 29 30 30 355
-1175 */ { 09, 02, 01, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
-1176 */ { 00, 02, 19, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1177 */ { 00, 02, 08, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1178 */ { 06, 01, 28, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1179 */ { 00, 02, 16, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1180 */ { 00, 02, 05, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1181 */ { 03, 01, 24, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1182 */ { 00, 02, 12, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1183 */ { 11, 02, 02, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1184 */ { 00, 02, 21, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1185 */ { 00, 02, 09, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1186 */ { 07, 01, 30, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1187 */ { 00, 02, 17, 0b1101000010010000 }, /* 30 30 29 30 29 29 29 29 30 29 29 30 353
-1188 */ { 00, 01, 08, 0b0111010010011000 }, /* 29 30 30 30 29 30 29 29 30 29 29 30 354
-1189 */ { 05, 01, 26, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1190 */ { 00, 02, 14, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1191 */ { 00, 02, 03, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 355
-1192 */ { 02, 01, 24, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1193 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1194 */ { 10, 01, 31, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1195 */ { 00, 02, 19, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1196 */ { 00, 02, 08, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1197 */ { 06, 01, 27, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1198 */ { 00, 02, 15, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1199 */ { 00, 02, 04, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
-1200 */ { 02, 01, 25, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1201 */ { 00, 02, 12, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1202 */ { 12, 02, 02, 0b0100100111011000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
-1203 */ { 00, 02, 21, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1204 */ { 00, 02, 10, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1205 */ { 08, 01, 29, 0b1010101001011000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
-1206 */ { 00, 02, 17, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1207 */ { 00, 02, 06, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1208 */ { 04, 01, 26, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
-1209 */ { 00, 02, 13, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1210 */ { 00, 02, 03, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1211 */ { 02, 01, 24, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1212 */ { 00, 02, 12, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1213 */ { 09, 01, 31, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1214 */ { 00, 02, 19, 0b0101010010110000 }, /* 29 30 29 30 29 30 29 29 30 29 30 30 354
-1215 */ { 00, 02, 08, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1216 */ { 07, 01, 28, 0b0110110100101000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
-1217 */ { 00, 02, 15, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
-1218 */ { 00, 02, 04, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1219 */ { 03, 01, 25, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1220 */ { 00, 02, 13, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1221 */ { 12, 02, 01, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1222 */ { 00, 02, 20, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1223 */ { 00, 02, 09, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1224 */ { 08, 01, 29, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1225 */ { 00, 02, 16, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1226 */ { 00, 02, 06, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1227 */ { 05, 01, 26, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1228 */ { 00, 02, 15, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1229 */ { 00, 02, 03, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1230 */ { 02, 01, 23, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1231 */ { 00, 02, 11, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1232 */ { 09, 01, 31, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1233 */ { 00, 02, 18, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
-1234 */ { 00, 02, 07, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1235 */ { 07, 01, 28, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1236 */ { 00, 02, 16, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
-1237 */ { 00, 02, 04, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-1238 */ { 04, 01, 25, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1239 */ { 00, 02, 13, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1240 */ { 12, 02, 02, 0b1010100100111000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
-1241 */ { 00, 02, 20, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
-1242 */ { 00, 02, 09, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1243 */ { 08, 01, 29, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1244 */ { 00, 02, 17, 0b1010111001010000 }, /* 30 29 30 29 30 30 30 29 29 30 29 30 355
-1245 */ { 00, 02, 06, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1246 */ { 04, 01, 26, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1247 */ { 00, 02, 14, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1248 */ { 00, 02, 04, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
-1249 */ { 02, 01, 23, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1250 */ { 00, 02, 10, 0b1110010100110000 }, /* 30 30 30 29 29 30 29 30 29 29 30 30 355
-1251 */ { 10, 01, 31, 0b0110110010011000 }, /* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
-1252 */ { 00, 02, 19, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1253 */ { 00, 02, 07, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
-1254 */ { 06, 01, 28, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1255 */ { 00, 02, 16, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1256 */ { 00, 02, 05, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
-1257 */ { 04, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1258 */ { 00, 02, 12, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1259 */ { 11, 02, 01, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1260 */ { 00, 02, 20, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1261 */ { 00, 02, 08, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
-1262 */ { 09, 01, 29, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1263 */ { 00, 02, 17, 0b0101010101110000 }, /* 29 30 29 30 29 30 29 30 29 30 30 30 355
-1264 */ { 00, 02, 07, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
-1265 */ { 05, 01, 26, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1266 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1267 */ { 00, 02, 03, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1268 */ { 01, 01, 23, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1269 */ { 00, 02, 10, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1270 */ { 11, 01, 30, 0b1011010111000000 }, /* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
-1271 */ { 00, 02, 18, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1272 */ { 00, 02, 08, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1273 */ { 06, 01, 28, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1274 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1275 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1276 */ { 03, 01, 25, 0b0110101001011000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
-1277 */ { 00, 02, 12, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1278 */ { 11, 02, 01, 0b0110101100101000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1279 */ { 00, 02, 20, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
-1280 */ { 00, 02, 09, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1281 */ { 08, 01, 29, 0b0010101011101000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
-1282 */ { 00, 02, 17, 0b0100100111100000 }, /* 29 30 29 29 30 29 29 30 30 30 30 29 354
-1283 */ { 00, 02, 06, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1284 */ { 05, 01, 26, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1285 */ { 00, 02, 13, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
-1286 */ { 00, 02, 02, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1287 */ { 02, 01, 22, 0b1111001010010000 }, /* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
-1288 */ { 00, 02, 10, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
-1289 */ { 10, 01, 30, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1290 */ { 00, 02, 18, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1291 */ { 00, 02, 08, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1292 */ { 06, 01, 28, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1293 */ { 00, 02, 15, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1294 */ { 00, 02, 04, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1295 */ { 04, 01, 24, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1296 */ { 00, 02, 12, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1297 */ { 12, 01, 31, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
-1298 */ { 00, 02, 19, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1299 */ { 00, 02, 09, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1300 */ { 08, 01, 30, 0b0000100101111000 }, /* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
-1301 */ { 00, 02, 18, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1302 */ { 00, 02, 07, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1303 */ { 05, 01, 27, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1304 */ { 00, 02, 14, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-1305 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1306 */ { 01, 01, 23, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1307 */ { 00, 02, 11, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
-1308 */ { 11, 02, 01, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1309 */ { 00, 02, 19, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1310 */ { 00, 02, 08, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1311 */ { 07, 01, 28, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1312 */ { 00, 02, 16, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1313 */ { 00, 02, 04, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1314 */ { 03, 01, 25, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1315 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1316 */ { 00, 02, 02, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
-1317 */ { 01, 01, 22, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1318 */ { 00, 02, 10, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-1319 */ { 08, 01, 30, 0b1010010101011000 }, /* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
-1320 */ { 00, 02, 18, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1321 */ { 00, 02, 06, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
-1322 */ { 05, 01, 26, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1323 */ { 00, 02, 14, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1324 */ { 00, 02, 04, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
-1325 */ { 01, 01, 23, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1326 */ { 00, 02, 11, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1327 */ { 09, 02, 01, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1328 */ { 00, 02, 20, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
-1329 */ { 00, 02, 08, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
-1330 */ { 07, 01, 28, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1331 */ { 00, 02, 16, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1332 */ { 00, 02, 05, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1333 */ { 03, 01, 25, 0b0100101110101000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
-1334 */ { 00, 02, 13, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1335 */ { 12, 02, 02, 0b1010011001110000 }, /* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
-1336 */ { 00, 02, 21, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
-1337 */ { 00, 02, 09, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
-1338 */ { 08, 01, 29, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1339 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1340 */ { 00, 02, 06, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
-1341 */ { 05, 01, 26, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1342 */ { 00, 02, 14, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1343 */ { 00, 02, 04, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1344 */ { 02, 01, 24, 0b1010001011101000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
-1345 */ { 00, 02, 11, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
-1346 */ { 10, 01, 31, 0b1101000101011000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1347 */ { 00, 02, 19, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1348 */ { 00, 02, 08, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1349 */ { 07, 01, 27, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
-1350 */ { 00, 02, 15, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
-1351 */ { 00, 02, 05, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
-1352 */ { 03, 01, 26, 0b0100100111011000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
-1353 */ { 00, 02, 13, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
-1354 */ { 00, 02, 02, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
-1355 */ { 01, 01, 22, 0b1101000101011000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1356 */ { 00, 02, 10, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1357 */ { 09, 01, 29, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1358 */ { 00, 02, 17, 0b0110101100100000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 354
-1359 */ { 00, 02, 06, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 355
-1360 */ { 05, 01, 27, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1361 */ { 00, 02, 14, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1362 */ { 00, 02, 04, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
-1363 */ { 03, 01, 24, 0b1010001010111000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
-1364 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1365 */ { 10, 01, 31, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
-1366 */ { 00, 02, 18, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1367 */ { 00, 02, 08, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1368 */ { 07, 01, 28, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1369 */ { 00, 02, 15, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
-1370 */ { 00, 02, 05, 0b0101001011100000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 354
-1371 */ { 03, 01, 25, 0b1100010101110000 }, /* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
-1372 */ { 00, 02, 13, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
-1373 */ { 11, 02, 01, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1374 */ { 00, 02, 20, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-1375 */ { 00, 02, 09, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1376 */ { 09, 01, 30, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1377 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1378 */ { 00, 02, 06, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
-1379 */ { 05, 01, 27, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-1380 */ { 00, 02, 15, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1381 */ { 00, 02, 03, 0b1010100011010000 }, /* 30 29 30 29 30 29 29 29 30 30 29 30 354
-1382 */ { 02, 01, 23, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1383 */ { 00, 02, 11, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
-1384 */ { 10, 01, 31, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1385 */ { 00, 02, 18, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1386 */ { 00, 02, 08, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
-1387 */ { 06, 01, 28, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1388 */ { 00, 02, 16, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1389 */ { 00, 02, 05, 0b0101000110110000 }, /* 29 30 29 30 29 29 29 30 30 29 30 30 354
-1390 */ { 04, 01, 25, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1391 */ { 00, 02, 13, 0b0110010100110000 }, /* 29 30 30 29 29 30 29 30 29 29 30 30 354
-1392 */ { 12, 02, 02, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1393 */ { 00, 02, 20, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1394 */ { 00, 02, 09, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1395 */ { 09, 01, 30, 0b0010101110101000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
-1396 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1397 */ { 00, 02, 06, 0b1100001101110000 }, /* 30 30 29 29 29 29 30 30 29 30 30 30 355
-1398 */ { 05, 01, 27, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1399 */ { 00, 02, 14, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1400 */ { 00, 02, 03, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
-1401 */ { 03, 01, 24, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1402 */ { 00, 02, 11, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
-1403 */ { 11, 02, 01, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1404 */ { 00, 02, 20, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1405 */ { 00, 02, 09, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
-1406 */ { 07, 01, 29, 0b1010001011101000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
-1407 */ { 00, 02, 17, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
-1408 */ { 00, 02, 06, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
-1409 */ { 04, 01, 25, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1410 */ { 00, 02, 13, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1411 */ { 12, 02, 02, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
-1412 */ { 00, 02, 21, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
-1413 */ { 00, 02, 10, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
-1414 */ { 09, 01, 31, 0b0010010111011000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
-1415 */ { 00, 02, 19, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
-1416 */ { 00, 02, 08, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
-1417 */ { 05, 01, 27, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1418 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1419 */ { 00, 02, 04, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1420 */ { 01, 01, 24, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1421 */ { 00, 02, 11, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1422 */ { 12, 02, 01, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1423 */ { 00, 02, 20, 0b0100101101110000 }, /* 29 30 29 29 30 29 30 30 29 30 30 30 355
-1424 */ { 00, 02, 10, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
-1425 */ { 07, 01, 29, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1426 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1427 */ { 00, 02, 06, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1428 */ { 04, 01, 26, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1429 */ { 00, 02, 13, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1430 */ { 12, 02, 02, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
-1431 */ { 00, 02, 21, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
-1432 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1433 */ { 08, 01, 30, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1434 */ { 00, 02, 18, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
-1435 */ { 00, 02, 07, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-1436 */ { 06, 01, 27, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1437 */ { 00, 02, 14, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1438 */ { 00, 02, 04, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1439 */ { 02, 01, 24, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-1440 */ { 00, 02, 12, 0b1001010111100000 }, /* 30 29 29 30 29 30 29 30 30 30 30 29 355
-1441 */ { 11, 02, 01, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1442 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1443 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1444 */ { 07, 01, 29, 0b1101001001110000 }, /* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
-1445 */ { 00, 02, 16, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
-1446 */ { 00, 02, 05, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1447 */ { 04, 01, 26, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1448 */ { 00, 02, 14, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
-1449 */ { 00, 02, 02, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1450 */ { 01, 01, 23, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1451 */ { 00, 02, 11, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1452 */ { 09, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1453 */ { 00, 02, 18, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1454 */ { 00, 02, 07, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
-1455 */ { 06, 01, 27, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1456 */ { 00, 02, 15, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
-1457 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1458 */ { 02, 01, 24, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1459 */ { 00, 02, 12, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1460 */ { 11, 02, 02, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1461 */ { 00, 02, 19, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1462 */ { 00, 02, 08, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
-1463 */ { 07, 01, 29, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1464 */ { 00, 02, 16, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
-1465 */ { 00, 02, 05, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
-1466 */ { 03, 01, 26, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1467 */ { 00, 02, 14, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
-1468 */ { 00, 02, 03, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1469 */ { 02, 01, 22, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1470 */ { 00, 02, 10, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
-1471 */ { 09, 01, 30, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1472 */ { 00, 02, 18, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1473 */ { 00, 02, 06, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
-1474 */ { 06, 01, 27, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1475 */ { 00, 02, 15, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1476 */ { 00, 02, 05, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1477 */ { 02, 01, 24, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1478 */ { 00, 02, 12, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-1479 */ { 10, 02, 01, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1480 */ { 00, 02, 20, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1481 */ { 00, 02, 08, 0b0111010010100000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 354
-1482 */ { 08, 01, 28, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1483 */ { 00, 02, 16, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
-1484 */ { 00, 02, 06, 0b0101001110110000 }, /* 29 30 29 30 29 29 30 30 30 29 30 30 355
-1485 */ { 04, 01, 26, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1486 */ { 00, 02, 14, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
-1487 */ { 00, 02, 03, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1488 */ { 01, 01, 23, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1489 */ { 00, 02, 10, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1490 */ { 09, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1491 */ { 00, 02, 18, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1492 */ { 00, 02, 07, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1493 */ { 05, 01, 27, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1494 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1495 */ { 00, 02, 04, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1496 */ { 03, 01, 25, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1497 */ { 00, 02, 11, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-1498 */ { 11, 01, 31, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
-1499 */ { 00, 02, 19, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1500 */ { 00, 02, 09, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1501 */ { 07, 01, 29, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1502 */ { 00, 02, 17, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1503 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1504 */ { 04, 01, 27, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1505 */ { 00, 02, 14, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1506 */ { 00, 02, 03, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1507 */ { 01, 01, 23, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
-1508 */ { 00, 02, 11, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1509 */ { 09, 01, 31, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1510 */ { 00, 02, 19, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
-1511 */ { 00, 02, 08, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1512 */ { 05, 01, 29, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1513 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1514 */ { 00, 02, 05, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1515 */ { 04, 01, 25, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1516 */ { 00, 02, 13, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
-1517 */ { 12, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1518 */ { 00, 02, 20, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
-1519 */ { 00, 02, 10, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1520 */ { 08, 01, 30, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1521 */ { 00, 02, 17, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 355
-1522 */ { 00, 02, 07, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1523 */ { 04, 01, 27, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1524 */ { 00, 02, 14, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1525 */ { 12, 02, 02, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
-1526 */ { 00, 02, 21, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 355
-1527 */ { 00, 02, 11, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1528 */ { 10, 02, 01, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1529 */ { 00, 02, 19, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
-1530 */ { 00, 02, 08, 0b0101001011100000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 354
-1531 */ { 06, 01, 28, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1532 */ { 00, 02, 16, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
-1533 */ { 00, 02, 04, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1534 */ { 02, 01, 24, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1535 */ { 00, 02, 12, 0b1011010110010000 }, /* 30 29 30 30 29 30 29 30 30 29 29 30 355
-1536 */ { 12, 02, 02, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1537 */ { 00, 02, 20, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1538 */ { 00, 02, 10, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1539 */ { 07, 01, 30, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1540 */ { 00, 02, 18, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-1541 */ { 00, 02, 06, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1542 */ { 05, 01, 26, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1543 */ { 00, 02, 14, 0b0110110010100000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 354
-1544 */ { 00, 02, 03, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1545 */ { 01, 01, 23, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1546 */ { 00, 02, 11, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
-1547 */ { 09, 02, 01, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1548 */ { 00, 02, 20, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
-1549 */ { 00, 02, 08, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1550 */ { 06, 01, 28, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1551 */ { 00, 02, 15, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
-1552 */ { 00, 02, 05, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1553 */ { 03, 01, 24, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1554 */ { 00, 02, 12, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1555 */ { 11, 02, 02, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1556 */ { 00, 02, 21, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1557 */ { 00, 02, 09, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1558 */ { 07, 01, 30, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1559 */ { 00, 02, 17, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1560 */ { 00, 02, 06, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1561 */ { 05, 01, 26, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1562 */ { 00, 02, 14, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1563 */ { 00, 02, 03, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-1564 */ { 02, 01, 24, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1565 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1566 */ { 10, 01, 31, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1567 */ { 00, 02, 19, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1568 */ { 00, 02, 08, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1569 */ { 06, 01, 27, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1570 */ { 00, 02, 15, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1571 */ { 00, 02, 05, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
-1572 */ { 02, 01, 25, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1573 */ { 00, 02, 12, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1574 */ { 12, 02, 02, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1575 */ { 00, 02, 21, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1576 */ { 00, 02, 10, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1577 */ { 08, 01, 29, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1578 */ { 00, 02, 17, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1579 */ { 00, 02, 06, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1580 */ { 04, 01, 26, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1581 */ { 00, 02, 14, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1582 */ { 00, 02, 03, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1583 */ { 02, 01, 24, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1584 */ { 00, 02, 12, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1585 */ { 09, 01, 31, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1586 */ { 00, 02, 18, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1587 */ { 00, 02, 07, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-1588 */ { 06, 01, 28, 0b0110101101001000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
-1589 */ { 00, 02, 15, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1590 */ { 00, 02, 05, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1591 */ { 03, 01, 25, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
-1592 */ { 00, 02, 13, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1593 */ { 11, 02, 01, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1594 */ { 00, 02, 20, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1595 */ { 00, 02, 09, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1596 */ { 08, 01, 29, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1597 */ { 00, 02, 16, 0b1011010011010000 }, /* 30 29 30 30 29 30 29 29 30 30 29 30 355
-1598 */ { 00, 02, 06, 0b0101011010110000 }, /* 29 30 29 30 29 30 30 29 30 29 30 30 355
-1599 */ { 04, 01, 27, 0b0010011011011000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
-1600 */ { 00, 02, 15, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1601 */ { 00, 02, 03, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-1602 */ { 02, 01, 23, 0b1100100110011000 }, /* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
-1603 */ { 00, 02, 11, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1604 */ { 09, 01, 31, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1605 */ { 00, 02, 18, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1606 */ { 00, 02, 07, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1607 */ { 06, 01, 28, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1608 */ { 00, 02, 16, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
-1609 */ { 00, 02, 05, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
-1610 */ { 03, 01, 25, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1611 */ { 00, 02, 13, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1612 */ { 11, 02, 02, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1613 */ { 00, 02, 19, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
-1614 */ { 00, 02, 09, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1615 */ { 08, 01, 29, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1616 */ { 00, 02, 17, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 355
-1617 */ { 00, 02, 06, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1618 */ { 04, 01, 26, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1619 */ { 00, 02, 14, 0b1010010011110000 }, /* 30 29 30 29 29 30 29 29 30 30 30 30 355
-1620 */ { 00, 02, 04, 0b0101001001100000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 353
-1621 */ { 02, 01, 22, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1622 */ { 00, 02, 10, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1623 */ { 10, 01, 31, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1624 */ { 00, 02, 19, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1625 */ { 00, 02, 07, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-1626 */ { 06, 01, 28, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1627 */ { 00, 02, 16, 0b0100100111100000 }, /* 29 30 29 29 30 29 29 30 30 30 30 29 354
-1628 */ { 00, 02, 05, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1629 */ { 04, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1630 */ { 00, 02, 12, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1631 */ { 11, 02, 01, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1632 */ { 00, 02, 20, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1633 */ { 00, 02, 08, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
-1634 */ { 08, 01, 29, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1635 */ { 00, 02, 17, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1636 */ { 00, 02, 07, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1637 */ { 04, 01, 26, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1638 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1639 */ { 00, 02, 03, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1640 */ { 01, 01, 23, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1641 */ { 00, 02, 10, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1642 */ { 11, 01, 30, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1643 */ { 00, 02, 19, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1644 */ { 00, 02, 08, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1645 */ { 06, 01, 28, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1646 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1647 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1648 */ { 03, 01, 25, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1649 */ { 00, 02, 11, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-1650 */ { 11, 02, 01, 0b0110101101001000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
-1651 */ { 00, 02, 20, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1652 */ { 00, 02, 10, 0b0010101110100000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 354
-1653 */ { 07, 01, 29, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
-1654 */ { 00, 02, 17, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1655 */ { 00, 02, 06, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1656 */ { 05, 01, 26, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1657 */ { 00, 02, 13, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1658 */ { 00, 02, 02, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-1659 */ { 03, 01, 23, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1660 */ { 00, 02, 11, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1661 */ { 07, 01, 30, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
-1662 */ { 00, 02, 18, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 355
-1663 */ { 00, 02, 08, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-1664 */ { 06, 01, 28, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1665 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1666 */ { 00, 02, 04, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1667 */ { 04, 01, 24, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1668 */ { 00, 02, 12, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1669 */ { 00, 02, 01, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
-1670 */ { 02, 01, 21, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1671 */ { 00, 02, 09, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-1672 */ { 07, 01, 30, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1673 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1674 */ { 00, 02, 06, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
-1675 */ { 05, 01, 26, 0b0111010010101000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-1676 */ { 00, 02, 14, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1677 */ { 00, 02, 02, 0b1010110110010000 }, /* 30 29 30 29 30 30 29 30 30 29 29 30 355
-1678 */ { 03, 01, 23, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-1679 */ { 00, 02, 11, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1680 */ { 08, 01, 31, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1681 */ { 00, 02, 18, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
-1682 */ { 00, 02, 07, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1683 */ { 06, 01, 27, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1684 */ { 00, 02, 15, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
-1685 */ { 00, 02, 03, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
-1686 */ { 04, 01, 24, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-1687 */ { 00, 02, 12, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1688 */ { 00, 02, 02, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1689 */ { 03, 01, 21, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1690 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1691 */ { 07, 01, 29, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1692 */ { 00, 02, 17, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
-1693 */ { 00, 02, 05, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
-1694 */ { 05, 01, 25, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
-1695 */ { 00, 02, 13, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
-1696 */ { 00, 02, 03, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
-1697 */ { 03, 01, 23, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1698 */ { 00, 02, 11, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
-1699 */ { 07, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1700 */ { 00, 02, 19, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1701 */ { 00, 02, 08, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
-1702 */ { 06, 01, 28, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1703 */ { 00, 02, 16, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
-1704 */ { 00, 02, 05, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
-1705 */ { 04, 01, 25, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1706 */ { 00, 02, 13, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1707 */ { 00, 02, 03, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1708 */ { 03, 01, 23, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1709 */ { 00, 02, 10, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1710 */ { 07, 01, 30, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1711 */ { 00, 02, 17, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-1712 */ { 00, 02, 07, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1713 */ { 05, 01, 26, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1714 */ { 00, 02, 14, 0b1010101011100000 }, /* 30 29 30 29 30 29 30 29 30 30 30 29 355
-1715 */ { 00, 02, 04, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1716 */ { 03, 01, 24, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1717 */ { 00, 02, 11, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-1718 */ { 08, 01, 31, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1719 */ { 00, 02, 19, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1720 */ { 00, 02, 08, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1721 */ { 06, 01, 28, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1722 */ { 00, 02, 16, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1723 */ { 00, 02, 05, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
-1724 */ { 04, 01, 26, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-1725 */ { 00, 02, 13, 0b0101001011010000 }, /* 29 30 29 30 29 29 30 29 30 30 29 30 354
-1726 */ { 00, 02, 02, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1727 */ { 03, 01, 22, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-1728 */ { 00, 02, 10, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1729 */ { 07, 01, 29, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1730 */ { 00, 02, 17, 0b1001110101010000 }, /* 30 29 29 30 30 30 29 30 29 30 29 30 355
-1731 */ { 00, 02, 07, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
-1732 */ { 05, 01, 27, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1733 */ { 00, 02, 14, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-1734 */ { 00, 02, 04, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1735 */ { 04, 01, 24, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1736 */ { 00, 02, 12, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
-1737 */ { 09, 01, 31, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1738 */ { 00, 02, 19, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1739 */ { 00, 02, 08, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1740 */ { 06, 01, 29, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-1741 */ { 00, 02, 16, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1742 */ { 00, 02, 05, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1743 */ { 04, 01, 26, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1744 */ { 00, 02, 13, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
-1745 */ { 00, 02, 01, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 355
-1746 */ { 03, 01, 22, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1747 */ { 00, 02, 09, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
-1748 */ { 07, 01, 30, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1749 */ { 00, 02, 17, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1750 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1751 */ { 05, 01, 27, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1752 */ { 00, 02, 15, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
-1753 */ { 00, 02, 03, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
-1754 */ { 04, 01, 23, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1755 */ { 00, 02, 11, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1756 */ { 09, 01, 31, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
-1757 */ { 00, 02, 18, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
-1758 */ { 00, 02, 08, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
-1759 */ { 06, 01, 29, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-1760 */ { 00, 02, 17, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
-1761 */ { 00, 02, 05, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
-1762 */ { 05, 01, 25, 0b1011000101011000 }, /* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
-1763 */ { 00, 02, 13, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1764 */ { 00, 02, 02, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1765 */ { 02, 01, 21, 0b1011010110010000 }, /* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
-1766 */ { 00, 02, 09, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 355
-1767 */ { 07, 01, 30, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1768 */ { 00, 02, 18, 0b0101001101110000 }, /* 29 30 29 30 29 29 30 30 29 30 30 30 355
-1769 */ { 00, 02, 07, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
-1770 */ { 05, 01, 27, 0b0110001010111000 }, /* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
-1771 */ { 00, 02, 15, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1772 */ { 00, 02, 04, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1773 */ { 03, 01, 23, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1774 */ { 00, 02, 11, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1775 */ { 10, 01, 31, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1776 */ { 00, 02, 19, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
-1777 */ { 00, 02, 08, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1778 */ { 06, 01, 28, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1779 */ { 00, 02, 16, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
-1780 */ { 00, 02, 05, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-1781 */ { 05, 01, 24, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1782 */ { 00, 02, 12, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1783 */ { 00, 02, 02, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1784 */ { 03, 01, 22, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1785 */ { 00, 02, 09, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
-1786 */ { 07, 01, 30, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1787 */ { 00, 02, 18, 0b0100101010110000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 354
-1788 */ { 00, 02, 07, 0b1010100011010000 }, /* 30 29 30 29 30 29 29 29 30 30 29 30 354
-1789 */ { 05, 01, 26, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1790 */ { 00, 02, 14, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
-1791 */ { 00, 02, 03, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1792 */ { 04, 01, 24, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1793 */ { 00, 02, 11, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
-1794 */ { 00, 01, 31, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1795 */ { 02, 01, 21, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1796 */ { 00, 02, 09, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1797 */ { 06, 01, 28, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1798 */ { 00, 02, 16, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1799 */ { 00, 02, 05, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
-1800 */ { 04, 01, 25, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1801 */ { 00, 02, 13, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
-1802 */ { 00, 02, 03, 0b0010101110100000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 354
-1803 */ { 02, 01, 23, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1804 */ { 00, 02, 11, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1805 */ { 06, 01, 31, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1806 */ { 00, 02, 18, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
-1807 */ { 00, 02, 07, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
-1808 */ { 05, 01, 28, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1809 */ { 00, 02, 14, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
-1810 */ { 00, 02, 04, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
-1811 */ { 03, 01, 25, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1812 */ { 00, 02, 13, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
-1813 */ { 00, 02, 01, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
-1814 */ { 02, 01, 21, 0b1101000101101000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
-1815 */ { 00, 02, 09, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
-1816 */ { 06, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1817 */ { 00, 02, 16, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
-1818 */ { 00, 02, 05, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
-1819 */ { 04, 01, 26, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1820 */ { 00, 02, 14, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
-1821 */ { 00, 02, 03, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1822 */ { 03, 01, 23, 0b1010001011011000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
-1823 */ { 00, 02, 11, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
-1824 */ { 07, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1825 */ { 00, 02, 18, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1826 */ { 00, 02, 07, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1827 */ { 05, 01, 27, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1828 */ { 00, 02, 15, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-1829 */ { 00, 02, 04, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1830 */ { 04, 01, 25, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1831 */ { 00, 02, 13, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
-1832 */ { 09, 02, 02, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1833 */ { 00, 02, 20, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1834 */ { 00, 02, 09, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1835 */ { 06, 01, 29, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1836 */ { 00, 02, 17, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1837 */ { 00, 02, 05, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1838 */ { 04, 01, 26, 0b0101001101101000 }, /* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
-1839 */ { 00, 02, 14, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1840 */ { 00, 02, 03, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1841 */ { 03, 01, 23, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
-1842 */ { 00, 02, 10, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
-1843 */ { 07, 01, 30, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1844 */ { 00, 02, 18, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
-1845 */ { 00, 02, 07, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-1846 */ { 05, 01, 27, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-1847 */ { 00, 02, 15, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1848 */ { 00, 02, 05, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1849 */ { 04, 01, 24, 0b1010010101011000 }, /* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
-1850 */ { 00, 02, 12, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1851 */ { 08, 02, 01, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1852 */ { 00, 02, 20, 0b1011001010010000 }, /* 30 29 30 30 29 29 30 29 30 29 29 30 354
-1853 */ { 00, 02, 08, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1854 */ { 07, 01, 29, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1855 */ { 00, 02, 17, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
-1856 */ { 00, 02, 06, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1857 */ { 05, 01, 26, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1858 */ { 00, 02, 14, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1859 */ { 00, 02, 03, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1860 */ { 03, 01, 23, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1861 */ { 00, 02, 10, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
-1862 */ { 08, 01, 30, 0b1010110101001000 }, /* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
-1863 */ { 00, 02, 18, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
-1864 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1865 */ { 05, 01, 27, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1866 */ { 00, 02, 15, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
-1867 */ { 00, 02, 05, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1868 */ { 04, 01, 25, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1869 */ { 00, 02, 11, 0b1110010010100000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 354
-1870 */ { 10, 01, 31, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
-1871 */ { 00, 02, 19, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
-1872 */ { 00, 02, 09, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
-1873 */ { 06, 01, 29, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1874 */ { 00, 02, 17, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
-1875 */ { 00, 02, 06, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1876 */ { 05, 01, 26, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1877 */ { 00, 02, 13, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
-1878 */ { 00, 02, 02, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1879 */ { 03, 01, 22, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1880 */ { 00, 02, 10, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
-1881 */ { 07, 01, 30, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1882 */ { 00, 02, 18, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1883 */ { 00, 02, 08, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1884 */ { 05, 01, 28, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1885 */ { 00, 02, 15, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
-1886 */ { 00, 02, 04, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1887 */ { 04, 01, 24, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1888 */ { 00, 02, 12, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1889 */ { 00, 01, 31, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1890 */ { 02, 01, 21, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1891 */ { 00, 02, 09, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
-1892 */ { 06, 01, 30, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1893 */ { 00, 02, 17, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
-1894 */ { 00, 02, 06, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1895 */ { 05, 01, 26, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1896 */ { 00, 02, 13, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
-1897 */ { 00, 02, 02, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1898 */ { 03, 01, 22, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1899 */ { 00, 02, 10, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1900 */ { 08, 01, 31, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1901 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1902 */ { 00, 02, 08, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1903 */ { 05, 01, 29, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1904 */ { 00, 02, 16, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
-1905 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1906 */ { 04, 01, 25, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1907 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1908 */ { 00, 02, 02, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
-1909 */ { 02, 01, 22, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1910 */ { 00, 02, 10, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1911 */ { 06, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1912 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-1913 */ { 00, 02, 06, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1914 */ { 05, 01, 26, 0b1101100101001000 }, /* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
-1915 */ { 00, 02, 14, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1916 */ { 00, 02, 04, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1917 */ { 02, 01, 23, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */ { 00, 02, 11, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
-1919 */ { 07, 02, 01, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1920 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1921 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1922 */ { 05, 01, 28, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */ { 00, 02, 16, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
-1924 */ { 00, 02, 05, 0b1010110101000000 }, /* 30 29 30 29 30 30 29 30 29 30 29 29 354
-1925 */ { 04, 01, 24, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1926 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1927 */ { 00, 02, 02, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1928 */ { 02, 01, 23, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1929 */ { 00, 02, 10, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1930 */ { 06, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */ { 00, 02, 17, 0b1110010010100000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 354
-1932 */ { 00, 02, 06, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-1933 */ { 05, 01, 26, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */ { 00, 02, 14, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
-1935 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1936 */ { 03, 01, 24, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1937 */ { 00, 02, 11, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-1938 */ { 07, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */ { 00, 02, 19, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
-1940 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-1941 */ { 06, 01, 27, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */ { 00, 02, 15, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
-1943 */ { 00, 02, 05, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
-1944 */ { 04, 01, 26, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-1945 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-1946 */ { 00, 02, 02, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-1947 */ { 02, 01, 22, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-1949 */ { 07, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1950 */ { 00, 02, 17, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-1951 */ { 00, 02, 06, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-1952 */ { 05, 01, 27, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1953 */ { 00, 02, 14, 0b0100110110110000 }, /* 29 30 29 29 30 30 29 30 30 29 30 30 355
-1954 */ { 00, 02, 04, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
-1955 */ { 03, 01, 24, 0b1001001010111000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-1957 */ { 08, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1958 */ { 00, 02, 19, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
-1959 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
-1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-1965 */ { 00, 02, 02, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
-1966 */ { 03, 01, 22, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
-1968 */ { 07, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
-1970 */ { 00, 02, 06, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
-1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-1973 */ { 00, 02, 03, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
-1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-1976 */ { 08, 01, 31, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
-1978 */ { 00, 02, 07, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
-1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-1982 */ { 04, 01, 25, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
-1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-1987 */ { 06, 01, 29, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1988 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1989 */ { 00, 02, 06, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
-1990 */ { 05, 01, 27, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
-1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
-1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
-1995 */ { 08, 01, 31, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1996 */ { 00, 02, 19, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
-1997 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
-1998 */ { 05, 01, 28, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
-2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
-2001 */ { 04, 01, 24, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
-2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
-2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */ { 00, 02, 09, 0b0101011011000000 }, /* 29 30 29 30 29 30 30 29 30 30 29 29 354
-2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
-2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
-2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
-2012 */ { 03, 01, 23, 0b1011101001010000 }, /* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
-2013 */ { 00, 02, 10, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
-2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
-2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
-2017 */ { 05, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
-2019 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
-2020 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
-2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
-2023 */ { 02, 01, 22, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
-2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */ { 00, 02, 17, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
-2027 */ { 00, 02, 07, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
-2028 */ { 05, 01, 27, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-2029 */ { 00, 02, 13, 0b1101100100110000 }, /* 30 30 29 30 30 29 29 30 29 29 30 30 355
-2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
-2031 */ { 03, 01, 23, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
-2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
-2036 */ { 06, 01, 28, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
-2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
-2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */ { 00, 02, 12, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
-2041 */ { 00, 02, 01, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
-2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
-2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
-2046 */ { 00, 02, 06, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
-2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */ { 00, 02, 14, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
-2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
-2050 */ { 03, 01, 23, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
- */ };
-
- internal override int MinCalendarYear => MinLunisolarYear;
-
- internal override int MaxCalendarYear => MaxLunisolarYear;
-
- internal override DateTime MinDate => s_minDate;
-
- internal override DateTime MaxDate => s_maxDate;
-
- internal override EraInfo[]? CalEraInfo => null;
-
- internal override int GetYearInfo(int lunarYear, int index)
- {
- if (lunarYear < MinLunisolarYear || lunarYear > MaxLunisolarYear)
- {
- throw new ArgumentOutOfRangeException(
- "year",
- lunarYear,
- SR.Format(SR.ArgumentOutOfRange_Range, MinLunisolarYear, MaxLunisolarYear));
- }
-
- return s_yinfo[lunarYear - MinLunisolarYear, index];
- }
-
- internal override int GetYear(int year, DateTime time)
- {
- return year;
- }
-
- internal override int GetGregorianYear(int year, int era)
- {
- if (era != CurrentEra && era != GregorianEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- if (year < MinLunisolarYear || year > MaxLunisolarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, MinLunisolarYear, MaxLunisolarYear));
- }
-
- return year;
- }
-
- public KoreanLunisolarCalendar()
- {
- }
-
- public override int GetEra(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return GregorianEra;
- }
-
- internal override CalendarId BaseCalendarID => CalendarId.KOREA;
-
- internal override CalendarId ID => CalendarId.KOREANLUNISOLAR;
-
- public override int[] Eras => new int[] { GregorianEra };
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/LocaleData.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/LocaleData.Unix.cs
deleted file mode 100644
index 2af5eb9c250..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/LocaleData.Unix.cs
+++ /dev/null
@@ -1,4573 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-#pragma warning disable SA1001
-
-// This file contains the handling of Windows OS specific culture features.
-
-namespace System.Globalization
-{
- internal enum LocaleDataParts
- {
- Lcid = 0,
- AnsiCodePage = 1,
- OemCodePage = 2,
- MacCodePage = 3,
- EbcdicCodePage = 4,
- GeoId = 5,
- DigitSubstitution = 6,
- SpecificLocaleIndex = 7,
- ConsoleLocaleIndex = 8
- }
-
- internal static class LocaleData
- {
- // 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_localeNamesIndices, we binary search this string when mapping
- // an culture name to Lcid. Note that these names are all lowercase and are
- // sorted alphabetically (ordinal).
- private const string c_localeNames =
- // culture name Lcid
- "aa" + // 01000 - 0
- "aa-dj" + // 01000 - 2
- "aa-er" + // 01000 - 7
- "aa-et" + // 01000 - 12
- "af" + // 00036 - 17
- "af-na" + // 01000 - 19
- "af-za" + // 00436 - 24
- "agq" + // 01000 - 29
- "agq-cm" + // 01000 - 32
- "ak" + // 01000 - 38
- "ak-gh" + // 01000 - 40
- "am" + // 0005e - 45
- "am-et" + // 0045e - 47
- "ar" + // 00001 - 52
- "ar-001" + // 01000 - 54
- "ar-ae" + // 03801 - 60
- "ar-bh" + // 03c01 - 65
- "ar-dj" + // 01000 - 70
- "ar-dz" + // 01401 - 75
- "ar-eg" + // 00c01 - 80
- "ar-er" + // 01000 - 85
- "ar-il" + // 01000 - 90
- "ar-iq" + // 00801 - 95
- "ar-jo" + // 02c01 - 100
- "ar-km" + // 01000 - 105
- "ar-kw" + // 03401 - 110
- "ar-lb" + // 03001 - 115
- "ar-ly" + // 01001 - 120
- "ar-ma" + // 01801 - 125
- "ar-mr" + // 01000 - 130
- "ar-om" + // 02001 - 135
- "ar-ps" + // 01000 - 140
- "ar-qa" + // 04001 - 145
- "ar-sa" + // 00401 - 150
- "ar-sd" + // 01000 - 155
- "ar-so" + // 01000 - 160
- "ar-ss" + // 01000 - 165
- "ar-sy" + // 02801 - 170
- "ar-td" + // 01000 - 175
- "ar-tn" + // 01c01 - 180
- "ar-ye" + // 02401 - 185
- "arn" + // 0007a - 190
- "arn-cl" + // 0047a - 193
- "as" + // 0004d - 199
- "as-in" + // 0044d - 201
- "asa" + // 01000 - 206
- "asa-tz" + // 01000 - 209
- "ast" + // 01000 - 215
- "ast-es" + // 01000 - 218
- "az" + // 0002c - 224
- "az-cyrl" + // 0742c - 226
- "az-cyrl-az" + // 0082c - 233
- "az-latn" + // 0782c - 243
- "az-latn-az" + // 0042c - 250
- "ba" + // 0006d - 260
- "ba-ru" + // 0046d - 262
- "bas" + // 01000 - 267
- "bas-cm" + // 01000 - 270
- "be" + // 00023 - 276
- "be-by" + // 00423 - 278
- "bem" + // 01000 - 283
- "bem-zm" + // 01000 - 286
- "bez" + // 01000 - 292
- "bez-tz" + // 01000 - 295
- "bg" + // 00002 - 301
- "bg-bg" + // 00402 - 303
- "bin" + // 00066 - 308
- "bin-ng" + // 00466 - 311
- "bm" + // 01000 - 317
- "bm-latn" + // 01000 - 319
- "bm-latn-ml" + // 01000 - 326
- "bn" + // 00045 - 336
- "bn-bd" + // 00845 - 338
- "bn-in" + // 00445 - 343
- "bo" + // 00051 - 348
- "bo-cn" + // 00451 - 350
- "bo-in" + // 01000 - 355
- "br" + // 0007e - 360
- "br-fr" + // 0047e - 362
- "brx" + // 01000 - 367
- "brx-in" + // 01000 - 370
- "bs" + // 0781a - 376
- "bs-cyrl" + // 0641a - 378
- "bs-cyrl-ba" + // 0201a - 385
- "bs-latn" + // 0681a - 395
- "bs-latn-ba" + // 0141a - 402
- "byn" + // 01000 - 412
- "byn-er" + // 01000 - 415
- "ca" + // 00003 - 421
- "ca-ad" + // 01000 - 423
- "ca-es" + // 00403 - 428
- "ca-es-valencia" + // 00803 - 433
- "ca-fr" + // 01000 - 447
- "ca-it" + // 01000 - 452
- "ce" + // 01000 - 457
- "ce-ru" + // 01000 - 459
- "cgg" + // 01000 - 464
- "cgg-ug" + // 01000 - 467
- "chr" + // 0005c - 473
- "chr-cher" + // 07c5c - 476
- "chr-cher-us" + // 0045c - 484
- "co" + // 00083 - 495
- "co-fr" + // 00483 - 497
- "cs" + // 00005 - 502
- "cs-cz" + // 00405 - 504
- "cu" + // 01000 - 509
- "cu-ru" + // 01000 - 511
- "cy" + // 00052 - 516
- "cy-gb" + // 00452 - 518
- "da" + // 00006 - 523
- "da-dk" + // 00406 - 525
- "da-gl" + // 01000 - 530
- "dav" + // 01000 - 535
- "dav-ke" + // 01000 - 538
- "de" + // 00007 - 544
- "de-at" + // 00c07 - 546
- "de-be" + // 01000 - 551
- "de-ch" + // 00807 - 556
- "de-de" + // 00407 - 561
- "de-de_phoneb" + // 10407 - 566
- "de-it" + // 01000 - 578
- "de-li" + // 01407 - 583
- "de-lu" + // 01007 - 588
- "dje" + // 01000 - 593
- "dje-ne" + // 01000 - 596
- "dsb" + // 07c2e - 602
- "dsb-de" + // 0082e - 605
- "dua" + // 01000 - 611
- "dua-cm" + // 01000 - 614
- "dv" + // 00065 - 620
- "dv-mv" + // 00465 - 622
- "dyo" + // 01000 - 627
- "dyo-sn" + // 01000 - 630
- "dz" + // 01000 - 636
- "dz-bt" + // 00c51 - 638
- "ebu" + // 01000 - 643
- "ebu-ke" + // 01000 - 646
- "ee" + // 01000 - 652
- "ee-gh" + // 01000 - 654
- "ee-tg" + // 01000 - 659
- "el" + // 00008 - 664
- "el-cy" + // 01000 - 666
- "el-gr" + // 00408 - 671
- "en" + // 00009 - 676
- "en-001" + // 01000 - 678
- "en-029" + // 02409 - 684
- "en-150" + // 01000 - 690
- "en-ag" + // 01000 - 696
- "en-ai" + // 01000 - 701
- "en-as" + // 01000 - 706
- "en-at" + // 01000 - 711
- "en-au" + // 00c09 - 716
- "en-bb" + // 01000 - 721
- "en-be" + // 01000 - 726
- "en-bi" + // 01000 - 731
- "en-bm" + // 01000 - 736
- "en-bs" + // 01000 - 741
- "en-bw" + // 01000 - 746
- "en-bz" + // 02809 - 751
- "en-ca" + // 01009 - 756
- "en-cc" + // 01000 - 761
- "en-ch" + // 01000 - 766
- "en-ck" + // 01000 - 771
- "en-cm" + // 01000 - 776
- "en-cx" + // 01000 - 781
- "en-cy" + // 01000 - 786
- "en-de" + // 01000 - 791
- "en-dk" + // 01000 - 796
- "en-dm" + // 01000 - 801
- "en-er" + // 01000 - 806
- "en-fi" + // 01000 - 811
- "en-fj" + // 01000 - 816
- "en-fk" + // 01000 - 821
- "en-fm" + // 01000 - 826
- "en-gb" + // 00809 - 831
- "en-gd" + // 01000 - 836
- "en-gg" + // 01000 - 841
- "en-gh" + // 01000 - 846
- "en-gi" + // 01000 - 851
- "en-gm" + // 01000 - 856
- "en-gu" + // 01000 - 861
- "en-gy" + // 01000 - 866
- "en-hk" + // 03c09 - 871
- "en-id" + // 03809 - 876
- "en-ie" + // 01809 - 881
- "en-il" + // 01000 - 886
- "en-im" + // 01000 - 891
- "en-in" + // 04009 - 896
- "en-io" + // 01000 - 901
- "en-je" + // 01000 - 906
- "en-jm" + // 02009 - 911
- "en-ke" + // 01000 - 916
- "en-ki" + // 01000 - 921
- "en-kn" + // 01000 - 926
- "en-ky" + // 01000 - 931
- "en-lc" + // 01000 - 936
- "en-lr" + // 01000 - 941
- "en-ls" + // 01000 - 946
- "en-mg" + // 01000 - 951
- "en-mh" + // 01000 - 956
- "en-mo" + // 01000 - 961
- "en-mp" + // 01000 - 966
- "en-ms" + // 01000 - 971
- "en-mt" + // 01000 - 976
- "en-mu" + // 01000 - 981
- "en-mw" + // 01000 - 986
- "en-my" + // 04409 - 991
- "en-na" + // 01000 - 996
- "en-nf" + // 01000 - 1001
- "en-ng" + // 01000 - 1006
- "en-nl" + // 01000 - 1011
- "en-nr" + // 01000 - 1016
- "en-nu" + // 01000 - 1021
- "en-nz" + // 01409 - 1026
- "en-pg" + // 01000 - 1031
- "en-ph" + // 03409 - 1036
- "en-pk" + // 01000 - 1041
- "en-pn" + // 01000 - 1046
- "en-pr" + // 01000 - 1051
- "en-pw" + // 01000 - 1056
- "en-rw" + // 01000 - 1061
- "en-sb" + // 01000 - 1066
- "en-sc" + // 01000 - 1071
- "en-sd" + // 01000 - 1076
- "en-se" + // 01000 - 1081
- "en-sg" + // 04809 - 1086
- "en-sh" + // 01000 - 1091
- "en-si" + // 01000 - 1096
- "en-sl" + // 01000 - 1101
- "en-ss" + // 01000 - 1106
- "en-sx" + // 01000 - 1111
- "en-sz" + // 01000 - 1116
- "en-tc" + // 01000 - 1121
- "en-tk" + // 01000 - 1126
- "en-to" + // 01000 - 1131
- "en-tt" + // 02c09 - 1136
- "en-tv" + // 01000 - 1141
- "en-tz" + // 01000 - 1146
- "en-ug" + // 01000 - 1151
- "en-um" + // 01000 - 1156
- "en-us" + // 00409 - 1161
- "en-vc" + // 01000 - 1166
- "en-vg" + // 01000 - 1171
- "en-vi" + // 01000 - 1176
- "en-vu" + // 01000 - 1181
- "en-ws" + // 01000 - 1186
- "en-za" + // 01c09 - 1191
- "en-zm" + // 01000 - 1196
- "en-zw" + // 03009 - 1201
- "eo" + // 01000 - 1206
- "eo-001" + // 01000 - 1208
- "es" + // 0000a - 1214
- "es-419" + // 0580a - 1216
- "es-ar" + // 02c0a - 1222
- "es-bo" + // 0400a - 1227
- "es-br" + // 01000 - 1232
- "es-cl" + // 0340a - 1237
- "es-co" + // 0240a - 1242
- "es-cr" + // 0140a - 1247
- "es-cu" + // 05c0a - 1252
- "es-do" + // 01c0a - 1257
- "es-ec" + // 0300a - 1262
- "es-es" + // 00c0a - 1267
- "es-es_tradnl" + // 0040a - 1272
- "es-gq" + // 01000 - 1284
- "es-gt" + // 0100a - 1289
- "es-hn" + // 0480a - 1294
- "es-mx" + // 0080a - 1299
- "es-ni" + // 04c0a - 1304
- "es-pa" + // 0180a - 1309
- "es-pe" + // 0280a - 1314
- "es-ph" + // 01000 - 1319
- "es-pr" + // 0500a - 1324
- "es-py" + // 03c0a - 1329
- "es-sv" + // 0440a - 1334
- "es-us" + // 0540a - 1339
- "es-uy" + // 0380a - 1344
- "es-ve" + // 0200a - 1349
- "et" + // 00025 - 1354
- "et-ee" + // 00425 - 1356
- "eu" + // 0002d - 1361
- "eu-es" + // 0042d - 1363
- "ewo" + // 01000 - 1368
- "ewo-cm" + // 01000 - 1371
- "fa" + // 00029 - 1377
- "fa-ir" + // 00429 - 1379
- "ff" + // 00067 - 1384
- "ff-cm" + // 01000 - 1386
- "ff-gn" + // 01000 - 1391
- "ff-latn" + // 07c67 - 1396
- "ff-latn-sn" + // 00867 - 1403
- "ff-mr" + // 01000 - 1413
- "ff-ng" + // 00467 - 1418
- "fi" + // 0000b - 1423
- "fi-fi" + // 0040b - 1425
- "fil" + // 00064 - 1430
- "fil-ph" + // 00464 - 1433
- "fo" + // 00038 - 1439
- "fo-dk" + // 01000 - 1441
- "fo-fo" + // 00438 - 1446
- "fr" + // 0000c - 1451
- "fr-029" + // 01c0c - 1453
- "fr-be" + // 0080c - 1459
- "fr-bf" + // 01000 - 1464
- "fr-bi" + // 01000 - 1469
- "fr-bj" + // 01000 - 1474
- "fr-bl" + // 01000 - 1479
- "fr-ca" + // 00c0c - 1484
- "fr-cd" + // 0240c - 1489
- "fr-cf" + // 01000 - 1494
- "fr-cg" + // 01000 - 1499
- "fr-ch" + // 0100c - 1504
- "fr-ci" + // 0300c - 1509
- "fr-cm" + // 02c0c - 1514
- "fr-dj" + // 01000 - 1519
- "fr-dz" + // 01000 - 1524
- "fr-fr" + // 0040c - 1529
- "fr-ga" + // 01000 - 1534
- "fr-gf" + // 01000 - 1539
- "fr-gn" + // 01000 - 1544
- "fr-gp" + // 01000 - 1549
- "fr-gq" + // 01000 - 1554
- "fr-ht" + // 03c0c - 1559
- "fr-km" + // 01000 - 1564
- "fr-lu" + // 0140c - 1569
- "fr-ma" + // 0380c - 1574
- "fr-mc" + // 0180c - 1579
- "fr-mf" + // 01000 - 1584
- "fr-mg" + // 01000 - 1589
- "fr-ml" + // 0340c - 1594
- "fr-mq" + // 01000 - 1599
- "fr-mr" + // 01000 - 1604
- "fr-mu" + // 01000 - 1609
- "fr-nc" + // 01000 - 1614
- "fr-ne" + // 01000 - 1619
- "fr-pf" + // 01000 - 1624
- "fr-pm" + // 01000 - 1629
- "fr-re" + // 0200c - 1634
- "fr-rw" + // 01000 - 1639
- "fr-sc" + // 01000 - 1644
- "fr-sn" + // 0280c - 1649
- "fr-sy" + // 01000 - 1654
- "fr-td" + // 01000 - 1659
- "fr-tg" + // 01000 - 1664
- "fr-tn" + // 01000 - 1669
- "fr-vu" + // 01000 - 1674
- "fr-wf" + // 01000 - 1679
- "fr-yt" + // 01000 - 1684
- "fur" + // 01000 - 1689
- "fur-it" + // 01000 - 1692
- "fy" + // 00062 - 1698
- "fy-nl" + // 00462 - 1700
- "ga" + // 0003c - 1705
- "ga-ie" + // 0083c - 1707
- "gd" + // 00091 - 1712
- "gd-gb" + // 00491 - 1714
- "gl" + // 00056 - 1719
- "gl-es" + // 00456 - 1721
- "gn" + // 00074 - 1726
- "gn-py" + // 00474 - 1728
- "gsw" + // 00084 - 1733
- "gsw-ch" + // 01000 - 1736
- "gsw-fr" + // 00484 - 1742
- "gsw-li" + // 01000 - 1748
- "gu" + // 00047 - 1754
- "gu-in" + // 00447 - 1756
- "guz" + // 01000 - 1761
- "guz-ke" + // 01000 - 1764
- "gv" + // 01000 - 1770
- "gv-im" + // 01000 - 1772
- "ha" + // 00068 - 1777
- "ha-latn" + // 07c68 - 1779
- "ha-latn-gh" + // 01000 - 1786
- "ha-latn-ne" + // 01000 - 1796
- "ha-latn-ng" + // 00468 - 1806
- "haw" + // 00075 - 1816
- "haw-us" + // 00475 - 1819
- "he" + // 0000d - 1825
- "he-il" + // 0040d - 1827
- "hi" + // 00039 - 1832
- "hi-in" + // 00439 - 1834
- "hr" + // 0001a - 1839
- "hr-ba" + // 0101a - 1841
- "hr-hr" + // 0041a - 1846
- "hsb" + // 0002e - 1851
- "hsb-de" + // 0042e - 1854
- "hu" + // 0000e - 1860
- "hu-hu" + // 0040e - 1862
- "hu-hu_technl" + // 1040e - 1867
- "hy" + // 0002b - 1879
- "hy-am" + // 0042b - 1881
- "ia" + // 01000 - 1886
- "ia-001" + // 01000 - 1888
- "ia-fr" + // 01000 - 1894
- "ibb" + // 00069 - 1899
- "ibb-ng" + // 00469 - 1902
- "id" + // 00021 - 1908
- "id-id" + // 00421 - 1910
- "ig" + // 00070 - 1915
- "ig-ng" + // 00470 - 1917
- "ii" + // 00078 - 1922
- "ii-cn" + // 00478 - 1924
- "is" + // 0000f - 1929
- "is-is" + // 0040f - 1931
- "it" + // 00010 - 1936
- "it-ch" + // 00810 - 1938
- "it-it" + // 00410 - 1943
- "it-sm" + // 01000 - 1948
- "iu" + // 0005d - 1953
- "iu-cans" + // 0785d - 1955
- "iu-cans-ca" + // 0045d - 1962
- "iu-latn" + // 07c5d - 1972
- "iu-latn-ca" + // 0085d - 1979
- "ja" + // 00011 - 1989
- "ja-jp" + // 00411 - 1991
- "ja-jp_radstr" + // 40411 - 1996
- "jgo" + // 01000 - 2008
- "jgo-cm" + // 01000 - 2011
- "jmc" + // 01000 - 2017
- "jmc-tz" + // 01000 - 2020
- "jv" + // 01000 - 2026
- "jv-java" + // 01000 - 2028
- "jv-java-id" + // 01000 - 2035
- "jv-latn" + // 01000 - 2045
- "jv-latn-id" + // 01000 - 2052
- "ka" + // 00037 - 2062
- "ka-ge" + // 00437 - 2064
- "ka-ge_modern" + // 10437 - 2069
- "kab" + // 01000 - 2081
- "kab-dz" + // 01000 - 2084
- "kam" + // 01000 - 2090
- "kam-ke" + // 01000 - 2093
- "kde" + // 01000 - 2099
- "kde-tz" + // 01000 - 2102
- "kea" + // 01000 - 2108
- "kea-cv" + // 01000 - 2111
- "khq" + // 01000 - 2117
- "khq-ml" + // 01000 - 2120
- "ki" + // 01000 - 2126
- "ki-ke" + // 01000 - 2128
- "kk" + // 0003f - 2133
- "kk-kz" + // 0043f - 2135
- "kkj" + // 01000 - 2140
- "kkj-cm" + // 01000 - 2143
- "kl" + // 0006f - 2149
- "kl-gl" + // 0046f - 2151
- "kln" + // 01000 - 2156
- "kln-ke" + // 01000 - 2159
- "km" + // 00053 - 2165
- "km-kh" + // 00453 - 2167
- "kn" + // 0004b - 2172
- "kn-in" + // 0044b - 2174
- "ko" + // 00012 - 2179
- "ko-kp" + // 01000 - 2181
- "ko-kr" + // 00412 - 2186
- "kok" + // 00057 - 2191
- "kok-in" + // 00457 - 2194
- "kr" + // 00071 - 2200
- "kr-ng" + // 00471 - 2202
- "ks" + // 00060 - 2207
- "ks-arab" + // 00460 - 2209
- "ks-arab-in" + // 01000 - 2216
- "ks-deva" + // 01000 - 2226
- "ks-deva-in" + // 00860 - 2233
- "ksb" + // 01000 - 2243
- "ksb-tz" + // 01000 - 2246
- "ksf" + // 01000 - 2252
- "ksf-cm" + // 01000 - 2255
- "ksh" + // 01000 - 2261
- "ksh-de" + // 01000 - 2264
- "ku" + // 00092 - 2270
- "ku-arab" + // 07c92 - 2272
- "ku-arab-iq" + // 00492 - 2279
- "ku-arab-ir" + // 01000 - 2289
- "kw" + // 01000 - 2299
- "kw-gb" + // 01000 - 2301
- "ky" + // 00040 - 2306
- "ky-kg" + // 00440 - 2308
- "la" + // 00076 - 2313
- "la-001" + // 00476 - 2315
- "lag" + // 01000 - 2321
- "lag-tz" + // 01000 - 2324
- "lb" + // 0006e - 2330
- "lb-lu" + // 0046e - 2332
- "lg" + // 01000 - 2337
- "lg-ug" + // 01000 - 2339
- "lkt" + // 01000 - 2344
- "lkt-us" + // 01000 - 2347
- "ln" + // 01000 - 2353
- "ln-ao" + // 01000 - 2355
- "ln-cd" + // 01000 - 2360
- "ln-cf" + // 01000 - 2365
- "ln-cg" + // 01000 - 2370
- "lo" + // 00054 - 2375
- "lo-la" + // 00454 - 2377
- "lrc" + // 01000 - 2382
- "lrc-iq" + // 01000 - 2385
- "lrc-ir" + // 01000 - 2391
- "lt" + // 00027 - 2397
- "lt-lt" + // 00427 - 2399
- "lu" + // 01000 - 2404
- "lu-cd" + // 01000 - 2406
- "luo" + // 01000 - 2411
- "luo-ke" + // 01000 - 2414
- "luy" + // 01000 - 2420
- "luy-ke" + // 01000 - 2423
- "lv" + // 00026 - 2429
- "lv-lv" + // 00426 - 2431
- "mas" + // 01000 - 2436
- "mas-ke" + // 01000 - 2439
- "mas-tz" + // 01000 - 2445
- "mer" + // 01000 - 2451
- "mer-ke" + // 01000 - 2454
- "mfe" + // 01000 - 2460
- "mfe-mu" + // 01000 - 2463
- "mg" + // 01000 - 2469
- "mg-mg" + // 01000 - 2471
- "mgh" + // 01000 - 2476
- "mgh-mz" + // 01000 - 2479
- "mgo" + // 01000 - 2485
- "mgo-cm" + // 01000 - 2488
- "mi" + // 00081 - 2494
- "mi-nz" + // 00481 - 2496
- "mk" + // 0002f - 2501
- "mk-mk" + // 0042f - 2503
- "ml" + // 0004c - 2508
- "ml-in" + // 0044c - 2510
- "mn" + // 00050 - 2515
- "mn-cyrl" + // 07850 - 2517
- "mn-mn" + // 00450 - 2524
- "mn-mong" + // 07c50 - 2529
- "mn-mong-cn" + // 00850 - 2536
- "mn-mong-mn" + // 00c50 - 2546
- "mni" + // 00058 - 2556
- "mni-in" + // 00458 - 2559
- "moh" + // 0007c - 2565
- "moh-ca" + // 0047c - 2568
- "mr" + // 0004e - 2574
- "mr-in" + // 0044e - 2576
- "ms" + // 0003e - 2581
- "ms-bn" + // 0083e - 2583
- "ms-my" + // 0043e - 2588
- "ms-sg" + // 01000 - 2593
- "mt" + // 0003a - 2598
- "mt-mt" + // 0043a - 2600
- "mua" + // 01000 - 2605
- "mua-cm" + // 01000 - 2608
- "my" + // 00055 - 2614
- "my-mm" + // 00455 - 2616
- "mzn" + // 01000 - 2621
- "mzn-ir" + // 01000 - 2624
- "naq" + // 01000 - 2630
- "naq-na" + // 01000 - 2633
- "nb" + // 07c14 - 2639
- "nb-no" + // 00414 - 2641
- "nb-sj" + // 01000 - 2646
- "nd" + // 01000 - 2651
- "nd-zw" + // 01000 - 2653
- "nds" + // 01000 - 2658
- "nds-de" + // 01000 - 2661
- "nds-nl" + // 01000 - 2667
- "ne" + // 00061 - 2673
- "ne-in" + // 00861 - 2675
- "ne-np" + // 00461 - 2680
- "nl" + // 00013 - 2685
- "nl-aw" + // 01000 - 2687
- "nl-be" + // 00813 - 2692
- "nl-bq" + // 01000 - 2697
- "nl-cw" + // 01000 - 2702
- "nl-nl" + // 00413 - 2707
- "nl-sr" + // 01000 - 2712
- "nl-sx" + // 01000 - 2717
- "nmg" + // 01000 - 2722
- "nmg-cm" + // 01000 - 2725
- "nn" + // 07814 - 2731
- "nn-no" + // 00814 - 2733
- "nnh" + // 01000 - 2738
- "nnh-cm" + // 01000 - 2741
- "no" + // 00014 - 2747
- "nqo" + // 01000 - 2749
- "nqo-gn" + // 01000 - 2752
- "nr" + // 01000 - 2758
- "nr-za" + // 01000 - 2760
- "nso" + // 0006c - 2765
- "nso-za" + // 0046c - 2768
- "nus" + // 01000 - 2774
- "nus-ss" + // 01000 - 2777
- "nyn" + // 01000 - 2783
- "nyn-ug" + // 01000 - 2786
- "oc" + // 00082 - 2792
- "oc-fr" + // 00482 - 2794
- "om" + // 00072 - 2799
- "om-et" + // 00472 - 2801
- "om-ke" + // 01000 - 2806
- "or" + // 00048 - 2811
- "or-in" + // 00448 - 2813
- "os" + // 01000 - 2818
- "os-ge" + // 01000 - 2820
- "os-ru" + // 01000 - 2825
- "pa" + // 00046 - 2830
- "pa-arab" + // 07c46 - 2832
- "pa-arab-pk" + // 00846 - 2839
- "pa-in" + // 00446 - 2849
- "pap" + // 00079 - 2854
- "pap-029" + // 00479 - 2857
- "pl" + // 00015 - 2864
- "pl-pl" + // 00415 - 2866
- "prg" + // 01000 - 2871
- "prg-001" + // 01000 - 2874
- "prs" + // 0008c - 2881
- "prs-af" + // 0048c - 2884
- "ps" + // 00063 - 2890
- "ps-af" + // 00463 - 2892
- "pt" + // 00016 - 2897
- "pt-ao" + // 01000 - 2899
- "pt-br" + // 00416 - 2904
- "pt-ch" + // 01000 - 2909
- "pt-cv" + // 01000 - 2914
- "pt-gq" + // 01000 - 2919
- "pt-gw" + // 01000 - 2924
- "pt-lu" + // 01000 - 2929
- "pt-mo" + // 01000 - 2934
- "pt-mz" + // 01000 - 2939
- "pt-pt" + // 00816 - 2944
- "pt-st" + // 01000 - 2949
- "pt-tl" + // 01000 - 2954
- "qps-latn-x-sh" + // 00901 - 2959
- "qps-ploc" + // 00501 - 2972
- "qps-ploca" + // 005fe - 2980
- "qps-plocm" + // 009ff - 2989
- "quc" + // 00086 - 2998
- "quc-latn" + // 07c86 - 3001
- "quc-latn-gt" + // 00486 - 3009
- "quz" + // 0006b - 3020
- "quz-bo" + // 0046b - 3023
- "quz-ec" + // 0086b - 3029
- "quz-pe" + // 00c6b - 3035
- "rm" + // 00017 - 3041
- "rm-ch" + // 00417 - 3043
- "rn" + // 01000 - 3048
- "rn-bi" + // 01000 - 3050
- "ro" + // 00018 - 3055
- "ro-md" + // 00818 - 3057
- "ro-ro" + // 00418 - 3062
- "rof" + // 01000 - 3067
- "rof-tz" + // 01000 - 3070
- "ru" + // 00019 - 3076
- "ru-by" + // 01000 - 3078
- "ru-kg" + // 01000 - 3083
- "ru-kz" + // 01000 - 3088
- "ru-md" + // 00819 - 3093
- "ru-ru" + // 00419 - 3098
- "ru-ua" + // 01000 - 3103
- "rw" + // 00087 - 3108
- "rw-rw" + // 00487 - 3110
- "rwk" + // 01000 - 3115
- "rwk-tz" + // 01000 - 3118
- "sa" + // 0004f - 3124
- "sa-in" + // 0044f - 3126
- "sah" + // 00085 - 3131
- "sah-ru" + // 00485 - 3134
- "saq" + // 01000 - 3140
- "saq-ke" + // 01000 - 3143
- "sbp" + // 01000 - 3149
- "sbp-tz" + // 01000 - 3152
- "sd" + // 00059 - 3158
- "sd-arab" + // 07c59 - 3160
- "sd-arab-pk" + // 00859 - 3167
- "sd-deva" + // 01000 - 3177
- "sd-deva-in" + // 00459 - 3184
- "se" + // 0003b - 3194
- "se-fi" + // 00c3b - 3196
- "se-no" + // 0043b - 3201
- "se-se" + // 0083b - 3206
- "seh" + // 01000 - 3211
- "seh-mz" + // 01000 - 3214
- "ses" + // 01000 - 3220
- "ses-ml" + // 01000 - 3223
- "sg" + // 01000 - 3229
- "sg-cf" + // 01000 - 3231
- "shi" + // 01000 - 3236
- "shi-latn" + // 01000 - 3239
- "shi-latn-ma" + // 01000 - 3247
- "shi-tfng" + // 01000 - 3258
- "shi-tfng-ma" + // 01000 - 3266
- "si" + // 0005b - 3277
- "si-lk" + // 0045b - 3279
- "sk" + // 0001b - 3284
- "sk-sk" + // 0041b - 3286
- "sl" + // 00024 - 3291
- "sl-si" + // 00424 - 3293
- "sma" + // 0783b - 3298
- "sma-no" + // 0183b - 3301
- "sma-se" + // 01c3b - 3307
- "smj" + // 07c3b - 3313
- "smj-no" + // 0103b - 3316
- "smj-se" + // 0143b - 3322
- "smn" + // 0703b - 3328
- "smn-fi" + // 0243b - 3331
- "sms" + // 0743b - 3337
- "sms-fi" + // 0203b - 3340
- "sn" + // 01000 - 3346
- "sn-latn" + // 01000 - 3348
- "sn-latn-zw" + // 01000 - 3355
- "so" + // 00077 - 3365
- "so-dj" + // 01000 - 3367
- "so-et" + // 01000 - 3372
- "so-ke" + // 01000 - 3377
- "so-so" + // 00477 - 3382
- "sq" + // 0001c - 3387
- "sq-al" + // 0041c - 3389
- "sq-mk" + // 01000 - 3394
- "sq-xk" + // 01000 - 3399
- "sr" + // 07c1a - 3404
- "sr-cyrl" + // 06c1a - 3406
- "sr-cyrl-ba" + // 01c1a - 3413
- "sr-cyrl-cs" + // 00c1a - 3423
- "sr-cyrl-me" + // 0301a - 3433
- "sr-cyrl-rs" + // 0281a - 3443
- "sr-cyrl-xk" + // 01000 - 3453
- "sr-latn" + // 0701a - 3463
- "sr-latn-ba" + // 0181a - 3470
- "sr-latn-cs" + // 0081a - 3480
- "sr-latn-me" + // 02c1a - 3490
- "sr-latn-rs" + // 0241a - 3500
- "sr-latn-xk" + // 01000 - 3510
- "ss" + // 01000 - 3520
- "ss-sz" + // 01000 - 3522
- "ss-za" + // 01000 - 3527
- "ssy" + // 01000 - 3532
- "ssy-er" + // 01000 - 3535
- "st" + // 00030 - 3541
- "st-ls" + // 01000 - 3543
- "st-za" + // 00430 - 3548
- "sv" + // 0001d - 3553
- "sv-ax" + // 01000 - 3555
- "sv-fi" + // 0081d - 3560
- "sv-se" + // 0041d - 3565
- "sw" + // 00041 - 3570
- "sw-cd" + // 01000 - 3572
- "sw-ke" + // 00441 - 3577
- "sw-tz" + // 01000 - 3582
- "sw-ug" + // 01000 - 3587
- "swc" + // 01000 - 3592
- "swc-cd" + // 01000 - 3595
- "syr" + // 0005a - 3601
- "syr-sy" + // 0045a - 3604
- "ta" + // 00049 - 3610
- "ta-in" + // 00449 - 3612
- "ta-lk" + // 00849 - 3617
- "ta-my" + // 01000 - 3622
- "ta-sg" + // 01000 - 3627
- "te" + // 0004a - 3632
- "te-in" + // 0044a - 3634
- "teo" + // 01000 - 3639
- "teo-ke" + // 01000 - 3642
- "teo-ug" + // 01000 - 3648
- "tg" + // 00028 - 3654
- "tg-cyrl" + // 07c28 - 3656
- "tg-cyrl-tj" + // 00428 - 3663
- "th" + // 0001e - 3673
- "th-th" + // 0041e - 3675
- "ti" + // 00073 - 3680
- "ti-er" + // 00873 - 3682
- "ti-et" + // 00473 - 3687
- "tig" + // 01000 - 3692
- "tig-er" + // 01000 - 3695
- "tk" + // 00042 - 3701
- "tk-tm" + // 00442 - 3703
- "tn" + // 00032 - 3708
- "tn-bw" + // 00832 - 3710
- "tn-za" + // 00432 - 3715
- "to" + // 01000 - 3720
- "to-to" + // 01000 - 3722
- "tr" + // 0001f - 3727
- "tr-cy" + // 01000 - 3729
- "tr-tr" + // 0041f - 3734
- "ts" + // 00031 - 3739
- "ts-za" + // 00431 - 3741
- "tt" + // 00044 - 3746
- "tt-ru" + // 00444 - 3748
- "twq" + // 01000 - 3753
- "twq-ne" + // 01000 - 3756
- "tzm" + // 0005f - 3762
- "tzm-arab" + // 01000 - 3765
- "tzm-arab-ma" + // 0045f - 3773
- "tzm-latn" + // 07c5f - 3784
- "tzm-latn-dz" + // 0085f - 3792
- "tzm-latn-ma" + // 01000 - 3803
- "tzm-tfng" + // 0785f - 3814
- "tzm-tfng-ma" + // 0105f - 3822
- "ug" + // 00080 - 3833
- "ug-cn" + // 00480 - 3835
- "uk" + // 00022 - 3840
- "uk-ua" + // 00422 - 3842
- "ur" + // 00020 - 3847
- "ur-in" + // 00820 - 3849
- "ur-pk" + // 00420 - 3854
- "uz" + // 00043 - 3859
- "uz-arab" + // 01000 - 3861
- "uz-arab-af" + // 01000 - 3868
- "uz-cyrl" + // 07843 - 3878
- "uz-cyrl-uz" + // 00843 - 3885
- "uz-latn" + // 07c43 - 3895
- "uz-latn-uz" + // 00443 - 3902
- "vai" + // 01000 - 3912
- "vai-latn" + // 01000 - 3915
- "vai-latn-lr" + // 01000 - 3923
- "vai-vaii" + // 01000 - 3934
- "vai-vaii-lr" + // 01000 - 3942
- "ve" + // 00033 - 3953
- "ve-za" + // 00433 - 3955
- "vi" + // 0002a - 3960
- "vi-vn" + // 0042a - 3962
- "vo" + // 01000 - 3967
- "vo-001" + // 01000 - 3969
- "vun" + // 01000 - 3975
- "vun-tz" + // 01000 - 3978
- "wae" + // 01000 - 3984
- "wae-ch" + // 01000 - 3987
- "wal" + // 01000 - 3993
- "wal-et" + // 01000 - 3996
- "wo" + // 00088 - 4002
- "wo-sn" + // 00488 - 4004
- "x-iv_mathan" + // 1007f - 4009
- "xh" + // 00034 - 4020
- "xh-za" + // 00434 - 4022
- "xog" + // 01000 - 4027
- "xog-ug" + // 01000 - 4030
- "yav" + // 01000 - 4036
- "yav-cm" + // 01000 - 4039
- "yi" + // 0003d - 4045
- "yi-001" + // 0043d - 4047
- "yo" + // 0006a - 4053
- "yo-bj" + // 01000 - 4055
- "yo-ng" + // 0046a - 4060
- "yue" + // 01000 - 4065
- "yue-hk" + // 01000 - 4068
- "zgh" + // 01000 - 4074
- "zgh-tfng" + // 01000 - 4077
- "zgh-tfng-ma" + // 01000 - 4085
- "zh" + // 07804 - 4096
- "zh-chs" + // 00004 - 4098
- "zh-cht" + // 07c04 - 4104
- "zh-cn" + // 00804 - 4110
- "zh-cn_phoneb" + // 50804 - 4115
- "zh-cn_stroke" + // 20804 - 4127
- "zh-hans" + // 00004 - 4139
- "zh-hans-hk" + // 01000 - 4146
- "zh-hans-mo" + // 01000 - 4156
- "zh-hant" + // 07c04 - 4166
- "zh-hk" + // 00c04 - 4173
- "zh-hk_radstr" + // 40c04 - 4178
- "zh-mo" + // 01404 - 4190
- "zh-mo_radstr" + // 41404 - 4195
- "zh-mo_stroke" + // 21404 - 4207
- "zh-sg" + // 01004 - 4219
- "zh-sg_phoneb" + // 51004 - 4224
- "zh-sg_stroke" + // 21004 - 4236
- "zh-tw" + // 00404 - 4248
- "zh-tw_pronun" + // 30404 - 4253
- "zh-tw_radstr" + // 40404 - 4265
- "zu" + // 00035 - 4277
- "zu-za"; // 00435 - 4279
-
- // c_threeLetterWindowsLanguageName is string containing 3-letter Windows language names
- // every 3-characters entry is matching locale name entry in c_localeNames
-
- private const string c_threeLetterWindowsLanguageName =
- "ZZZ" + // aa
- "ZZZ" + // aa-dj
- "ZZZ" + // aa-er
- "ZZZ" + // aa-et
- "AFK" + // af
- "ZZZ" + // af-na
- "AFK" + // af-za
- "ZZZ" + // agq
- "ZZZ" + // agq-cm
- "ZZZ" + // ak
- "ZZZ" + // ak-gh
- "AMH" + // am
- "AMH" + // am-et
- "ARA" + // ar
- "ZZZ" + // ar-001
- "ARU" + // ar-ae
- "ARH" + // ar-bh
- "ZZZ" + // ar-dj
- "ARG" + // ar-dz
- "ARE" + // ar-eg
- "ZZZ" + // ar-er
- "ZZZ" + // ar-il
- "ARI" + // ar-iq
- "ARJ" + // ar-jo
- "ZZZ" + // ar-km
- "ARK" + // ar-kw
- "ARB" + // ar-lb
- "ARL" + // ar-ly
- "ARM" + // ar-ma
- "ZZZ" + // ar-mr
- "ARO" + // ar-om
- "ZZZ" + // ar-ps
- "ARQ" + // ar-qa
- "ARA" + // ar-sa
- "ZZZ" + // ar-sd
- "ZZZ" + // ar-so
- "ZZZ" + // ar-ss
- "ARS" + // ar-sy
- "ZZZ" + // ar-td
- "ART" + // ar-tn
- "ARY" + // ar-ye
- "MPD" + // arn
- "MPD" + // arn-cl
- "ASM" + // as
- "ASM" + // as-in
- "ZZZ" + // asa
- "ZZZ" + // asa-tz
- "ZZZ" + // ast
- "ZZZ" + // ast-es
- "AZE" + // az
- "AZC" + // az-cyrl
- "AZC" + // az-cyrl-az
- "AZE" + // az-latn
- "AZE" + // az-latn-az
- "BAS" + // ba
- "BAS" + // ba-ru
- "ZZZ" + // bas
- "ZZZ" + // bas-cm
- "BEL" + // be
- "BEL" + // be-by
- "ZZZ" + // bem
- "ZZZ" + // bem-zm
- "ZZZ" + // bez
- "ZZZ" + // bez-tz
- "BGR" + // bg
- "BGR" + // bg-bg
- "ZZZ" + // bin
- "ZZZ" + // bin-ng
- "ZZZ" + // bm
- "ZZZ" + // bm-latn
- "ZZZ" + // bm-latn-ml
- "BNB" + // bn
- "BNB" + // bn-bd
- "BNG" + // bn-in
- "BOB" + // bo
- "BOB" + // bo-cn
- "ZZZ" + // bo-in
- "BRE" + // br
- "BRE" + // br-fr
- "ZZZ" + // brx
- "ZZZ" + // brx-in
- "BSB" + // bs
- "BSC" + // bs-cyrl
- "BSC" + // bs-cyrl-ba
- "BSB" + // bs-latn
- "BSB" + // bs-latn-ba
- "ZZZ" + // byn
- "ZZZ" + // byn-er
- "CAT" + // ca
- "ZZZ" + // ca-ad
- "CAT" + // ca-es
- "VAL" + // ca-es-valencia
- "ZZZ" + // ca-fr
- "ZZZ" + // ca-it
- "ZZZ" + // ce
- "ZZZ" + // ce-ru
- "ZZZ" + // cgg
- "ZZZ" + // cgg-ug
- "CRE" + // chr
- "CRE" + // chr-cher
- "CRE" + // chr-cher-us
- "COS" + // co
- "COS" + // co-fr
- "CSY" + // cs
- "CSY" + // cs-cz
- "ZZZ" + // cu
- "ZZZ" + // cu-ru
- "CYM" + // cy
- "CYM" + // cy-gb
- "DAN" + // da
- "DAN" + // da-dk
- "ZZZ" + // da-gl
- "ZZZ" + // dav
- "ZZZ" + // dav-ke
- "DEU" + // de
- "DEA" + // de-at
- "ZZZ" + // de-be
- "DES" + // de-ch
- "DEU" + // de-de
- "DEU" + // de-de_phoneb
- "ZZZ" + // de-it
- "DEC" + // de-li
- "DEL" + // de-lu
- "ZZZ" + // dje
- "ZZZ" + // dje-ne
- "DSB" + // dsb
- "DSB" + // dsb-de
- "ZZZ" + // dua
- "ZZZ" + // dua-cm
- "DIV" + // dv
- "DIV" + // dv-mv
- "ZZZ" + // dyo
- "ZZZ" + // dyo-sn
- "ZZZ" + // dz
- "ZZZ" + // dz-bt
- "ZZZ" + // ebu
- "ZZZ" + // ebu-ke
- "ZZZ" + // ee
- "ZZZ" + // ee-gh
- "ZZZ" + // ee-tg
- "ELL" + // el
- "ZZZ" + // el-cy
- "ELL" + // el-gr
- "ENU" + // en
- "ZZZ" + // en-001
- "ENB" + // en-029
- "ZZZ" + // en-150
- "ZZZ" + // en-ag
- "ZZZ" + // en-ai
- "ZZZ" + // en-as
- "ZZZ" + // en-at
- "ENA" + // en-au
- "ZZZ" + // en-bb
- "ZZZ" + // en-be
- "ZZZ" + // en-bi
- "ZZZ" + // en-bm
- "ZZZ" + // en-bs
- "ZZZ" + // en-bw
- "ENL" + // en-bz
- "ENC" + // en-ca
- "ZZZ" + // en-cc
- "ZZZ" + // en-ch
- "ZZZ" + // en-ck
- "ZZZ" + // en-cm
- "ZZZ" + // en-cx
- "ZZZ" + // en-cy
- "ZZZ" + // en-de
- "ZZZ" + // en-dk
- "ZZZ" + // en-dm
- "ZZZ" + // en-er
- "ZZZ" + // en-fi
- "ZZZ" + // en-fj
- "ZZZ" + // en-fk
- "ZZZ" + // en-fm
- "ENG" + // en-gb
- "ZZZ" + // en-gd
- "ZZZ" + // en-gg
- "ZZZ" + // en-gh
- "ZZZ" + // en-gi
- "ZZZ" + // en-gm
- "ZZZ" + // en-gu
- "ZZZ" + // en-gy
- "ENH" + // en-hk
- "ZZZ" + // en-id
- "ENI" + // en-ie
- "ZZZ" + // en-il
- "ZZZ" + // en-im
- "ENN" + // en-in
- "ZZZ" + // en-io
- "ZZZ" + // en-je
- "ENJ" + // en-jm
- "ZZZ" + // en-ke
- "ZZZ" + // en-ki
- "ZZZ" + // en-kn
- "ZZZ" + // en-ky
- "ZZZ" + // en-lc
- "ZZZ" + // en-lr
- "ZZZ" + // en-ls
- "ZZZ" + // en-mg
- "ZZZ" + // en-mh
- "ZZZ" + // en-mo
- "ZZZ" + // en-mp
- "ZZZ" + // en-ms
- "ZZZ" + // en-mt
- "ZZZ" + // en-mu
- "ZZZ" + // en-mw
- "ENM" + // en-my
- "ZZZ" + // en-na
- "ZZZ" + // en-nf
- "ZZZ" + // en-ng
- "ZZZ" + // en-nl
- "ZZZ" + // en-nr
- "ZZZ" + // en-nu
- "ENZ" + // en-nz
- "ZZZ" + // en-pg
- "ENP" + // en-ph
- "ZZZ" + // en-pk
- "ZZZ" + // en-pn
- "ZZZ" + // en-pr
- "ZZZ" + // en-pw
- "ZZZ" + // en-rw
- "ZZZ" + // en-sb
- "ZZZ" + // en-sc
- "ZZZ" + // en-sd
- "ZZZ" + // en-se
- "ENE" + // en-sg
- "ZZZ" + // en-sh
- "ZZZ" + // en-si
- "ZZZ" + // en-sl
- "ZZZ" + // en-ss
- "ZZZ" + // en-sx
- "ZZZ" + // en-sz
- "ZZZ" + // en-tc
- "ZZZ" + // en-tk
- "ZZZ" + // en-to
- "ENT" + // en-tt
- "ZZZ" + // en-tv
- "ZZZ" + // en-tz
- "ZZZ" + // en-ug
- "ZZZ" + // en-um
- "ENU" + // en-us
- "ZZZ" + // en-vc
- "ZZZ" + // en-vg
- "ZZZ" + // en-vi
- "ZZZ" + // en-vu
- "ZZZ" + // en-ws
- "ENS" + // en-za
- "ZZZ" + // en-zm
- "ENW" + // en-zw
- "ZZZ" + // eo
- "ZZZ" + // eo-001
- "ESN" + // es
- "ESJ" + // es-419
- "ESS" + // es-ar
- "ESB" + // es-bo
- "ZZZ" + // es-br
- "ESL" + // es-cl
- "ESO" + // es-co
- "ESC" + // es-cr
- "ESK" + // es-cu
- "ESD" + // es-do
- "ESF" + // es-ec
- "ESN" + // es-es
- "ESP" + // es-es_tradnl
- "ZZZ" + // es-gq
- "ESG" + // es-gt
- "ESH" + // es-hn
- "ESM" + // es-mx
- "ESI" + // es-ni
- "ESA" + // es-pa
- "ESR" + // es-pe
- "ZZZ" + // es-ph
- "ESU" + // es-pr
- "ESZ" + // es-py
- "ESE" + // es-sv
- "EST" + // es-us
- "ESY" + // es-uy
- "ESV" + // es-ve
- "ETI" + // et
- "ETI" + // et-ee
- "EUQ" + // eu
- "EUQ" + // eu-es
- "ZZZ" + // ewo
- "ZZZ" + // ewo-cm
- "FAR" + // fa
- "FAR" + // fa-ir
- "FUL" + // ff
- "ZZZ" + // ff-cm
- "ZZZ" + // ff-gn
- "FUL" + // ff-latn
- "FUL" + // ff-latn-sn
- "ZZZ" + // ff-mr
- "ZZZ" + // ff-ng
- "FIN" + // fi
- "FIN" + // fi-fi
- "FPO" + // fil
- "FPO" + // fil-ph
- "FOS" + // fo
- "ZZZ" + // fo-dk
- "FOS" + // fo-fo
- "FRA" + // fr
- "ZZZ" + // fr-029
- "FRB" + // fr-be
- "ZZZ" + // fr-bf
- "ZZZ" + // fr-bi
- "ZZZ" + // fr-bj
- "ZZZ" + // fr-bl
- "FRC" + // fr-ca
- "FRD" + // fr-cd
- "ZZZ" + // fr-cf
- "ZZZ" + // fr-cg
- "FRS" + // fr-ch
- "FRI" + // fr-ci
- "FRE" + // fr-cm
- "ZZZ" + // fr-dj
- "ZZZ" + // fr-dz
- "FRA" + // fr-fr
- "ZZZ" + // fr-ga
- "ZZZ" + // fr-gf
- "ZZZ" + // fr-gn
- "ZZZ" + // fr-gp
- "ZZZ" + // fr-gq
- "FRH" + // fr-ht
- "ZZZ" + // fr-km
- "FRL" + // fr-lu
- "FRO" + // fr-ma
- "FRM" + // fr-mc
- "ZZZ" + // fr-mf
- "ZZZ" + // fr-mg
- "FRF" + // fr-ml
- "ZZZ" + // fr-mq
- "ZZZ" + // fr-mr
- "ZZZ" + // fr-mu
- "ZZZ" + // fr-nc
- "ZZZ" + // fr-ne
- "ZZZ" + // fr-pf
- "ZZZ" + // fr-pm
- "FRR" + // fr-re
- "ZZZ" + // fr-rw
- "ZZZ" + // fr-sc
- "FRN" + // fr-sn
- "ZZZ" + // fr-sy
- "ZZZ" + // fr-td
- "ZZZ" + // fr-tg
- "ZZZ" + // fr-tn
- "ZZZ" + // fr-vu
- "ZZZ" + // fr-wf
- "ZZZ" + // fr-yt
- "ZZZ" + // fur
- "ZZZ" + // fur-it
- "FYN" + // fy
- "FYN" + // fy-nl
- "IRE" + // ga
- "IRE" + // ga-ie
- "GLA" + // gd
- "GLA" + // gd-gb
- "GLC" + // gl
- "GLC" + // gl-es
- "GRN" + // gn
- "GRN" + // gn-py
- "ZZZ" + // gsw
- "ZZZ" + // gsw-ch
- "GSW" + // gsw-fr
- "ZZZ" + // gsw-li
- "GUJ" + // gu
- "GUJ" + // gu-in
- "ZZZ" + // guz
- "ZZZ" + // guz-ke
- "ZZZ" + // gv
- "ZZZ" + // gv-im
- "HAU" + // ha
- "HAU" + // ha-latn
- "ZZZ" + // ha-latn-gh
- "ZZZ" + // ha-latn-ne
- "HAU" + // ha-latn-ng
- "HAW" + // haw
- "HAW" + // haw-us
- "HEB" + // he
- "HEB" + // he-il
- "HIN" + // hi
- "HIN" + // hi-in
- "HRV" + // hr
- "HRB" + // hr-ba
- "HRV" + // hr-hr
- "HSB" + // hsb
- "HSB" + // hsb-de
- "HUN" + // hu
- "HUN" + // hu-hu
- "HUN" + // hu-hu_technl
- "HYE" + // hy
- "HYE" + // hy-am
- "ZZZ" + // ia
- "ZZZ" + // ia-001
- "ZZZ" + // ia-fr
- "ZZZ" + // ibb
- "ZZZ" + // ibb-ng
- "IND" + // id
- "IND" + // id-id
- "IBO" + // ig
- "IBO" + // ig-ng
- "III" + // ii
- "III" + // ii-cn
- "ISL" + // is
- "ISL" + // is-is
- "ITA" + // it
- "ITS" + // it-ch
- "ITA" + // it-it
- "ZZZ" + // it-sm
- "IUK" + // iu
- "IUS" + // iu-cans
- "IUS" + // iu-cans-ca
- "IUK" + // iu-latn
- "IUK" + // iu-latn-ca
- "JPN" + // ja
- "JPN" + // ja-jp
- "JPN" + // ja-jp_radstr
- "ZZZ" + // jgo
- "ZZZ" + // jgo-cm
- "ZZZ" + // jmc
- "ZZZ" + // jmc-tz
- "JAV" + // jv
- "ZZZ" + // jv-java
- "ZZZ" + // jv-java-id
- "JAV" + // jv-latn
- "JAV" + // jv-latn-id
- "KAT" + // ka
- "KAT" + // ka-ge
- "KAT" + // ka-ge_modern
- "ZZZ" + // kab
- "ZZZ" + // kab-dz
- "ZZZ" + // kam
- "ZZZ" + // kam-ke
- "ZZZ" + // kde
- "ZZZ" + // kde-tz
- "ZZZ" + // kea
- "ZZZ" + // kea-cv
- "ZZZ" + // khq
- "ZZZ" + // khq-ml
- "ZZZ" + // ki
- "ZZZ" + // ki-ke
- "KKZ" + // kk
- "KKZ" + // kk-kz
- "ZZZ" + // kkj
- "ZZZ" + // kkj-cm
- "KAL" + // kl
- "KAL" + // kl-gl
- "ZZZ" + // kln
- "ZZZ" + // kln-ke
- "KHM" + // km
- "KHM" + // km-kh
- "KDI" + // kn
- "KDI" + // kn-in
- "KOR" + // ko
- "ZZZ" + // ko-kp
- "KOR" + // ko-kr
- "KNK" + // kok
- "KNK" + // kok-in
- "ZZZ" + // kr
- "ZZZ" + // kr-ng
- "ZZZ" + // ks
- "ZZZ" + // ks-arab
- "ZZZ" + // ks-arab-in
- "ZZZ" + // ks-deva
- "ZZZ" + // ks-deva-in
- "ZZZ" + // ksb
- "ZZZ" + // ksb-tz
- "ZZZ" + // ksf
- "ZZZ" + // ksf-cm
- "ZZZ" + // ksh
- "ZZZ" + // ksh-de
- "KUR" + // ku
- "KUR" + // ku-arab
- "KUR" + // ku-arab-iq
- "ZZZ" + // ku-arab-ir
- "ZZZ" + // kw
- "ZZZ" + // kw-gb
- "KYR" + // ky
- "KYR" + // ky-kg
- "ZZZ" + // la
- "ZZZ" + // la-001
- "ZZZ" + // lag
- "ZZZ" + // lag-tz
- "LBX" + // lb
- "LBX" + // lb-lu
- "ZZZ" + // lg
- "ZZZ" + // lg-ug
- "ZZZ" + // lkt
- "ZZZ" + // lkt-us
- "ZZZ" + // ln
- "ZZZ" + // ln-ao
- "ZZZ" + // ln-cd
- "ZZZ" + // ln-cf
- "ZZZ" + // ln-cg
- "LAO" + // lo
- "LAO" + // lo-la
- "ZZZ" + // lrc
- "ZZZ" + // lrc-iq
- "ZZZ" + // lrc-ir
- "LTH" + // lt
- "LTH" + // lt-lt
- "ZZZ" + // lu
- "ZZZ" + // lu-cd
- "ZZZ" + // luo
- "ZZZ" + // luo-ke
- "ZZZ" + // luy
- "ZZZ" + // luy-ke
- "LVI" + // lv
- "LVI" + // lv-lv
- "ZZZ" + // mas
- "ZZZ" + // mas-ke
- "ZZZ" + // mas-tz
- "ZZZ" + // mer
- "ZZZ" + // mer-ke
- "ZZZ" + // mfe
- "ZZZ" + // mfe-mu
- "MLG" + // mg
- "MLG" + // mg-mg
- "ZZZ" + // mgh
- "ZZZ" + // mgh-mz
- "ZZZ" + // mgo
- "ZZZ" + // mgo-cm
- "MRI" + // mi
- "MRI" + // mi-nz
- "MKI" + // mk
- "MKI" + // mk-mk
- "MYM" + // ml
- "MYM" + // ml-in
- "MNN" + // mn
- "MNN" + // mn-cyrl
- "MNN" + // mn-mn
- "MNG" + // mn-mong
- "MNG" + // mn-mong-cn
- "MNM" + // mn-mong-mn
- "ZZZ" + // mni
- "ZZZ" + // mni-in
- "MWK" + // moh
- "MWK" + // moh-ca
- "MAR" + // mr
- "MAR" + // mr-in
- "MSL" + // ms
- "MSB" + // ms-bn
- "MSL" + // ms-my
- "ZZZ" + // ms-sg
- "MLT" + // mt
- "MLT" + // mt-mt
- "ZZZ" + // mua
- "ZZZ" + // mua-cm
- "MYA" + // my
- "MYA" + // my-mm
- "ZZZ" + // mzn
- "ZZZ" + // mzn-ir
- "ZZZ" + // naq
- "ZZZ" + // naq-na
- "NOR" + // nb
- "NOR" + // nb-no
- "ZZZ" + // nb-sj
- "ZZZ" + // nd
- "ZZZ" + // nd-zw
- "ZZZ" + // nds
- "ZZZ" + // nds-de
- "ZZZ" + // nds-nl
- "NEP" + // ne
- "NEI" + // ne-in
- "NEP" + // ne-np
- "NLD" + // nl
- "ZZZ" + // nl-aw
- "NLB" + // nl-be
- "ZZZ" + // nl-bq
- "ZZZ" + // nl-cw
- "NLD" + // nl-nl
- "ZZZ" + // nl-sr
- "ZZZ" + // nl-sx
- "ZZZ" + // nmg
- "ZZZ" + // nmg-cm
- "NON" + // nn
- "NON" + // nn-no
- "ZZZ" + // nnh
- "ZZZ" + // nnh-cm
- "NOR" + // no
- "NQO" + // nqo
- "NQO" + // nqo-gn
- "ZZZ" + // nr
- "ZZZ" + // nr-za
- "NSO" + // nso
- "NSO" + // nso-za
- "ZZZ" + // nus
- "ZZZ" + // nus-ss
- "ZZZ" + // nyn
- "ZZZ" + // nyn-ug
- "OCI" + // oc
- "OCI" + // oc-fr
- "ORM" + // om
- "ORM" + // om-et
- "ZZZ" + // om-ke
- "ORI" + // or
- "ORI" + // or-in
- "ZZZ" + // os
- "ZZZ" + // os-ge
- "ZZZ" + // os-ru
- "PAN" + // pa
- "PAP" + // pa-arab
- "PAP" + // pa-arab-pk
- "PAN" + // pa-in
- "ZZZ" + // pap
- "ZZZ" + // pap-029
- "PLK" + // pl
- "PLK" + // pl-pl
- "ZZZ" + // prg
- "ZZZ" + // prg-001
- "PRS" + // prs
- "PRS" + // prs-af
- "PAS" + // ps
- "PAS" + // ps-af
- "PTB" + // pt
- "PTA" + // pt-ao
- "PTB" + // pt-br
- "ZZZ" + // pt-ch
- "ZZZ" + // pt-cv
- "ZZZ" + // pt-gq
- "ZZZ" + // pt-gw
- "ZZZ" + // pt-lu
- "ZZZ" + // pt-mo
- "ZZZ" + // pt-mz
- "PTG" + // pt-pt
- "ZZZ" + // pt-st
- "ZZZ" + // pt-tl
- "ENJ" + // qps-latn-x-sh
- "ENU" + // qps-ploc
- "JPN" + // qps-ploca
- "ARA" + // qps-plocm
- "QUT" + // quc
- "QUT" + // quc-latn
- "QUT" + // quc-latn-gt
- "QUB" + // quz
- "QUB" + // quz-bo
- "QUE" + // quz-ec
- "QUP" + // quz-pe
- "RMC" + // rm
- "RMC" + // rm-ch
- "ZZZ" + // rn
- "ZZZ" + // rn-bi
- "ROM" + // ro
- "ROD" + // ro-md
- "ROM" + // ro-ro
- "ZZZ" + // rof
- "ZZZ" + // rof-tz
- "RUS" + // ru
- "ZZZ" + // ru-by
- "ZZZ" + // ru-kg
- "ZZZ" + // ru-kz
- "RUM" + // ru-md
- "RUS" + // ru-ru
- "ZZZ" + // ru-ua
- "KIN" + // rw
- "KIN" + // rw-rw
- "ZZZ" + // rwk
- "ZZZ" + // rwk-tz
- "SAN" + // sa
- "SAN" + // sa-in
- "SAH" + // sah
- "SAH" + // sah-ru
- "ZZZ" + // saq
- "ZZZ" + // saq-ke
- "ZZZ" + // sbp
- "ZZZ" + // sbp-tz
- "SIP" + // sd
- "SIP" + // sd-arab
- "SIP" + // sd-arab-pk
- "ZZZ" + // sd-deva
- "ZZZ" + // sd-deva-in
- "SME" + // se
- "SMG" + // se-fi
- "SME" + // se-no
- "SMF" + // se-se
- "ZZZ" + // seh
- "ZZZ" + // seh-mz
- "ZZZ" + // ses
- "ZZZ" + // ses-ml
- "ZZZ" + // sg
- "ZZZ" + // sg-cf
- "ZZZ" + // shi
- "ZZZ" + // shi-latn
- "ZZZ" + // shi-latn-ma
- "ZZZ" + // shi-tfng
- "ZZZ" + // shi-tfng-ma
- "SIN" + // si
- "SIN" + // si-lk
- "SKY" + // sk
- "SKY" + // sk-sk
- "SLV" + // sl
- "SLV" + // sl-si
- "SMB" + // sma
- "SMA" + // sma-no
- "SMB" + // sma-se
- "SMK" + // smj
- "SMJ" + // smj-no
- "SMK" + // smj-se
- "SMN" + // smn
- "SMN" + // smn-fi
- "SMS" + // sms
- "SMS" + // sms-fi
- "SNA" + // sn
- "SNA" + // sn-latn
- "SNA" + // sn-latn-zw
- "SOM" + // so
- "ZZZ" + // so-dj
- "ZZZ" + // so-et
- "ZZZ" + // so-ke
- "SOM" + // so-so
- "SQI" + // sq
- "SQI" + // sq-al
- "ZZZ" + // sq-mk
- "ZZZ" + // sq-xk
- "SRM" + // sr
- "SRO" + // sr-cyrl
- "SRN" + // sr-cyrl-ba
- "SRB" + // sr-cyrl-cs
- "SRQ" + // sr-cyrl-me
- "SRO" + // sr-cyrl-rs
- "ZZZ" + // sr-cyrl-xk
- "SRM" + // sr-latn
- "SRS" + // sr-latn-ba
- "SRL" + // sr-latn-cs
- "SRP" + // sr-latn-me
- "SRM" + // sr-latn-rs
- "ZZZ" + // sr-latn-xk
- "ZZZ" + // ss
- "ZZZ" + // ss-sz
- "ZZZ" + // ss-za
- "ZZZ" + // ssy
- "ZZZ" + // ssy-er
- "SOT" + // st
- "ZZZ" + // st-ls
- "SOT" + // st-za
- "SVE" + // sv
- "ZZZ" + // sv-ax
- "SVF" + // sv-fi
- "SVE" + // sv-se
- "SWK" + // sw
- "ZZZ" + // sw-cd
- "SWK" + // sw-ke
- "ZZZ" + // sw-tz
- "ZZZ" + // sw-ug
- "ZZZ" + // swc
- "ZZZ" + // swc-cd
- "SYR" + // syr
- "SYR" + // syr-sy
- "TAI" + // ta
- "TAI" + // ta-in
- "TAM" + // ta-lk
- "ZZZ" + // ta-my
- "ZZZ" + // ta-sg
- "TEL" + // te
- "TEL" + // te-in
- "ZZZ" + // teo
- "ZZZ" + // teo-ke
- "ZZZ" + // teo-ug
- "TAJ" + // tg
- "TAJ" + // tg-cyrl
- "TAJ" + // tg-cyrl-tj
- "THA" + // th
- "THA" + // th-th
- "TIR" + // ti
- "TIR" + // ti-er
- "TIE" + // ti-et
- "ZZZ" + // tig
- "ZZZ" + // tig-er
- "TUK" + // tk
- "TUK" + // tk-tm
- "TSN" + // tn
- "TSB" + // tn-bw
- "TSN" + // tn-za
- "ZZZ" + // to
- "ZZZ" + // to-to
- "TRK" + // tr
- "ZZZ" + // tr-cy
- "TRK" + // tr-tr
- "TSO" + // ts
- "TSO" + // ts-za
- "TTT" + // tt
- "TTT" + // tt-ru
- "ZZZ" + // twq
- "ZZZ" + // twq-ne
- "TZA" + // tzm
- "ZZZ" + // tzm-arab
- "ZZZ" + // tzm-arab-ma
- "TZA" + // tzm-latn
- "TZA" + // tzm-latn-dz
- "ZZZ" + // tzm-latn-ma
- "TZM" + // tzm-tfng
- "TZM" + // tzm-tfng-ma
- "UIG" + // ug
- "UIG" + // ug-cn
- "UKR" + // uk
- "UKR" + // uk-ua
- "URD" + // ur
- "URI" + // ur-in
- "URD" + // ur-pk
- "UZB" + // uz
- "ZZZ" + // uz-arab
- "ZZZ" + // uz-arab-af
- "UZC" + // uz-cyrl
- "UZC" + // uz-cyrl-uz
- "UZB" + // uz-latn
- "UZB" + // uz-latn-uz
- "ZZZ" + // vai
- "ZZZ" + // vai-latn
- "ZZZ" + // vai-latn-lr
- "ZZZ" + // vai-vaii
- "ZZZ" + // vai-vaii-lr
- "ZZZ" + // ve
- "ZZZ" + // ve-za
- "VIT" + // vi
- "VIT" + // vi-vn
- "ZZZ" + // vo
- "ZZZ" + // vo-001
- "ZZZ" + // vun
- "ZZZ" + // vun-tz
- "ZZZ" + // wae
- "ZZZ" + // wae-ch
- "ZZZ" + // wal
- "ZZZ" + // wal-et
- "WOL" + // wo
- "WOL" + // wo-sn
- "IVL" + // x-iv_mathan
- "XHO" + // xh
- "XHO" + // xh-za
- "ZZZ" + // xog
- "ZZZ" + // xog-ug
- "ZZZ" + // yav
- "ZZZ" + // yav-cm
- "ZZZ" + // yi
- "ZZZ" + // yi-001
- "YOR" + // yo
- "ZZZ" + // yo-bj
- "YOR" + // yo-ng
- "ZZZ" + // yue
- "ZZZ" + // yue-hk
- "ZHG" + // zgh
- "ZHG" + // zgh-tfng
- "ZHG" + // zgh-tfng-ma
- "CHS" + // zh
- "CHS" + // zh-chs
- "CHT" + // zh-cht
- "CHS" + // zh-cn
- "CHS" + // zh-cn_phoneb
- "CHS" + // zh-cn_stroke
- "CHS" + // zh-hans
- "ZZZ" + // zh-hans-hk
- "ZZZ" + // zh-hans-mo
- "ZHH" + // zh-hant
- "ZHH" + // zh-hk
- "ZHH" + // zh-hk_radstr
- "ZHM" + // zh-mo
- "ZHM" + // zh-mo_radstr
- "ZHM" + // zh-mo_stroke
- "ZHI" + // zh-sg
- "ZHI" + // zh-sg_phoneb
- "ZHI" + // zh-sg_stroke
- "CHT" + // zh-tw
- "CHT" + // zh-tw_pronun
- "CHT" + // zh-tw_radstr
- "ZUL" + // zu
- "ZUL"; // zu-za
-
- // s_localeNamesIndices contains the start index of every culture name in the string
- // s_localeNames. We infer the length of each string by looking at the start index
- // of the next string.
- private static readonly int[] s_localeNamesIndices = new int[]
- {
- // c_localeNames index, // index to this array - culture name
- 0 , // 0 - aa
- 2 , // 1 - aa-dj
- 7 , // 2 - aa-er
- 12 , // 3 - aa-et
- 17 , // 4 - af
- 19 , // 5 - af-na
- 24 , // 6 - af-za
- 29 , // 7 - agq
- 32 , // 8 - agq-cm
- 38 , // 9 - ak
- 40 , // 10 - ak-gh
- 45 , // 11 - am
- 47 , // 12 - am-et
- 52 , // 13 - ar
- 54 , // 14 - ar-001
- 60 , // 15 - ar-ae
- 65 , // 16 - ar-bh
- 70 , // 17 - ar-dj
- 75 , // 18 - ar-dz
- 80 , // 19 - ar-eg
- 85 , // 20 - ar-er
- 90 , // 21 - ar-il
- 95 , // 22 - ar-iq
- 100 , // 23 - ar-jo
- 105 , // 24 - ar-km
- 110 , // 25 - ar-kw
- 115 , // 26 - ar-lb
- 120 , // 27 - ar-ly
- 125 , // 28 - ar-ma
- 130 , // 29 - ar-mr
- 135 , // 30 - ar-om
- 140 , // 31 - ar-ps
- 145 , // 32 - ar-qa
- 150 , // 33 - ar-sa
- 155 , // 34 - ar-sd
- 160 , // 35 - ar-so
- 165 , // 36 - ar-ss
- 170 , // 37 - ar-sy
- 175 , // 38 - ar-td
- 180 , // 39 - ar-tn
- 185 , // 40 - ar-ye
- 190 , // 41 - arn
- 193 , // 42 - arn-cl
- 199 , // 43 - as
- 201 , // 44 - as-in
- 206 , // 45 - asa
- 209 , // 46 - asa-tz
- 215 , // 47 - ast
- 218 , // 48 - ast-es
- 224 , // 49 - az
- 226 , // 50 - az-cyrl
- 233 , // 51 - az-cyrl-az
- 243 , // 52 - az-latn
- 250 , // 53 - az-latn-az
- 260 , // 54 - ba
- 262 , // 55 - ba-ru
- 267 , // 56 - bas
- 270 , // 57 - bas-cm
- 276 , // 58 - be
- 278 , // 59 - be-by
- 283 , // 60 - bem
- 286 , // 61 - bem-zm
- 292 , // 62 - bez
- 295 , // 63 - bez-tz
- 301 , // 64 - bg
- 303 , // 65 - bg-bg
- 308 , // 66 - bin
- 311 , // 67 - bin-ng
- 317 , // 68 - bm
- 319 , // 69 - bm-latn
- 326 , // 70 - bm-latn-ml
- 336 , // 71 - bn
- 338 , // 72 - bn-bd
- 343 , // 73 - bn-in
- 348 , // 74 - bo
- 350 , // 75 - bo-cn
- 355 , // 76 - bo-in
- 360 , // 77 - br
- 362 , // 78 - br-fr
- 367 , // 79 - brx
- 370 , // 80 - brx-in
- 376 , // 81 - bs
- 378 , // 82 - bs-cyrl
- 385 , // 83 - bs-cyrl-ba
- 395 , // 84 - bs-latn
- 402 , // 85 - bs-latn-ba
- 412 , // 86 - byn
- 415 , // 87 - byn-er
- 421 , // 88 - ca
- 423 , // 89 - ca-ad
- 428 , // 90 - ca-es
- 433 , // 91 - ca-es-valencia
- 447 , // 92 - ca-fr
- 452 , // 93 - ca-it
- 457 , // 94 - ce
- 459 , // 95 - ce-ru
- 464 , // 96 - cgg
- 467 , // 97 - cgg-ug
- 473 , // 98 - chr
- 476 , // 99 - chr-cher
- 484 , // 100 - chr-cher-us
- 495 , // 101 - co
- 497 , // 102 - co-fr
- 502 , // 103 - cs
- 504 , // 104 - cs-cz
- 509 , // 105 - cu
- 511 , // 106 - cu-ru
- 516 , // 107 - cy
- 518 , // 108 - cy-gb
- 523 , // 109 - da
- 525 , // 110 - da-dk
- 530 , // 111 - da-gl
- 535 , // 112 - dav
- 538 , // 113 - dav-ke
- 544 , // 114 - de
- 546 , // 115 - de-at
- 551 , // 116 - de-be
- 556 , // 117 - de-ch
- 561 , // 118 - de-de
- 566 , // 119 - de-de_phoneb
- 578 , // 120 - de-it
- 583 , // 121 - de-li
- 588 , // 122 - de-lu
- 593 , // 123 - dje
- 596 , // 124 - dje-ne
- 602 , // 125 - dsb
- 605 , // 126 - dsb-de
- 611 , // 127 - dua
- 614 , // 128 - dua-cm
- 620 , // 129 - dv
- 622 , // 130 - dv-mv
- 627 , // 131 - dyo
- 630 , // 132 - dyo-sn
- 636 , // 133 - dz
- 638 , // 134 - dz-bt
- 643 , // 135 - ebu
- 646 , // 136 - ebu-ke
- 652 , // 137 - ee
- 654 , // 138 - ee-gh
- 659 , // 139 - ee-tg
- 664 , // 140 - el
- 666 , // 141 - el-cy
- 671 , // 142 - el-gr
- 676 , // 143 - en
- 678 , // 144 - en-001
- 684 , // 145 - en-029
- 690 , // 146 - en-150
- 696 , // 147 - en-ag
- 701 , // 148 - en-ai
- 706 , // 149 - en-as
- 711 , // 150 - en-at
- 716 , // 151 - en-au
- 721 , // 152 - en-bb
- 726 , // 153 - en-be
- 731 , // 154 - en-bi
- 736 , // 155 - en-bm
- 741 , // 156 - en-bs
- 746 , // 157 - en-bw
- 751 , // 158 - en-bz
- 756 , // 159 - en-ca
- 761 , // 160 - en-cc
- 766 , // 161 - en-ch
- 771 , // 162 - en-ck
- 776 , // 163 - en-cm
- 781 , // 164 - en-cx
- 786 , // 165 - en-cy
- 791 , // 166 - en-de
- 796 , // 167 - en-dk
- 801 , // 168 - en-dm
- 806 , // 169 - en-er
- 811 , // 170 - en-fi
- 816 , // 171 - en-fj
- 821 , // 172 - en-fk
- 826 , // 173 - en-fm
- 831 , // 174 - en-gb
- 836 , // 175 - en-gd
- 841 , // 176 - en-gg
- 846 , // 177 - en-gh
- 851 , // 178 - en-gi
- 856 , // 179 - en-gm
- 861 , // 180 - en-gu
- 866 , // 181 - en-gy
- 871 , // 182 - en-hk
- 876 , // 183 - en-id
- 881 , // 184 - en-ie
- 886 , // 185 - en-il
- 891 , // 186 - en-im
- 896 , // 187 - en-in
- 901 , // 188 - en-io
- 906 , // 189 - en-je
- 911 , // 190 - en-jm
- 916 , // 191 - en-ke
- 921 , // 192 - en-ki
- 926 , // 193 - en-kn
- 931 , // 194 - en-ky
- 936 , // 195 - en-lc
- 941 , // 196 - en-lr
- 946 , // 197 - en-ls
- 951 , // 198 - en-mg
- 956 , // 199 - en-mh
- 961 , // 200 - en-mo
- 966 , // 201 - en-mp
- 971 , // 202 - en-ms
- 976 , // 203 - en-mt
- 981 , // 204 - en-mu
- 986 , // 205 - en-mw
- 991 , // 206 - en-my
- 996 , // 207 - en-na
- 1001, // 208 - en-nf
- 1006, // 209 - en-ng
- 1011, // 210 - en-nl
- 1016, // 211 - en-nr
- 1021, // 212 - en-nu
- 1026, // 213 - en-nz
- 1031, // 214 - en-pg
- 1036, // 215 - en-ph
- 1041, // 216 - en-pk
- 1046, // 217 - en-pn
- 1051, // 218 - en-pr
- 1056, // 219 - en-pw
- 1061, // 220 - en-rw
- 1066, // 221 - en-sb
- 1071, // 222 - en-sc
- 1076, // 223 - en-sd
- 1081, // 224 - en-se
- 1086, // 225 - en-sg
- 1091, // 226 - en-sh
- 1096, // 227 - en-si
- 1101, // 228 - en-sl
- 1106, // 229 - en-ss
- 1111, // 230 - en-sx
- 1116, // 231 - en-sz
- 1121, // 232 - en-tc
- 1126, // 233 - en-tk
- 1131, // 234 - en-to
- 1136, // 235 - en-tt
- 1141, // 236 - en-tv
- 1146, // 237 - en-tz
- 1151, // 238 - en-ug
- 1156, // 239 - en-um
- 1161, // 240 - en-us
- 1166, // 241 - en-vc
- 1171, // 242 - en-vg
- 1176, // 243 - en-vi
- 1181, // 244 - en-vu
- 1186, // 245 - en-ws
- 1191, // 246 - en-za
- 1196, // 247 - en-zm
- 1201, // 248 - en-zw
- 1206, // 249 - eo
- 1208, // 250 - eo-001
- 1214, // 251 - es
- 1216, // 252 - es-419
- 1222, // 253 - es-ar
- 1227, // 254 - es-bo
- 1232, // 255 - es-br
- 1237, // 256 - es-cl
- 1242, // 257 - es-co
- 1247, // 258 - es-cr
- 1252, // 259 - es-cu
- 1257, // 260 - es-do
- 1262, // 261 - es-ec
- 1267, // 262 - es-es
- 1272, // 263 - es-es_tradnl
- 1284, // 264 - es-gq
- 1289, // 265 - es-gt
- 1294, // 266 - es-hn
- 1299, // 267 - es-mx
- 1304, // 268 - es-ni
- 1309, // 269 - es-pa
- 1314, // 270 - es-pe
- 1319, // 271 - es-ph
- 1324, // 272 - es-pr
- 1329, // 273 - es-py
- 1334, // 274 - es-sv
- 1339, // 275 - es-us
- 1344, // 276 - es-uy
- 1349, // 277 - es-ve
- 1354, // 278 - et
- 1356, // 279 - et-ee
- 1361, // 280 - eu
- 1363, // 281 - eu-es
- 1368, // 282 - ewo
- 1371, // 283 - ewo-cm
- 1377, // 284 - fa
- 1379, // 285 - fa-ir
- 1384, // 286 - ff
- 1386, // 287 - ff-cm
- 1391, // 288 - ff-gn
- 1396, // 289 - ff-latn
- 1403, // 290 - ff-latn-sn
- 1413, // 291 - ff-mr
- 1418, // 292 - ff-ng
- 1423, // 293 - fi
- 1425, // 294 - fi-fi
- 1430, // 295 - fil
- 1433, // 296 - fil-ph
- 1439, // 297 - fo
- 1441, // 298 - fo-dk
- 1446, // 299 - fo-fo
- 1451, // 300 - fr
- 1453, // 301 - fr-029
- 1459, // 302 - fr-be
- 1464, // 303 - fr-bf
- 1469, // 304 - fr-bi
- 1474, // 305 - fr-bj
- 1479, // 306 - fr-bl
- 1484, // 307 - fr-ca
- 1489, // 308 - fr-cd
- 1494, // 309 - fr-cf
- 1499, // 310 - fr-cg
- 1504, // 311 - fr-ch
- 1509, // 312 - fr-ci
- 1514, // 313 - fr-cm
- 1519, // 314 - fr-dj
- 1524, // 315 - fr-dz
- 1529, // 316 - fr-fr
- 1534, // 317 - fr-ga
- 1539, // 318 - fr-gf
- 1544, // 319 - fr-gn
- 1549, // 320 - fr-gp
- 1554, // 321 - fr-gq
- 1559, // 322 - fr-ht
- 1564, // 323 - fr-km
- 1569, // 324 - fr-lu
- 1574, // 325 - fr-ma
- 1579, // 326 - fr-mc
- 1584, // 327 - fr-mf
- 1589, // 328 - fr-mg
- 1594, // 329 - fr-ml
- 1599, // 330 - fr-mq
- 1604, // 331 - fr-mr
- 1609, // 332 - fr-mu
- 1614, // 333 - fr-nc
- 1619, // 334 - fr-ne
- 1624, // 335 - fr-pf
- 1629, // 336 - fr-pm
- 1634, // 337 - fr-re
- 1639, // 338 - fr-rw
- 1644, // 339 - fr-sc
- 1649, // 340 - fr-sn
- 1654, // 341 - fr-sy
- 1659, // 342 - fr-td
- 1664, // 343 - fr-tg
- 1669, // 344 - fr-tn
- 1674, // 345 - fr-vu
- 1679, // 346 - fr-wf
- 1684, // 347 - fr-yt
- 1689, // 348 - fur
- 1692, // 349 - fur-it
- 1698, // 350 - fy
- 1700, // 351 - fy-nl
- 1705, // 352 - ga
- 1707, // 353 - ga-ie
- 1712, // 354 - gd
- 1714, // 355 - gd-gb
- 1719, // 356 - gl
- 1721, // 357 - gl-es
- 1726, // 358 - gn
- 1728, // 359 - gn-py
- 1733, // 360 - gsw
- 1736, // 361 - gsw-ch
- 1742, // 362 - gsw-fr
- 1748, // 363 - gsw-li
- 1754, // 364 - gu
- 1756, // 365 - gu-in
- 1761, // 366 - guz
- 1764, // 367 - guz-ke
- 1770, // 368 - gv
- 1772, // 369 - gv-im
- 1777, // 370 - ha
- 1779, // 371 - ha-latn
- 1786, // 372 - ha-latn-gh
- 1796, // 373 - ha-latn-ne
- 1806, // 374 - ha-latn-ng
- 1816, // 375 - haw
- 1819, // 376 - haw-us
- 1825, // 377 - he
- 1827, // 378 - he-il
- 1832, // 379 - hi
- 1834, // 380 - hi-in
- 1839, // 381 - hr
- 1841, // 382 - hr-ba
- 1846, // 383 - hr-hr
- 1851, // 384 - hsb
- 1854, // 385 - hsb-de
- 1860, // 386 - hu
- 1862, // 387 - hu-hu
- 1867, // 388 - hu-hu_technl
- 1879, // 389 - hy
- 1881, // 390 - hy-am
- 1886, // 391 - ia
- 1888, // 392 - ia-001
- 1894, // 393 - ia-fr
- 1899, // 394 - ibb
- 1902, // 395 - ibb-ng
- 1908, // 396 - id
- 1910, // 397 - id-id
- 1915, // 398 - ig
- 1917, // 399 - ig-ng
- 1922, // 400 - ii
- 1924, // 401 - ii-cn
- 1929, // 402 - is
- 1931, // 403 - is-is
- 1936, // 404 - it
- 1938, // 405 - it-ch
- 1943, // 406 - it-it
- 1948, // 407 - it-sm
- 1953, // 408 - iu
- 1955, // 409 - iu-cans
- 1962, // 410 - iu-cans-ca
- 1972, // 411 - iu-latn
- 1979, // 412 - iu-latn-ca
- 1989, // 413 - ja
- 1991, // 414 - ja-jp
- 1996, // 415 - ja-jp_radstr
- 2008, // 416 - jgo
- 2011, // 417 - jgo-cm
- 2017, // 418 - jmc
- 2020, // 419 - jmc-tz
- 2026, // 420 - jv
- 2028, // 421 - jv-java
- 2035, // 422 - jv-java-id
- 2045, // 423 - jv-latn
- 2052, // 424 - jv-latn-id
- 2062, // 425 - ka
- 2064, // 426 - ka-ge
- 2069, // 427 - ka-ge_modern
- 2081, // 428 - kab
- 2084, // 429 - kab-dz
- 2090, // 430 - kam
- 2093, // 431 - kam-ke
- 2099, // 432 - kde
- 2102, // 433 - kde-tz
- 2108, // 434 - kea
- 2111, // 435 - kea-cv
- 2117, // 436 - khq
- 2120, // 437 - khq-ml
- 2126, // 438 - ki
- 2128, // 439 - ki-ke
- 2133, // 440 - kk
- 2135, // 441 - kk-kz
- 2140, // 442 - kkj
- 2143, // 443 - kkj-cm
- 2149, // 444 - kl
- 2151, // 445 - kl-gl
- 2156, // 446 - kln
- 2159, // 447 - kln-ke
- 2165, // 448 - km
- 2167, // 449 - km-kh
- 2172, // 450 - kn
- 2174, // 451 - kn-in
- 2179, // 452 - ko
- 2181, // 453 - ko-kp
- 2186, // 454 - ko-kr
- 2191, // 455 - kok
- 2194, // 456 - kok-in
- 2200, // 457 - kr
- 2202, // 458 - kr-ng
- 2207, // 459 - ks
- 2209, // 460 - ks-arab
- 2216, // 461 - ks-arab-in
- 2226, // 462 - ks-deva
- 2233, // 463 - ks-deva-in
- 2243, // 464 - ksb
- 2246, // 465 - ksb-tz
- 2252, // 466 - ksf
- 2255, // 467 - ksf-cm
- 2261, // 468 - ksh
- 2264, // 469 - ksh-de
- 2270, // 470 - ku
- 2272, // 471 - ku-arab
- 2279, // 472 - ku-arab-iq
- 2289, // 473 - ku-arab-ir
- 2299, // 474 - kw
- 2301, // 475 - kw-gb
- 2306, // 476 - ky
- 2308, // 477 - ky-kg
- 2313, // 478 - la
- 2315, // 479 - la-001
- 2321, // 480 - lag
- 2324, // 481 - lag-tz
- 2330, // 482 - lb
- 2332, // 483 - lb-lu
- 2337, // 484 - lg
- 2339, // 485 - lg-ug
- 2344, // 486 - lkt
- 2347, // 487 - lkt-us
- 2353, // 488 - ln
- 2355, // 489 - ln-ao
- 2360, // 490 - ln-cd
- 2365, // 491 - ln-cf
- 2370, // 492 - ln-cg
- 2375, // 493 - lo
- 2377, // 494 - lo-la
- 2382, // 495 - lrc
- 2385, // 496 - lrc-iq
- 2391, // 497 - lrc-ir
- 2397, // 498 - lt
- 2399, // 499 - lt-lt
- 2404, // 500 - lu
- 2406, // 501 - lu-cd
- 2411, // 502 - luo
- 2414, // 503 - luo-ke
- 2420, // 504 - luy
- 2423, // 505 - luy-ke
- 2429, // 506 - lv
- 2431, // 507 - lv-lv
- 2436, // 508 - mas
- 2439, // 509 - mas-ke
- 2445, // 510 - mas-tz
- 2451, // 511 - mer
- 2454, // 512 - mer-ke
- 2460, // 513 - mfe
- 2463, // 514 - mfe-mu
- 2469, // 515 - mg
- 2471, // 516 - mg-mg
- 2476, // 517 - mgh
- 2479, // 518 - mgh-mz
- 2485, // 519 - mgo
- 2488, // 520 - mgo-cm
- 2494, // 521 - mi
- 2496, // 522 - mi-nz
- 2501, // 523 - mk
- 2503, // 524 - mk-mk
- 2508, // 525 - ml
- 2510, // 526 - ml-in
- 2515, // 527 - mn
- 2517, // 528 - mn-cyrl
- 2524, // 529 - mn-mn
- 2529, // 530 - mn-mong
- 2536, // 531 - mn-mong-cn
- 2546, // 532 - mn-mong-mn
- 2556, // 533 - mni
- 2559, // 534 - mni-in
- 2565, // 535 - moh
- 2568, // 536 - moh-ca
- 2574, // 537 - mr
- 2576, // 538 - mr-in
- 2581, // 539 - ms
- 2583, // 540 - ms-bn
- 2588, // 541 - ms-my
- 2593, // 542 - ms-sg
- 2598, // 543 - mt
- 2600, // 544 - mt-mt
- 2605, // 545 - mua
- 2608, // 546 - mua-cm
- 2614, // 547 - my
- 2616, // 548 - my-mm
- 2621, // 549 - mzn
- 2624, // 550 - mzn-ir
- 2630, // 551 - naq
- 2633, // 552 - naq-na
- 2639, // 553 - nb
- 2641, // 554 - nb-no
- 2646, // 555 - nb-sj
- 2651, // 556 - nd
- 2653, // 557 - nd-zw
- 2658, // 558 - nds
- 2661, // 559 - nds-de
- 2667, // 560 - nds-nl
- 2673, // 561 - ne
- 2675, // 562 - ne-in
- 2680, // 563 - ne-np
- 2685, // 564 - nl
- 2687, // 565 - nl-aw
- 2692, // 566 - nl-be
- 2697, // 567 - nl-bq
- 2702, // 568 - nl-cw
- 2707, // 569 - nl-nl
- 2712, // 570 - nl-sr
- 2717, // 571 - nl-sx
- 2722, // 572 - nmg
- 2725, // 573 - nmg-cm
- 2731, // 574 - nn
- 2733, // 575 - nn-no
- 2738, // 576 - nnh
- 2741, // 577 - nnh-cm
- 2747, // 578 - no
- 2749, // 579 - nqo
- 2752, // 580 - nqo-gn
- 2758, // 581 - nr
- 2760, // 582 - nr-za
- 2765, // 583 - nso
- 2768, // 584 - nso-za
- 2774, // 585 - nus
- 2777, // 586 - nus-ss
- 2783, // 587 - nyn
- 2786, // 588 - nyn-ug
- 2792, // 589 - oc
- 2794, // 590 - oc-fr
- 2799, // 591 - om
- 2801, // 592 - om-et
- 2806, // 593 - om-ke
- 2811, // 594 - or
- 2813, // 595 - or-in
- 2818, // 596 - os
- 2820, // 597 - os-ge
- 2825, // 598 - os-ru
- 2830, // 599 - pa
- 2832, // 600 - pa-arab
- 2839, // 601 - pa-arab-pk
- 2849, // 602 - pa-in
- 2854, // 603 - pap
- 2857, // 604 - pap-029
- 2864, // 605 - pl
- 2866, // 606 - pl-pl
- 2871, // 607 - prg
- 2874, // 608 - prg-001
- 2881, // 609 - prs
- 2884, // 610 - prs-af
- 2890, // 611 - ps
- 2892, // 612 - ps-af
- 2897, // 613 - pt
- 2899, // 614 - pt-ao
- 2904, // 615 - pt-br
- 2909, // 616 - pt-ch
- 2914, // 617 - pt-cv
- 2919, // 618 - pt-gq
- 2924, // 619 - pt-gw
- 2929, // 620 - pt-lu
- 2934, // 621 - pt-mo
- 2939, // 622 - pt-mz
- 2944, // 623 - pt-pt
- 2949, // 624 - pt-st
- 2954, // 625 - pt-tl
- 2959, // 626 - qps-latn-x-sh
- 2972, // 627 - qps-ploc
- 2980, // 628 - qps-ploca
- 2989, // 629 - qps-plocm
- 2998, // 630 - quc
- 3001, // 631 - quc-latn
- 3009, // 632 - quc-latn-gt
- 3020, // 633 - quz
- 3023, // 634 - quz-bo
- 3029, // 635 - quz-ec
- 3035, // 636 - quz-pe
- 3041, // 637 - rm
- 3043, // 638 - rm-ch
- 3048, // 639 - rn
- 3050, // 640 - rn-bi
- 3055, // 641 - ro
- 3057, // 642 - ro-md
- 3062, // 643 - ro-ro
- 3067, // 644 - rof
- 3070, // 645 - rof-tz
- 3076, // 646 - ru
- 3078, // 647 - ru-by
- 3083, // 648 - ru-kg
- 3088, // 649 - ru-kz
- 3093, // 650 - ru-md
- 3098, // 651 - ru-ru
- 3103, // 652 - ru-ua
- 3108, // 653 - rw
- 3110, // 654 - rw-rw
- 3115, // 655 - rwk
- 3118, // 656 - rwk-tz
- 3124, // 657 - sa
- 3126, // 658 - sa-in
- 3131, // 659 - sah
- 3134, // 660 - sah-ru
- 3140, // 661 - saq
- 3143, // 662 - saq-ke
- 3149, // 663 - sbp
- 3152, // 664 - sbp-tz
- 3158, // 665 - sd
- 3160, // 666 - sd-arab
- 3167, // 667 - sd-arab-pk
- 3177, // 668 - sd-deva
- 3184, // 669 - sd-deva-in
- 3194, // 670 - se
- 3196, // 671 - se-fi
- 3201, // 672 - se-no
- 3206, // 673 - se-se
- 3211, // 674 - seh
- 3214, // 675 - seh-mz
- 3220, // 676 - ses
- 3223, // 677 - ses-ml
- 3229, // 678 - sg
- 3231, // 679 - sg-cf
- 3236, // 680 - shi
- 3239, // 681 - shi-latn
- 3247, // 682 - shi-latn-ma
- 3258, // 683 - shi-tfng
- 3266, // 684 - shi-tfng-ma
- 3277, // 685 - si
- 3279, // 686 - si-lk
- 3284, // 687 - sk
- 3286, // 688 - sk-sk
- 3291, // 689 - sl
- 3293, // 690 - sl-si
- 3298, // 691 - sma
- 3301, // 692 - sma-no
- 3307, // 693 - sma-se
- 3313, // 694 - smj
- 3316, // 695 - smj-no
- 3322, // 696 - smj-se
- 3328, // 697 - smn
- 3331, // 698 - smn-fi
- 3337, // 699 - sms
- 3340, // 700 - sms-fi
- 3346, // 701 - sn
- 3348, // 702 - sn-latn
- 3355, // 703 - sn-latn-zw
- 3365, // 704 - so
- 3367, // 705 - so-dj
- 3372, // 706 - so-et
- 3377, // 707 - so-ke
- 3382, // 708 - so-so
- 3387, // 709 - sq
- 3389, // 710 - sq-al
- 3394, // 711 - sq-mk
- 3399, // 712 - sq-xk
- 3404, // 713 - sr
- 3406, // 714 - sr-cyrl
- 3413, // 715 - sr-cyrl-ba
- 3423, // 716 - sr-cyrl-cs
- 3433, // 717 - sr-cyrl-me
- 3443, // 718 - sr-cyrl-rs
- 3453, // 719 - sr-cyrl-xk
- 3463, // 720 - sr-latn
- 3470, // 721 - sr-latn-ba
- 3480, // 722 - sr-latn-cs
- 3490, // 723 - sr-latn-me
- 3500, // 724 - sr-latn-rs
- 3510, // 725 - sr-latn-xk
- 3520, // 726 - ss
- 3522, // 727 - ss-sz
- 3527, // 728 - ss-za
- 3532, // 729 - ssy
- 3535, // 730 - ssy-er
- 3541, // 731 - st
- 3543, // 732 - st-ls
- 3548, // 733 - st-za
- 3553, // 734 - sv
- 3555, // 735 - sv-ax
- 3560, // 736 - sv-fi
- 3565, // 737 - sv-se
- 3570, // 738 - sw
- 3572, // 739 - sw-cd
- 3577, // 740 - sw-ke
- 3582, // 741 - sw-tz
- 3587, // 742 - sw-ug
- 3592, // 743 - swc
- 3595, // 744 - swc-cd
- 3601, // 745 - syr
- 3604, // 746 - syr-sy
- 3610, // 747 - ta
- 3612, // 748 - ta-in
- 3617, // 749 - ta-lk
- 3622, // 750 - ta-my
- 3627, // 751 - ta-sg
- 3632, // 752 - te
- 3634, // 753 - te-in
- 3639, // 754 - teo
- 3642, // 755 - teo-ke
- 3648, // 756 - teo-ug
- 3654, // 757 - tg
- 3656, // 758 - tg-cyrl
- 3663, // 759 - tg-cyrl-tj
- 3673, // 760 - th
- 3675, // 761 - th-th
- 3680, // 762 - ti
- 3682, // 763 - ti-er
- 3687, // 764 - ti-et
- 3692, // 765 - tig
- 3695, // 766 - tig-er
- 3701, // 767 - tk
- 3703, // 768 - tk-tm
- 3708, // 769 - tn
- 3710, // 770 - tn-bw
- 3715, // 771 - tn-za
- 3720, // 772 - to
- 3722, // 773 - to-to
- 3727, // 774 - tr
- 3729, // 775 - tr-cy
- 3734, // 776 - tr-tr
- 3739, // 777 - ts
- 3741, // 778 - ts-za
- 3746, // 779 - tt
- 3748, // 780 - tt-ru
- 3753, // 781 - twq
- 3756, // 782 - twq-ne
- 3762, // 783 - tzm
- 3765, // 784 - tzm-arab
- 3773, // 785 - tzm-arab-ma
- 3784, // 786 - tzm-latn
- 3792, // 787 - tzm-latn-dz
- 3803, // 788 - tzm-latn-ma
- 3814, // 789 - tzm-tfng
- 3822, // 790 - tzm-tfng-ma
- 3833, // 791 - ug
- 3835, // 792 - ug-cn
- 3840, // 793 - uk
- 3842, // 794 - uk-ua
- 3847, // 795 - ur
- 3849, // 796 - ur-in
- 3854, // 797 - ur-pk
- 3859, // 798 - uz
- 3861, // 799 - uz-arab
- 3868, // 800 - uz-arab-af
- 3878, // 801 - uz-cyrl
- 3885, // 802 - uz-cyrl-uz
- 3895, // 803 - uz-latn
- 3902, // 804 - uz-latn-uz
- 3912, // 805 - vai
- 3915, // 806 - vai-latn
- 3923, // 807 - vai-latn-lr
- 3934, // 808 - vai-vaii
- 3942, // 809 - vai-vaii-lr
- 3953, // 810 - ve
- 3955, // 811 - ve-za
- 3960, // 812 - vi
- 3962, // 813 - vi-vn
- 3967, // 814 - vo
- 3969, // 815 - vo-001
- 3975, // 816 - vun
- 3978, // 817 - vun-tz
- 3984, // 818 - wae
- 3987, // 819 - wae-ch
- 3993, // 820 - wal
- 3996, // 821 - wal-et
- 4002, // 822 - wo
- 4004, // 823 - wo-sn
- 4009, // 824 - x-iv_mathan
- 4020, // 825 - xh
- 4022, // 826 - xh-za
- 4027, // 827 - xog
- 4030, // 828 - xog-ug
- 4036, // 829 - yav
- 4039, // 830 - yav-cm
- 4045, // 831 - yi
- 4047, // 832 - yi-001
- 4053, // 833 - yo
- 4055, // 834 - yo-bj
- 4060, // 835 - yo-ng
- 4065, // 836 - yue
- 4068, // 837 - yue-hk
- 4074, // 838 - zgh
- 4077, // 839 - zgh-tfng
- 4085, // 840 - zgh-tfng-ma
- 4096, // 841 - zh
- 4098, // 842 - zh-chs
- 4104, // 843 - zh-cht
- 4110, // 844 - zh-cn
- 4115, // 845 - zh-cn_phoneb
- 4127, // 846 - zh-cn_stroke
- 4139, // 847 - zh-hans
- 4146, // 848 - zh-hans-hk
- 4156, // 849 - zh-hans-mo
- 4166, // 850 - zh-hant
- 4173, // 851 - zh-hk
- 4178, // 852 - zh-hk_radstr
- 4190, // 853 - zh-mo
- 4195, // 854 - zh-mo_radstr
- 4207, // 855 - zh-mo_stroke
- 4219, // 856 - zh-sg
- 4224, // 857 - zh-sg_phoneb
- 4236, // 858 - zh-sg_stroke
- 4248, // 859 - zh-tw
- 4253, // 860 - zh-tw_pronun
- 4265, // 861 - zh-tw_radstr
- 4277, // 862 - zu
- 4279, // 863 - zu-za
- 4284
- };
-
- private const int NUMERIC_LOCALE_DATA_COUNT_PER_ROW = 9;
- // s_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, specific locale index, Console locale index
- private static readonly int[] s_nameIndexToNumericData = new int[]
- {
- // Lcid, Ansi CP, Oem CP, MAC CP, EBCDIC CP, Geo Id, digit substitution, Specific culture index, keyboard Id, Console locale index // index - locale name
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 3 , 240 , // 0 - aa
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3e , 1 , 1 , 240 , // 1 - aa-dj
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 2 , 240 , // 2 - aa-er
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 3 , 240 , // 3 - aa-et
- 0x36 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 6 , 6 , // 4 - af
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xfe , 1 , 5 , 240 , // 5 - af-na
- 0x436 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 6 , 6 , // 6 - af-za
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 8 , 240 , // 7 - agq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 8 , 240 , // 8 - agq-cm
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 10 , 240 , // 9 - ak
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 10 , 240 , // 10 - ak-gh
- 0x5e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 12 , 143 , // 11 - am
- 0x45e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 12 , 143 , // 12 - am-et
- 0x1 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xcd , 0 , 33 , 143 , // 13 - ar
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x989e, 0 , 14 , 240 , // 14 - ar-001
- 0x3801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xe0 , 0 , 15 , 143 , // 15 - ar-ae
- 0x3c01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x11 , 0 , 16 , 143 , // 16 - ar-bh
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x3e , 0 , 17 , 240 , // 17 - ar-dj
- 0x1401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x4 , 1 , 18 , 300 , // 18 - ar-dz
- 0xc01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x43 , 0 , 19 , 143 , // 19 - ar-eg
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x47 , 0 , 20 , 240 , // 20 - ar-er
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x75 , 0 , 21 , 240 , // 21 - ar-il
- 0x801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 22 , 143 , // 22 - ar-iq
- 0x2c01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x7e , 0 , 23 , 143 , // 23 - ar-jo
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x32 , 0 , 24 , 240 , // 24 - ar-km
- 0x3401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x88 , 0 , 25 , 143 , // 25 - ar-kw
- 0x3001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x8b , 0 , 26 , 143 , // 26 - ar-lb
- 0x1001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x94 , 1 , 27 , 143 , // 27 - ar-ly
- 0x1801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x9f , 1 , 28 , 300 , // 28 - ar-ma
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xa2 , 0 , 29 , 240 , // 29 - ar-mr
- 0x2001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xa4 , 0 , 30 , 143 , // 30 - ar-om
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xb8 , 0 , 31 , 240 , // 31 - ar-ps
- 0x4001 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xc5 , 0 , 32 , 143 , // 32 - ar-qa
- 0x401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xcd , 0 , 33 , 143 , // 33 - ar-sa
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xdb , 0 , 34 , 240 , // 34 - ar-sd
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xd8 , 0 , 35 , 240 , // 35 - ar-so
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x114 , 0 , 36 , 240 , // 36 - ar-ss
- 0x2801 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xde , 0 , 37 , 143 , // 37 - ar-sy
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x29 , 0 , 38 , 240 , // 38 - ar-td
- 0x1c01 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xea , 1 , 39 , 300 , // 39 - ar-tn
- 0x2401 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x105 , 0 , 40 , 143 , // 40 - ar-ye
- 0x7a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x2e , 1 , 42 , 42 , // 41 - arn
- 0x47a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x2e , 1 , 42 , 42 , // 42 - arn-cl
- 0x4d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 44 , 143 , // 43 - as
- 0x44d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 44 , 143 , // 44 - as-in
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 46 , 240 , // 45 - asa
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 46 , 240 , // 46 - asa-tz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd9 , 1 , 48 , 240 , // 47 - ast
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd9 , 1 , 48 , 240 , // 48 - ast-es
- 0x2c , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x5 , 1 , 53 , 53 , // 49 - az
- 0x742c , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x5 , 1 , 51 , 51 , // 50 - az-cyrl
- 0x82c , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x5 , 1 , 51 , 51 , // 51 - az-cyrl-az
- 0x782c , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x5 , 1 , 53 , 53 , // 52 - az-latn
- 0x42c , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x5 , 1 , 53 , 53 , // 53 - az-latn-az
- 0x6d , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 55 , 55 , // 54 - ba
- 0x46d , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 55 , 55 , // 55 - ba-ru
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 57 , 240 , // 56 - bas
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 57 , 240 , // 57 - bas-cm
- 0x23 , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x1d , 1 , 59 , 59 , // 58 - be
- 0x423 , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x1d , 1 , 59 , 59 , // 59 - be-by
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x107 , 1 , 61 , 240 , // 60 - bem
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x107 , 1 , 61 , 240 , // 61 - bem-zm
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 63 , 240 , // 62 - bez
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 63 , 240 , // 63 - bez-tz
- 0x2 , 0x4e3 , 0x362 , 0x2717, 0x5221, 0x23 , 1 , 65 , 65 , // 64 - bg
- 0x402 , 0x4e3 , 0x362 , 0x2717, 0x5221, 0x23 , 1 , 65 , 65 , // 65 - bg-bg
- 0x66 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 67 , 240 , // 66 - bin
- 0x466 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 67 , 240 , // 67 - bin-ng
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 70 , 240 , // 68 - bm
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 70 , 240 , // 69 - bm-latn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 70 , 240 , // 70 - bm-latn-ml
- 0x45 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x17 , 1 , 72 , 143 , // 71 - bn
- 0x845 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x17 , 1 , 72 , 143 , // 72 - bn-bd
- 0x445 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 73 , 143 , // 73 - bn-in
- 0x51 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 75 , 143 , // 74 - bo
- 0x451 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 75 , 143 , // 75 - bo-cn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 76 , 240 , // 76 - bo-in
- 0x7e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 78 , 78 , // 77 - br
- 0x47e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 78 , 78 , // 78 - br-fr
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 80 , 240 , // 79 - brx
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 80 , 240 , // 80 - brx-in
- 0x781a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 85 , 85 , // 81 - bs
- 0x641a , 0x4e3 , 0x357 , 0x2762, 0x366 , 0x19 , 1 , 83 , 83 , // 82 - bs-cyrl
- 0x201a , 0x4e3 , 0x357 , 0x2762, 0x366 , 0x19 , 1 , 83 , 83 , // 83 - bs-cyrl-ba
- 0x681a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 85 , 85 , // 84 - bs-latn
- 0x141a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 85 , 85 , // 85 - bs-latn-ba
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 87 , 240 , // 86 - byn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 87 , 240 , // 87 - byn-er
- 0x3 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 90 , 90 , // 88 - ca
- 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x8 , 1 , 89 , 240 , // 89 - ca-ad
- 0x403 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 90 , 90 , // 90 - ca-es
- 0x803 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 91 , 90 , // 91 - ca-es-valencia
- 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x54 , 1 , 92 , 240 , // 92 - ca-fr
- 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x76 , 1 , 93 , 240 , // 93 - ca-it
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 95 , 240 , // 94 - ce
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 95 , 240 , // 95 - ce-ru
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 97 , 240 , // 96 - cgg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 97 , 240 , // 97 - cgg-ug
- 0x5c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 100 , 240 , // 98 - chr
- 0x7c5c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 100 , 240 , // 99 - chr-cher
- 0x45c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 100 , 240 , // 100 - chr-cher-us
- 0x83 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 102 , 102 , // 101 - co
- 0x483 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 102 , 102 , // 102 - co-fr
- 0x5 , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x4b , 1 , 104 , 104 , // 103 - cs
- 0x405 , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x4b , 1 , 104 , 104 , // 104 - cs-cz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 106 , 240 , // 105 - cu
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 106 , 240 , // 106 - cu-ru
- 0x52 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 108 , 108 , // 107 - cy
- 0x452 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 108 , 108 , // 108 - cy-gb
- 0x6 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x3d , 1 , 110 , 110 , // 109 - da
- 0x406 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x3d , 1 , 110 , 110 , // 110 - da-dk
- 0x1000 , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0x5d , 1 , 111 , 240 , // 111 - da-gl
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 113 , 240 , // 112 - dav
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 113 , 240 , // 113 - dav-ke
- 0x7 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x5e , 1 , 118 , 118 , // 114 - de
- 0xc07 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xe , 1 , 115 , 115 , // 115 - de-at
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x15 , 1 , 116 , 240 , // 116 - de-be
- 0x807 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xdf , 1 , 117 , 117 , // 117 - de-ch
- 0x407 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x5e , 1 , 118 , 118 , // 118 - de-de
- 0x10407, 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x5e , 1 , 118 , 118 , // 119 - de-de_phoneb
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x76 , 1 , 120 , 240 , // 120 - de-it
- 0x1407 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x91 , 1 , 121 , 121 , // 121 - de-li
- 0x1007 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0x93 , 1 , 122 , 122 , // 122 - de-lu
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 124 , 240 , // 123 - dje
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 124 , 240 , // 124 - dje-ne
- 0x7c2e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 126 , 126 , // 125 - dsb
- 0x82e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 126 , 126 , // 126 - dsb-de
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 128 , 240 , // 127 - dua
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 128 , 240 , // 128 - dua-cm
- 0x65 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa5 , 1 , 130 , 143 , // 129 - dv
- 0x465 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa5 , 1 , 130 , 143 , // 130 - dv-mv
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd2 , 1 , 132 , 240 , // 131 - dyo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd2 , 1 , 132 , 240 , // 132 - dyo-sn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x22 , 2 , 134 , 240 , // 133 - dz
- 0xc51 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x22 , 2 , 134 , 240 , // 134 - dz-bt
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 136 , 240 , // 135 - ebu
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 136 , 240 , // 136 - ebu-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 138 , 240 , // 137 - ee
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x59 , 1 , 138 , 240 , // 138 - ee-gh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe8 , 1 , 139 , 240 , // 139 - ee-tg
- 0x8 , 0x4e5 , 0x2e1 , 0x2716, 0x4f31, 0x62 , 1 , 142 , 142 , // 140 - el
- 0x1000 , 0x4e5 , 0x2e1 , 0x2716, 0x4f31, 0x3b , 1 , 141 , 240 , // 141 - el-cy
- 0x408 , 0x4e5 , 0x2e1 , 0x2716, 0x4f31, 0x62 , 1 , 142 , 142 , // 142 - el-gr
- 0x9 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 240 , 240 , // 143 - en
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x989e, 1 , 144 , 240 , // 144 - en-001
- 0x2409 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x993248, 1 , 145 , 145 , // 145 - en-029
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x292d, 1 , 146 , 240 , // 146 - en-150
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x2 , 1 , 147 , 240 , // 147 - en-ag
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x12c , 1 , 148 , 240 , // 148 - en-ai
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa , 1 , 149 , 240 , // 149 - en-as
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe , 1 , 150 , 240 , // 150 - en-at
- 0xc09 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc , 1 , 151 , 151 , // 151 - en-au
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x12 , 1 , 152 , 240 , // 152 - en-bb
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15 , 1 , 153 , 240 , // 153 - en-be
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x26 , 1 , 154 , 240 , // 154 - en-bi
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x14 , 1 , 155 , 240 , // 155 - en-bm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x16 , 1 , 156 , 240 , // 156 - en-bs
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x13 , 1 , 157 , 240 , // 157 - en-bw
- 0x2809 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x18 , 1 , 158 , 158 , // 158 - en-bz
- 0x1009 , 0x4e4 , 0x352 , 0x2710, 0x25 , 0x27 , 1 , 159 , 159 , // 159 - en-ca
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x137 , 1 , 160 , 240 , // 160 - en-cc
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 161 , 240 , // 161 - en-ch
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x138 , 1 , 162 , 240 , // 162 - en-ck
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x31 , 1 , 163 , 240 , // 163 - en-cm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x135 , 1 , 164 , 240 , // 164 - en-cx
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3b , 1 , 165 , 240 , // 165 - en-cy
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 166 , 240 , // 166 - en-de
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3d , 1 , 167 , 240 , // 167 - en-dk
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x3f , 1 , 168 , 240 , // 168 - en-dm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x47 , 1 , 169 , 240 , // 169 - en-er
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x4d , 1 , 170 , 240 , // 170 - en-fi
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x4e , 1 , 171 , 240 , // 171 - en-fj
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x13b , 1 , 172 , 240 , // 172 - en-fk
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x50 , 1 , 173 , 240 , // 173 - en-fm
- 0x809 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 174 , 174 , // 174 - en-gb
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x5b , 1 , 175 , 240 , // 175 - en-gd
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x144 , 1 , 176 , 240 , // 176 - en-gg
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x59 , 1 , 177 , 240 , // 177 - en-gh
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x5a , 1 , 178 , 240 , // 178 - en-gi
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x56 , 1 , 179 , 240 , // 179 - en-gm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x142 , 1 , 180 , 240 , // 180 - en-gu
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x65 , 1 , 181 , 240 , // 181 - en-gy
- 0x3c09 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x68 , 1 , 182 , 240 , // 182 - en-hk
- 0x3809 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 183 , 240 , // 183 - en-id
- 0x1809 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x44 , 1 , 184 , 184 , // 184 - en-ie
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x75 , 1 , 185 , 240 , // 185 - en-il
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x3b16, 1 , 186 , 240 , // 186 - en-im
- 0x4009 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x71 , 1 , 187 , 187 , // 187 - en-in
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x72 , 1 , 188 , 240 , // 188 - en-io
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x148 , 1 , 189 , 240 , // 189 - en-je
- 0x2009 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x7c , 1 , 190 , 190 , // 190 - en-jm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x81 , 1 , 191 , 240 , // 191 - en-ke
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x85 , 1 , 192 , 240 , // 192 - en-ki
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xcf , 1 , 193 , 240 , // 193 - en-kn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x133 , 1 , 194 , 240 , // 194 - en-ky
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xda , 1 , 195 , 240 , // 195 - en-lc
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x8e , 1 , 196 , 240 , // 196 - en-lr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x92 , 1 , 197 , 240 , // 197 - en-ls
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x95 , 1 , 198 , 240 , // 198 - en-mg
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc7 , 1 , 199 , 240 , // 199 - en-mh
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x97 , 1 , 200 , 240 , // 200 - en-mo
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x151 , 1 , 201 , 240 , // 201 - en-mp
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x14c , 1 , 202 , 240 , // 202 - en-ms
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa3 , 1 , 203 , 240 , // 203 - en-mt
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa0 , 1 , 204 , 240 , // 204 - en-mu
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9c , 1 , 205 , 240 , // 205 - en-mw
- 0x4409 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xa7 , 1 , 206 , 206 , // 206 - en-my
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xfe , 1 , 207 , 240 , // 207 - en-na
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x150 , 1 , 208 , 240 , // 208 - en-nf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 209 , 240 , // 209 - en-ng
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb0 , 1 , 210 , 240 , // 210 - en-nl
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb4 , 1 , 211 , 240 , // 211 - en-nr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x14f , 1 , 212 , 240 , // 212 - en-nu
- 0x1409 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb7 , 1 , 213 , 213 , // 213 - en-nz
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc2 , 1 , 214 , 240 , // 214 - en-pg
- 0x3409 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xc9 , 1 , 215 , 215 , // 215 - en-ph
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xbe , 1 , 216 , 240 , // 216 - en-pk
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x153 , 1 , 217 , 240 , // 217 - en-pn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xca , 1 , 218 , 240 , // 218 - en-pr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc3 , 1 , 219 , 240 , // 219 - en-pw
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xcc , 1 , 220 , 240 , // 220 - en-rw
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x1e , 1 , 221 , 240 , // 221 - en-sb
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd0 , 1 , 222 , 240 , // 222 - en-sc
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xdb , 1 , 223 , 240 , // 223 - en-sd
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdd , 1 , 224 , 240 , // 224 - en-se
- 0x4809 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xd7 , 1 , 225 , 225 , // 225 - en-sg
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x157 , 1 , 226 , 240 , // 226 - en-sh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd4 , 1 , 227 , 240 , // 227 - en-si
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd5 , 1 , 228 , 240 , // 228 - en-sl
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x114 , 1 , 229 , 240 , // 229 - en-ss
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x78f7, 1 , 230 , 240 , // 230 - en-sx
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x104 , 1 , 231 , 240 , // 231 - en-sz
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15d , 1 , 232 , 240 , // 232 - en-tc
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15b , 1 , 233 , 240 , // 233 - en-tk
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xe7 , 1 , 234 , 240 , // 234 - en-to
- 0x2c09 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xe1 , 1 , 235 , 235 , // 235 - en-tt
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xec , 1 , 236 , 240 , // 236 - en-tv
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xef , 1 , 237 , 240 , // 237 - en-tz
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xf0 , 1 , 238 , 240 , // 238 - en-ug
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9a55d40, 1 , 239 , 240 , // 239 - en-um
- 0x409 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 240 , 240 , // 240 - en-us
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xf8 , 1 , 241 , 240 , // 241 - en-vc
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15f , 1 , 242 , 240 , // 242 - en-vg
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xfc , 1 , 243 , 240 , // 243 - en-vi
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xae , 1 , 244 , 240 , // 244 - en-vu
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x103 , 1 , 245 , 240 , // 245 - en-ws
- 0x1c09 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xd1 , 1 , 246 , 246 , // 246 - en-za
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x107 , 1 , 247 , 240 , // 247 - en-zm
- 0x3009 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x108 , 1 , 248 , 248 , // 248 - en-zw
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 250 , 240 , // 249 - eo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 250 , 240 , // 250 - eo-001
- 0xa , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xd9 , 1 , 262 , 262 , // 251 - es
- 0x580a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x9a55d41, 1 , 252 , 240 , // 252 - es-419
- 0x2c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb , 1 , 253 , 253 , // 253 - es-ar
- 0x400a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x1a , 1 , 254 , 254 , // 254 - es-bo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x20 , 1 , 255 , 240 , // 255 - es-br
- 0x340a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x2e , 1 , 256 , 256 , // 256 - es-cl
- 0x240a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x33 , 1 , 257 , 257 , // 257 - es-co
- 0x140a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x36 , 1 , 258 , 258 , // 258 - es-cr
- 0x5c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x38 , 1 , 259 , 240 , // 259 - es-cu
- 0x1c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x41 , 1 , 260 , 260 , // 260 - es-do
- 0x300a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x42 , 1 , 261 , 261 , // 261 - es-ec
- 0xc0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xd9 , 1 , 262 , 262 , // 262 - es-es
- 0x40a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xd9 , 1 , 263 , 263 , // 263 - es-es_tradnl
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x45 , 1 , 264 , 240 , // 264 - es-gq
- 0x100a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 265 , 265 , // 265 - es-gt
- 0x480a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x6a , 1 , 266 , 266 , // 266 - es-hn
- 0x80a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xa6 , 1 , 267 , 267 , // 267 - es-mx
- 0x4c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb6 , 1 , 268 , 268 , // 268 - es-ni
- 0x180a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xc0 , 1 , 269 , 269 , // 269 - es-pa
- 0x280a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xbb , 1 , 270 , 270 , // 270 - es-pe
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xc9 , 1 , 271 , 240 , // 271 - es-ph
- 0x500a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xca , 1 , 272 , 272 , // 272 - es-pr
- 0x3c0a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb9 , 1 , 273 , 273 , // 273 - es-py
- 0x440a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x48 , 1 , 274 , 274 , // 274 - es-sv
- 0x540a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xf4 , 1 , 275 , 275 , // 275 - es-us
- 0x380a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xf6 , 1 , 276 , 276 , // 276 - es-uy
- 0x200a , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xf9 , 1 , 277 , 277 , // 277 - es-ve
- 0x25 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x46 , 1 , 279 , 279 , // 278 - et
- 0x425 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x46 , 1 , 279 , 279 , // 279 - et-ee
- 0x2d , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0xd9 , 1 , 281 , 240 , // 280 - eu
- 0x42d , 0x4e4 , 0x352 , 0x2 , 0x1f4 , 0xd9 , 1 , 281 , 240 , // 281 - eu-es
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 283 , 240 , // 282 - ewo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 283 , 240 , // 283 - ewo-cm
- 0x29 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x74 , 0 , 285 , 143 , // 284 - fa
- 0x429 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x74 , 0 , 285 , 143 , // 285 - fa-ir
- 0x67 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 290 , 290 , // 286 - ff
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x31 , 1 , 287 , 240 , // 287 - ff-cm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x64 , 1 , 288 , 240 , // 288 - ff-gn
- 0x7c67 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 290 , 290 , // 289 - ff-latn
- 0x867 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 290 , 290 , // 290 - ff-latn-sn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xa2 , 1 , 291 , 240 , // 291 - ff-mr
- 0x467 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xaf , 1 , 292 , 240 , // 292 - ff-ng
- 0xb , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 294 , 294 , // 293 - fi
- 0x40b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 294 , 294 , // 294 - fi-fi
- 0x64 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xc9 , 1 , 296 , 296 , // 295 - fil
- 0x464 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xc9 , 1 , 296 , 296 , // 296 - fil-ph
- 0x38 , 0x4e4 , 0x352 , 0x275f, 0x4f35, 0x51 , 1 , 299 , 299 , // 297 - fo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3d , 1 , 298 , 240 , // 298 - fo-dk
- 0x438 , 0x4e4 , 0x352 , 0x275f, 0x4f35, 0x51 , 1 , 299 , 299 , // 299 - fo-fo
- 0xc , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 316 , 316 , // 300 - fr
- 0x1c0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x993248, 1 , 301 , 316 , // 301 - fr-029
- 0x80c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x15 , 1 , 302 , 302 , // 302 - fr-be
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xf5 , 1 , 303 , 240 , // 303 - fr-bf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x26 , 1 , 304 , 240 , // 304 - fr-bi
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x1c , 1 , 305 , 240 , // 305 - fr-bj
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9a55c4f, 1 , 306 , 240 , // 306 - fr-bl
- 0xc0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x27 , 1 , 307 , 307 , // 307 - fr-ca
- 0x240c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x2c , 1 , 308 , 240 , // 308 - fr-cd
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x37 , 1 , 309 , 240 , // 309 - fr-cf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x2b , 1 , 310 , 240 , // 310 - fr-cg
- 0x100c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xdf , 1 , 311 , 311 , // 311 - fr-ch
- 0x300c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x77 , 1 , 312 , 240 , // 312 - fr-ci
- 0x2c0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x31 , 1 , 313 , 240 , // 313 - fr-cm
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x3e , 1 , 314 , 240 , // 314 - fr-dj
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 315 , 240 , // 315 - fr-dz
- 0x40c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 316 , 316 , // 316 - fr-fr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x57 , 1 , 317 , 240 , // 317 - fr-ga
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x13d , 1 , 318 , 240 , // 318 - fr-gf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x64 , 1 , 319 , 240 , // 319 - fr-gn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x141 , 1 , 320 , 240 , // 320 - fr-gp
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x45 , 1 , 321 , 240 , // 321 - fr-gq
- 0x3c0c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x67 , 1 , 322 , 240 , // 322 - fr-ht
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x32 , 1 , 323 , 240 , // 323 - fr-km
- 0x140c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x93 , 1 , 324 , 324 , // 324 - fr-lu
- 0x380c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9f , 1 , 325 , 240 , // 325 - fr-ma
- 0x180c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9e , 1 , 326 , 326 , // 326 - fr-mc
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x7bda, 1 , 327 , 240 , // 327 - fr-mf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x95 , 1 , 328 , 240 , // 328 - fr-mg
- 0x340c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x9d , 1 , 329 , 240 , // 329 - fr-ml
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x14a , 1 , 330 , 240 , // 330 - fr-mq
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xa2 , 1 , 331 , 240 , // 331 - fr-mr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xa0 , 1 , 332 , 240 , // 332 - fr-mu
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x14e , 1 , 333 , 240 , // 333 - fr-nc
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xad , 1 , 334 , 240 , // 334 - fr-ne
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x13e , 1 , 335 , 240 , // 335 - fr-pf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xce , 1 , 336 , 240 , // 336 - fr-pm
- 0x200c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xc6 , 1 , 337 , 240 , // 337 - fr-re
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xcc , 1 , 338 , 240 , // 338 - fr-rw
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd0 , 1 , 339 , 240 , // 339 - fr-sc
- 0x280c , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 340 , 240 , // 340 - fr-sn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xde , 1 , 341 , 240 , // 341 - fr-sy
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x29 , 1 , 342 , 240 , // 342 - fr-td
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xe8 , 1 , 343 , 240 , // 343 - fr-tg
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xea , 1 , 344 , 240 , // 344 - fr-tn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xae , 1 , 345 , 240 , // 345 - fr-vu
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x160 , 1 , 346 , 240 , // 346 - fr-wf
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x14b , 1 , 347 , 240 , // 347 - fr-yt
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x76 , 1 , 349 , 240 , // 348 - fur
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x76 , 1 , 349 , 240 , // 349 - fur-it
- 0x62 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 351 , 351 , // 350 - fy
- 0x462 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 351 , 351 , // 351 - fy-nl
- 0x3c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x44 , 1 , 353 , 353 , // 352 - ga
- 0x83c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x44 , 1 , 353 , 353 , // 353 - ga-ie
- 0x91 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 355 , 355 , // 354 - gd
- 0x491 , 0x4e4 , 0x352 , 0x2710, 0x4f3d, 0xf2 , 1 , 355 , 355 , // 355 - gd-gb
- 0x56 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 357 , 357 , // 356 - gl
- 0x456 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd9 , 1 , 357 , 357 , // 357 - gl-es
- 0x74 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb9 , 1 , 359 , 359 , // 358 - gn
- 0x474 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xb9 , 1 , 359 , 359 , // 359 - gn-py
- 0x84 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xdf , 1 , 361 , 240 , // 360 - gsw
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xdf , 1 , 361 , 240 , // 361 - gsw-ch
- 0x484 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 362 , 362 , // 362 - gsw-fr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x91 , 1 , 363 , 240 , // 363 - gsw-li
- 0x47 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 365 , 143 , // 364 - gu
- 0x447 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 365 , 143 , // 365 - gu-in
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 367 , 240 , // 366 - guz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 367 , 240 , // 367 - guz-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3b16, 1 , 369 , 240 , // 368 - gv
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3b16, 1 , 369 , 240 , // 369 - gv-im
- 0x68 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 374 , 374 , // 370 - ha
- 0x7c68 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 374 , 374 , // 371 - ha-latn
- 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x59 , 1 , 372 , 240 , // 372 - ha-latn-gh
- 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xad , 1 , 373 , 240 , // 373 - ha-latn-ne
- 0x468 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 374 , 374 , // 374 - ha-latn-ng
- 0x75 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 376 , 376 , // 375 - haw
- 0x475 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , 376 , 376 , // 376 - haw-us
- 0xd , 0x4e7 , 0x35e , 0x2715, 0x1f4 , 0x75 , 1 , 378 , 143 , // 377 - he
- 0x40d , 0x4e7 , 0x35e , 0x2715, 0x1f4 , 0x75 , 1 , 378 , 143 , // 378 - he-il
- 0x39 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 380 , 143 , // 379 - hi
- 0x439 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 380 , 143 , // 380 - hi-in
- 0x1a , 0x4e2 , 0x354 , 0x2762, 0x1f4 , 0x6c , 1 , 383 , 383 , // 381 - hr
- 0x101a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 382 , 382 , // 382 - hr-ba
- 0x41a , 0x4e2 , 0x354 , 0x2762, 0x1f4 , 0x6c , 1 , 383 , 383 , // 383 - hr-hr
- 0x2e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 385 , 385 , // 384 - hsb
- 0x42e , 0x4e4 , 0x352 , 0x2710, 0x366 , 0x5e , 1 , 385 , 385 , // 385 - hsb-de
- 0xe , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x6d , 1 , 387 , 387 , // 386 - hu
- 0x40e , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x6d , 1 , 387 , 387 , // 387 - hu-hu
- 0x1040e, 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x6d , 1 , 387 , 387 , // 388 - hu-hu_technl
- 0x2b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x7 , 1 , 390 , 390 , // 389 - hy
- 0x42b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x7 , 1 , 390 , 390 , // 390 - hy-am
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x54 , 1 , 393 , 240 , // 391 - ia
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 392 , 240 , // 392 - ia-001
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x54 , 1 , 393 , 240 , // 393 - ia-fr
- 0x69 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 395 , 240 , // 394 - ibb
- 0x469 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 395 , 240 , // 395 - ibb-ng
- 0x21 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 397 , 397 , // 396 - id
- 0x421 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 397 , 397 , // 397 - id-id
- 0x70 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 399 , 399 , // 398 - ig
- 0x470 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 399 , 399 , // 399 - ig-ng
- 0x78 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 401 , 143 , // 400 - ii
- 0x478 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 401 , 143 , // 401 - ii-cn
- 0xf , 0x4e4 , 0x352 , 0x275f, 0x5187, 0x6e , 1 , 403 , 403 , // 402 - is
- 0x40f , 0x4e4 , 0x352 , 0x275f, 0x5187, 0x6e , 1 , 403 , 403 , // 403 - is-is
- 0x10 , 0x4e4 , 0x352 , 0x2710, 0x4f38, 0x76 , 1 , 406 , 406 , // 404 - it
- 0x810 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xdf , 1 , 405 , 405 , // 405 - it-ch
- 0x410 , 0x4e4 , 0x352 , 0x2710, 0x4f38, 0x76 , 1 , 406 , 406 , // 406 - it-it
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f38, 0xd6 , 1 , 407 , 240 , // 407 - it-sm
- 0x5d , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x27 , 1 , 412 , 412 , // 408 - iu
- 0x785d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x27 , 1 , 410 , 143 , // 409 - iu-cans
- 0x45d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x27 , 1 , 410 , 143 , // 410 - iu-cans-ca
- 0x7c5d , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x27 , 1 , 412 , 412 , // 411 - iu-latn
- 0x85d , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x27 , 1 , 412 , 412 , // 412 - iu-latn-ca
- 0x11 , 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 414 , 414 , // 413 - ja
- 0x411 , 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 414 , 414 , // 414 - ja-jp
- 0x40411, 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 414 , 414 , // 415 - ja-jp_radstr
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 417 , 240 , // 416 - jgo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 417 , 240 , // 417 - jgo-cm
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 419 , 240 , // 418 - jmc
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 419 , 240 , // 419 - jmc-tz
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 424 , 424 , // 420 - jv
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 422 , 424 , // 421 - jv-java
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 422 , 424 , // 422 - jv-java-id
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 424 , 424 , // 423 - jv-latn
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f , 1 , 424 , 424 , // 424 - jv-latn-id
- 0x37 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 426 , 426 , // 425 - ka
- 0x437 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 426 , 426 , // 426 - ka-ge
- 0x10437, 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 426 , 426 , // 427 - ka-ge_modern
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x4 , 1 , 429 , 240 , // 428 - kab
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x4 , 1 , 429 , 240 , // 429 - kab-dz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 431 , 240 , // 430 - kam
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 431 , 240 , // 431 - kam-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 433 , 240 , // 432 - kde
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 433 , 240 , // 433 - kde-tz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x39 , 1 , 435 , 240 , // 434 - kea
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x39 , 1 , 435 , 240 , // 435 - kea-cv
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 437 , 240 , // 436 - khq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 437 , 240 , // 437 - khq-ml
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 439 , 240 , // 438 - ki
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 439 , 240 , // 439 - ki-ke
- 0x3f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x89 , 1 , 441 , 441 , // 440 - kk
- 0x43f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x89 , 1 , 441 , 441 , // 441 - kk-kz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 443 , 240 , // 442 - kkj
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 443 , 240 , // 443 - kkj-cm
- 0x6f , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x5d , 1 , 445 , 445 , // 444 - kl
- 0x46f , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0x5d , 1 , 445 , 445 , // 445 - kl-gl
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 447 , 240 , // 446 - kln
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 447 , 240 , // 447 - kln-ke
- 0x53 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x28 , 2 , 449 , 143 , // 448 - km
- 0x453 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x28 , 2 , 449 , 143 , // 449 - km-kh
- 0x4b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 451 , 143 , // 450 - kn
- 0x44b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 451 , 143 , // 451 - kn-in
- 0x12 , 0x3b5 , 0x3b5 , 0x2713, 0x5161, 0x86 , 1 , 454 , 454 , // 452 - ko
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x83 , 1 , 453 , 240 , // 453 - ko-kp
- 0x412 , 0x3b5 , 0x3b5 , 0x2713, 0x5161, 0x86 , 1 , 454 , 454 , // 454 - ko-kr
- 0x57 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 456 , 143 , // 455 - kok
- 0x457 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 456 , 143 , // 456 - kok-in
- 0x71 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 458 , 240 , // 457 - kr
- 0x471 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xaf , 1 , 458 , 240 , // 458 - kr-ng
- 0x60 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 461 , 240 , // 459 - ks
- 0x460 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 461 , 240 , // 460 - ks-arab
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 461 , 240 , // 461 - ks-arab-in
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 463 , 187 , // 462 - ks-deva
- 0x860 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 463 , 187 , // 463 - ks-deva-in
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 465 , 240 , // 464 - ksb
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 465 , 240 , // 465 - ksb-tz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 467 , 240 , // 466 - ksf
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 467 , 240 , // 467 - ksf-cm
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 469 , 240 , // 468 - ksh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 469 , 240 , // 469 - ksh-de
- 0x92 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 472 , 143 , // 470 - ku
- 0x7c92 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 472 , 143 , // 471 - ku-arab
- 0x492 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x79 , 0 , 472 , 143 , // 472 - ku-arab-iq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 0 , 473 , 240 , // 473 - ku-arab-ir
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf2 , 1 , 475 , 240 , // 474 - kw
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf2 , 1 , 475 , 240 , // 475 - kw-gb
- 0x40 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x82 , 1 , 477 , 477 , // 476 - ky
- 0x440 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x82 , 1 , 477 , 477 , // 477 - ky-kg
- 0x76 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x989e, 1 , 479 , 143 , // 478 - la
- 0x476 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0x989e, 1 , 479 , 143 , // 479 - la-001
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 481 , 240 , // 480 - lag
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 481 , 240 , // 481 - lag-tz
- 0x6e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x93 , 1 , 483 , 483 , // 482 - lb
- 0x46e , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x93 , 1 , 483 , 483 , // 483 - lb-lu
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 485 , 240 , // 484 - lg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 485 , 240 , // 485 - lg-ug
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 487 , 240 , // 486 - lkt
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf4 , 1 , 487 , 240 , // 487 - lkt-us
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 490 , 240 , // 488 - ln
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9 , 1 , 489 , 240 , // 489 - ln-ao
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 490 , 240 , // 490 - ln-cd
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x37 , 1 , 491 , 240 , // 491 - ln-cf
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2b , 1 , 492 , 240 , // 492 - ln-cg
- 0x54 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8a , 1 , 494 , 143 , // 493 - lo
- 0x454 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8a , 1 , 494 , 143 , // 494 - lo-la
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 497 , 240 , // 495 - lrc
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x79 , 2 , 496 , 240 , // 496 - lrc-iq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 497 , 240 , // 497 - lrc-ir
- 0x27 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8d , 1 , 499 , 499 , // 498 - lt
- 0x427 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8d , 1 , 499 , 499 , // 499 - lt-lt
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 501 , 240 , // 500 - lu
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2c , 1 , 501 , 240 , // 501 - lu-cd
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 503 , 240 , // 502 - luo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 503 , 240 , // 503 - luo-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 505 , 240 , // 504 - luy
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 505 , 240 , // 505 - luy-ke
- 0x26 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8c , 1 , 507 , 507 , // 506 - lv
- 0x426 , 0x4e9 , 0x307 , 0x272d, 0x1f4 , 0x8c , 1 , 507 , 507 , // 507 - lv-lv
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 509 , 240 , // 508 - mas
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 509 , 240 , // 509 - mas-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 510 , 240 , // 510 - mas-tz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 512 , 240 , // 511 - mer
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 512 , 240 , // 512 - mer-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa0 , 1 , 514 , 240 , // 513 - mfe
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa0 , 1 , 514 , 240 , // 514 - mfe-mu
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x95 , 1 , 516 , 240 , // 515 - mg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x95 , 1 , 516 , 240 , // 516 - mg-mg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 518 , 240 , // 517 - mgh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 518 , 240 , // 518 - mgh-mz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 520 , 240 , // 519 - mgo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 520 , 240 , // 520 - mgo-cm
- 0x81 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb7 , 1 , 522 , 522 , // 521 - mi
- 0x481 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb7 , 1 , 522 , 522 , // 522 - mi-nz
- 0x2f , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x4ca2, 1 , 524 , 524 , // 523 - mk
- 0x42f , 0x4e3 , 0x362 , 0x2717, 0x1f4 , 0x4ca2, 1 , 524 , 524 , // 524 - mk-mk
- 0x4c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 526 , 143 , // 525 - ml
- 0x44c , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 526 , 143 , // 526 - ml-in
- 0x50 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x9a , 1 , 529 , 529 , // 527 - mn
- 0x7850 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x9a , 1 , 529 , 529 , // 528 - mn-cyrl
- 0x450 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0x9a , 1 , 529 , 529 , // 529 - mn-mn
- 0x7c50 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 531 , 531 , // 530 - mn-mong
- 0x850 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2d , 1 , 531 , 531 , // 531 - mn-mong-cn
- 0xc50 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9a , 1 , 532 , 532 , // 532 - mn-mong-mn
- 0x58 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 534 , 187 , // 533 - mni
- 0x458 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 534 , 187 , // 534 - mni-in
- 0x7c , 0x4e4 , 0x352 , 0x2710, 0x25 , 0x27 , 1 , 536 , 240 , // 535 - moh
- 0x47c , 0x4e4 , 0x352 , 0x2710, 0x25 , 0x27 , 1 , 536 , 240 , // 536 - moh-ca
- 0x4e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 538 , 143 , // 537 - mr
- 0x44e , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 538 , 143 , // 538 - mr-in
- 0x3e , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa7 , 1 , 541 , 541 , // 539 - ms
- 0x83e , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x25 , 1 , 540 , 540 , // 540 - ms-bn
- 0x43e , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa7 , 1 , 541 , 541 , // 541 - ms-my
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd7 , 1 , 542 , 240 , // 542 - ms-sg
- 0x3a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa3 , 1 , 544 , 544 , // 543 - mt
- 0x43a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa3 , 1 , 544 , 544 , // 544 - mt-mt
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 546 , 240 , // 545 - mua
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 546 , 240 , // 546 - mua-cm
- 0x55 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x1b , 2 , 548 , 240 , // 547 - my
- 0x455 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x1b , 2 , 548 , 240 , // 548 - my-mm
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 550 , 240 , // 549 - mzn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x74 , 2 , 550 , 240 , // 550 - mzn-ir
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xfe , 1 , 552 , 240 , // 551 - naq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xfe , 1 , 552 , 240 , // 552 - naq-na
- 0x7c14 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 554 , 554 , // 553 - nb
- 0x414 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 554 , 554 , // 554 - nb-no
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xdc , 1 , 555 , 240 , // 555 - nb-sj
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 557 , 240 , // 556 - nd
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 557 , 240 , // 557 - nd-zw
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 559 , 240 , // 558 - nds
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x5e , 1 , 559 , 240 , // 559 - nds-de
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb0 , 1 , 560 , 240 , // 560 - nds-nl
- 0x61 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb2 , 1 , 563 , 143 , // 561 - ne
- 0x861 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 2 , 562 , 240 , // 562 - ne-in
- 0x461 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xb2 , 1 , 563 , 143 , // 563 - ne-np
- 0x13 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 569 , 569 , // 564 - nl
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x12e , 1 , 565 , 240 , // 565 - nl-aw
- 0x813 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x15 , 1 , 566 , 566 , // 566 - nl-be
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9a55d42, 1 , 567 , 240 , // 567 - nl-bq
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x111 , 1 , 568 , 240 , // 568 - nl-cw
- 0x413 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb0 , 1 , 569 , 569 , // 569 - nl-nl
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xb5 , 1 , 570 , 240 , // 570 - nl-sr
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x78f7, 1 , 571 , 240 , // 571 - nl-sx
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 573 , 240 , // 572 - nmg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 573 , 240 , // 573 - nmg-cm
- 0x7814 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 575 , 575 , // 574 - nn
- 0x814 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 575 , 575 , // 575 - nn-no
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 577 , 240 , // 576 - nnh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 577 , 240 , // 577 - nnh-cm
- 0x14 , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 554 , 554 , // 578 - no
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x64 , 2 , 580 , 143 , // 579 - nqo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x64 , 2 , 580 , 143 , // 580 - nqo-gn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 582 , 240 , // 581 - nr
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 582 , 240 , // 582 - nr-za
- 0x6c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 584 , 584 , // 583 - nso
- 0x46c , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 584 , 584 , // 584 - nso-za
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x114 , 1 , 586 , 240 , // 585 - nus
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x114 , 1 , 586 , 240 , // 586 - nus-ss
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 588 , 240 , // 587 - nyn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 588 , 240 , // 588 - nyn-ug
- 0x82 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 590 , 590 , // 589 - oc
- 0x482 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x54 , 1 , 590 , 590 , // 590 - oc-fr
- 0x72 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 592 , 240 , // 591 - om
- 0x472 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 592 , 240 , // 592 - om-et
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 593 , 240 , // 593 - om-ke
- 0x48 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 595 , 143 , // 594 - or
- 0x448 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 595 , 143 , // 595 - or-in
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 597 , 240 , // 596 - os
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x58 , 1 , 597 , 240 , // 597 - os-ge
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xcb , 1 , 598 , 240 , // 598 - os-ru
- 0x46 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 602 , 143 , // 599 - pa
- 0x7c46 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 601 , 143 , // 600 - pa-arab
- 0x846 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 601 , 143 , // 601 - pa-arab-pk
- 0x446 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 602 , 143 , // 602 - pa-in
- 0x79 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x993248, 1 , 604 , 145 , // 603 - pap
- 0x479 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x993248, 1 , 604 , 145 , // 604 - pap-029
- 0x15 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xbf , 1 , 606 , 606 , // 605 - pl
- 0x415 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xbf , 1 , 606 , 606 , // 606 - pl-pl
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 608 , 240 , // 607 - prg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 608 , 240 , // 608 - prg-001
- 0x8c , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x3 , 2 , 610 , 143 , // 609 - prs
- 0x48c , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x3 , 2 , 610 , 143 , // 610 - prs-af
- 0x63 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 612 , 143 , // 611 - ps
- 0x463 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 612 , 143 , // 612 - ps-af
- 0x16 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x20 , 1 , 615 , 615 , // 613 - pt
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x9 , 1 , 614 , 240 , // 614 - pt-ao
- 0x416 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x20 , 1 , 615 , 615 , // 615 - pt-br
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 616 , 240 , // 616 - pt-ch
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x39 , 1 , 617 , 240 , // 617 - pt-cv
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x45 , 1 , 618 , 240 , // 618 - pt-gq
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc4 , 1 , 619 , 240 , // 619 - pt-gw
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x93 , 1 , 620 , 240 , // 620 - pt-lu
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x97 , 1 , 621 , 240 , // 621 - pt-mo
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xa8 , 1 , 622 , 240 , // 622 - pt-mz
- 0x816 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xc1 , 1 , 623 , 623 , // 623 - pt-pt
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xe9 , 1 , 624 , 240 , // 624 - pt-st
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x6f60e7, 1 , 625 , 240 , // 625 - pt-tl
- 0x901 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x7c , 1 , 626 , 190 , // 626 - qps-latn-x-sh
- 0x501 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xf4 , 1 , 627 , 627 , // 627 - qps-ploc
- 0x5fe , 0x3a4 , 0x3a4 , 0x2711, 0x4f42, 0x7a , 1 , 628 , 628 , // 628 - qps-ploca
- 0x9ff , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xcd , 0 , 629 , 143 , // 629 - qps-plocm
- 0x86 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 632 , 632 , // 630 - quc
- 0x7c86 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 632 , 632 , // 631 - quc-latn
- 0x486 , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x63 , 1 , 632 , 632 , // 632 - quc-latn-gt
- 0x6b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x1a , 1 , 634 , 634 , // 633 - quz
- 0x46b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x1a , 1 , 634 , 634 , // 634 - quz-bo
- 0x86b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0x42 , 1 , 635 , 635 , // 635 - quz-ec
- 0xc6b , 0x4e4 , 0x352 , 0x2710, 0x4f3c, 0xbb , 1 , 636 , 636 , // 636 - quz-pe
- 0x17 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xdf , 1 , 638 , 638 , // 637 - rm
- 0x417 , 0x4e4 , 0x352 , 0x2710, 0x4f31, 0xdf , 1 , 638 , 638 , // 638 - rm-ch
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x26 , 1 , 640 , 240 , // 639 - rn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x26 , 1 , 640 , 240 , // 640 - rn-bi
- 0x18 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xc8 , 1 , 643 , 643 , // 641 - ro
- 0x818 , 0x4e2 , 0x354 , 0x2 , 0x1f4 , 0x98 , 1 , 642 , 240 , // 642 - ro-md
- 0x418 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xc8 , 1 , 643 , 643 , // 643 - ro-ro
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 645 , 240 , // 644 - rof
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 645 , 240 , // 645 - rof-tz
- 0x19 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 651 , 651 , // 646 - ru
- 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x1d , 1 , 647 , 240 , // 647 - ru-by
- 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x82 , 1 , 648 , 240 , // 648 - ru-kg
- 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x89 , 1 , 649 , 240 , // 649 - ru-kz
- 0x819 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0x98 , 1 , 650 , 240 , // 650 - ru-md
- 0x419 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 651 , 651 , // 651 - ru-ru
- 0x1000 , 0x4e3 , 0x362 , 0x2 , 0x1f4 , 0xf1 , 1 , 652 , 240 , // 652 - ru-ua
- 0x87 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xcc , 1 , 654 , 654 , // 653 - rw
- 0x487 , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xcc , 1 , 654 , 654 , // 654 - rw-rw
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 656 , 240 , // 655 - rwk
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 656 , 240 , // 656 - rwk-tz
- 0x4f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 658 , 143 , // 657 - sa
- 0x44f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 658 , 143 , // 658 - sa-in
- 0x85 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 660 , 660 , // 659 - sah
- 0x485 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 660 , 660 , // 660 - sah-ru
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 662 , 240 , // 661 - saq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 662 , 240 , // 662 - saq-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 664 , 240 , // 663 - sbp
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 664 , 240 , // 664 - sbp-tz
- 0x59 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 667 , 143 , // 665 - sd
- 0x7c59 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 667 , 143 , // 666 - sd-arab
- 0x859 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 2 , 667 , 143 , // 667 - sd-arab-pk
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 669 , 187 , // 668 - sd-deva
- 0x459 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 669 , 187 , // 669 - sd-deva-in
- 0x3b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 672 , 672 , // 670 - se
- 0xc3b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 671 , 671 , // 671 - se-fi
- 0x43b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 672 , 672 , // 672 - se-no
- 0x83b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 673 , 673 , // 673 - se-se
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 675 , 240 , // 674 - seh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa8 , 1 , 675 , 240 , // 675 - seh-mz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 677 , 240 , // 676 - ses
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9d , 1 , 677 , 240 , // 677 - ses-ml
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x37 , 1 , 679 , 240 , // 678 - sg
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x37 , 1 , 679 , 240 , // 679 - sg-cf
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 684 , 240 , // 680 - shi
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 682 , 240 , // 681 - shi-latn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 682 , 240 , // 682 - shi-latn-ma
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 684 , 240 , // 683 - shi-tfng
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 684 , 240 , // 684 - shi-tfng-ma
- 0x5b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2a , 1 , 686 , 143 , // 685 - si
- 0x45b , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2a , 1 , 686 , 143 , // 686 - si-lk
- 0x1b , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x8f , 1 , 688 , 688 , // 687 - sk
- 0x41b , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x8f , 1 , 688 , 688 , // 688 - sk-sk
- 0x24 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xd4 , 1 , 690 , 690 , // 689 - sl
- 0x424 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xd4 , 1 , 690 , 690 , // 690 - sl-si
- 0x783b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 693 , 693 , // 691 - sma
- 0x183b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 692 , 692 , // 692 - sma-no
- 0x1c3b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 693 , 693 , // 693 - sma-se
- 0x7c3b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 696 , 696 , // 694 - smj
- 0x103b , 0x4e4 , 0x352 , 0x2710, 0x4f35, 0xb1 , 1 , 695 , 695 , // 695 - smj-no
- 0x143b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 696 , 696 , // 696 - smj-se
- 0x703b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 698 , 698 , // 697 - smn
- 0x243b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 698 , 698 , // 698 - smn-fi
- 0x743b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 700 , 700 , // 699 - sms
- 0x203b , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 700 , 700 , // 700 - sms-fi
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 703 , 240 , // 701 - sn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 703 , 240 , // 702 - sn-latn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x108 , 1 , 703 , 240 , // 703 - sn-latn-zw
- 0x77 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd8 , 1 , 708 , 240 , // 704 - so
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3e , 1 , 705 , 240 , // 705 - so-dj
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 706 , 240 , // 706 - so-et
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 707 , 240 , // 707 - so-ke
- 0x477 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd8 , 1 , 708 , 240 , // 708 - so-so
- 0x1c , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x6 , 1 , 710 , 710 , // 709 - sq
- 0x41c , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x6 , 1 , 710 , 710 , // 710 - sq-al
- 0x1000 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x4ca2, 1 , 711 , 240 , // 711 - sq-mk
- 0x1000 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0x974941, 1 , 712 , 240 , // 712 - sq-xk
- 0x7c1a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10f , 1 , 724 , 724 , // 713 - sr
- 0x6c1a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10f , 1 , 718 , 718 , // 714 - sr-cyrl
- 0x1c1a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x19 , 1 , 715 , 715 , // 715 - sr-cyrl-ba
- 0xc1a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10d , 1 , 716 , 716 , // 716 - sr-cyrl-cs
- 0x301a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10e , 1 , 717 , 717 , // 717 - sr-cyrl-me
- 0x281a , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x10f , 1 , 718 , 718 , // 718 - sr-cyrl-rs
- 0x1000 , 0x4e3 , 0x357 , 0x2717, 0x5221, 0x974941, 1 , 719 , 240 , // 719 - sr-cyrl-xk
- 0x701a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10f , 1 , 724 , 724 , // 720 - sr-latn
- 0x181a , 0x4e2 , 0x354 , 0x2762, 0x366 , 0x19 , 1 , 721 , 721 , // 721 - sr-latn-ba
- 0x81a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10d , 1 , 722 , 722 , // 722 - sr-latn-cs
- 0x2c1a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10e , 1 , 723 , 723 , // 723 - sr-latn-me
- 0x241a , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x10f , 1 , 724 , 724 , // 724 - sr-latn-rs
- 0x1000 , 0x4e2 , 0x354 , 0x272d, 0x1f4 , 0x974941, 1 , 725 , 240 , // 725 - sr-latn-xk
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 728 , 240 , // 726 - ss
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x104 , 1 , 727 , 240 , // 727 - ss-sz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 728 , 240 , // 728 - ss-za
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 730 , 240 , // 729 - ssy
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 730 , 240 , // 730 - ssy-er
- 0x30 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 733 , 240 , // 731 - st
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x92 , 1 , 732 , 240 , // 732 - st-ls
- 0x430 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 733 , 240 , // 733 - st-za
- 0x1d , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 737 , 737 , // 734 - sv
- 0x1000 , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x9906f5, 1 , 735 , 240 , // 735 - sv-ax
- 0x81d , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0x4d , 1 , 736 , 736 , // 736 - sv-fi
- 0x41d , 0x4e4 , 0x352 , 0x2710, 0x4f36, 0xdd , 1 , 737 , 737 , // 737 - sv-se
- 0x41 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x81 , 1 , 740 , 740 , // 738 - sw
- 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x2c , 1 , 739 , 740 , // 739 - sw-cd
- 0x441 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x81 , 1 , 740 , 740 , // 740 - sw-ke
- 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xef , 1 , 741 , 240 , // 741 - sw-tz
- 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0xf0 , 1 , 742 , 240 , // 742 - sw-ug
- 0x1000 , 0x0 , 0x1 , 0x0 , 0x1f4 , 0x2c , 1 , 744 , 240 , // 743 - swc
- 0x1000 , 0x0 , 0x1 , 0x0 , 0x1f4 , 0x2c , 1 , 744 , 240 , // 744 - swc-cd
- 0x5a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xde , 1 , 746 , 143 , // 745 - syr
- 0x45a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xde , 1 , 746 , 143 , // 746 - syr-sy
- 0x49 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 748 , 143 , // 747 - ta
- 0x449 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 748 , 143 , // 748 - ta-in
- 0x849 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x2a , 1 , 749 , 143 , // 749 - ta-lk
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xa7 , 1 , 750 , 240 , // 750 - ta-my
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd7 , 1 , 751 , 240 , // 751 - ta-sg
- 0x4a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 753 , 143 , // 752 - te
- 0x44a , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x71 , 1 , 753 , 143 , // 753 - te-in
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 756 , 240 , // 754 - teo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x81 , 1 , 755 , 240 , // 755 - teo-ke
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 756 , 240 , // 756 - teo-ug
- 0x28 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xe4 , 1 , 759 , 759 , // 757 - tg
- 0x7c28 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xe4 , 1 , 759 , 759 , // 758 - tg-cyrl
- 0x428 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xe4 , 1 , 759 , 759 , // 759 - tg-cyrl-tj
- 0x1e , 0x36a , 0x36a , 0x2725, 0x5166, 0xe3 , 1 , 761 , 143 , // 760 - th
- 0x41e , 0x36a , 0x36a , 0x2725, 0x5166, 0xe3 , 1 , 761 , 143 , // 761 - th-th
- 0x73 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 763 , 143 , // 762 - ti
- 0x873 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 763 , 143 , // 763 - ti-er
- 0x473 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 764 , 143 , // 764 - ti-et
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 766 , 240 , // 765 - tig
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x47 , 1 , 766 , 240 , // 766 - tig-er
- 0x42 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xee , 1 , 768 , 768 , // 767 - tk
- 0x442 , 0x4e2 , 0x354 , 0x272d, 0x5190, 0xee , 1 , 768 , 768 , // 768 - tk-tm
- 0x32 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 771 , 771 , // 769 - tn
- 0x832 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0x13 , 1 , 770 , 770 , // 770 - tn-bw
- 0x432 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 771 , 771 , // 771 - tn-za
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe7 , 1 , 773 , 240 , // 772 - to
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xe7 , 1 , 773 , 240 , // 773 - to-to
- 0x1f , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0xeb , 1 , 776 , 776 , // 774 - tr
- 0x1000 , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0x3b , 1 , 775 , 240 , // 775 - tr-cy
- 0x41f , 0x4e6 , 0x359 , 0x2761, 0x51a9, 0xeb , 1 , 776 , 776 , // 776 - tr-tr
- 0x31 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 778 , 240 , // 777 - ts
- 0x431 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 778 , 240 , // 778 - ts-za
- 0x44 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 780 , 780 , // 779 - tt
- 0x444 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xcb , 1 , 780 , 780 , // 780 - tt-ru
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 782 , 240 , // 781 - twq
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xad , 1 , 782 , 240 , // 782 - twq-ne
- 0x5f , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 787 , 787 , // 783 - tzm
- 0x1000 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x9f , 1 , 785 , 240 , // 784 - tzm-arab
- 0x45f , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x9f , 1 , 785 , 240 , // 785 - tzm-arab-ma
- 0x7c5f , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 787 , 787 , // 786 - tzm-latn
- 0x85f , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0x4 , 1 , 787 , 787 , // 787 - tzm-latn-dz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 788 , 240 , // 788 - tzm-latn-ma
- 0x785f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 790 , 316 , // 789 - tzm-tfng
- 0x105f , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 790 , 316 , // 790 - tzm-tfng-ma
- 0x80 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x2d , 1 , 792 , 143 , // 791 - ug
- 0x480 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0x2d , 1 , 792 , 143 , // 792 - ug-cn
- 0x22 , 0x4e3 , 0x362 , 0x2721, 0x1f4 , 0xf1 , 1 , 794 , 794 , // 793 - uk
- 0x422 , 0x4e3 , 0x362 , 0x2721, 0x1f4 , 0xf1 , 1 , 794 , 794 , // 794 - uk-ua
- 0x20 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 1 , 797 , 143 , // 795 - ur
- 0x820 , 0x4e8 , 0x2d0 , 0x2 , 0x1f4 , 0x71 , 2 , 796 , 240 , // 796 - ur-in
- 0x420 , 0x4e8 , 0x2d0 , 0x2714, 0x4fc4, 0xbe , 1 , 797 , 143 , // 797 - ur-pk
- 0x43 , 0x4e6 , 0x359 , 0x272d, 0x1f4 , 0xf7 , 1 , 804 , 804 , // 798 - uz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 800 , 240 , // 799 - uz-arab
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x3 , 2 , 800 , 240 , // 800 - uz-arab-af
- 0x7843 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xf7 , 1 , 802 , 802 , // 801 - uz-cyrl
- 0x843 , 0x4e3 , 0x362 , 0x2717, 0x5190, 0xf7 , 1 , 802 , 802 , // 802 - uz-cyrl-uz
- 0x7c43 , 0x4e6 , 0x359 , 0x272d, 0x1f4 , 0xf7 , 1 , 804 , 804 , // 803 - uz-latn
- 0x443 , 0x4e6 , 0x359 , 0x272d, 0x1f4 , 0xf7 , 1 , 804 , 804 , // 804 - uz-latn-uz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 809 , 240 , // 805 - vai
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 807 , 240 , // 806 - vai-latn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 807 , 240 , // 807 - vai-latn-lr
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 809 , 240 , // 808 - vai-vaii
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x8e , 1 , 809 , 240 , // 809 - vai-vaii-lr
- 0x33 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 811 , 240 , // 810 - ve
- 0x433 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xd1 , 1 , 811 , 240 , // 811 - ve-za
- 0x2a , 0x4ea , 0x4ea , 0x2710, 0x1f4 , 0xfb , 1 , 813 , 143 , // 812 - vi
- 0x42a , 0x4ea , 0x4ea , 0x2710, 0x1f4 , 0xfb , 1 , 813 , 143 , // 813 - vi-vn
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 815 , 240 , // 814 - vo
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 815 , 240 , // 815 - vo-001
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 817 , 240 , // 816 - vun
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xef , 1 , 817 , 240 , // 817 - vun-tz
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 819 , 240 , // 818 - wae
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xdf , 1 , 819 , 240 , // 819 - wae-ch
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 821 , 240 , // 820 - wal
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 , 821 , 240 , // 821 - wal-et
- 0x88 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 823 , 823 , // 822 - wo
- 0x488 , 0x4e4 , 0x352 , 0x2710, 0x4f49, 0xd2 , 1 , 823 , 823 , // 823 - wo-sn
- 0x1007f, 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xf4 , 1 , -1 , -1 , // 824 - x-iv_mathan
- 0x34 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 826 , 826 , // 825 - xh
- 0x434 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 826 , 826 , // 826 - xh-za
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 828 , 240 , // 827 - xog
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0xf0 , 1 , 828 , 240 , // 828 - xog-ug
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 830 , 240 , // 829 - yav
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x31 , 1 , 830 , 240 , // 830 - yav-cm
- 0x3d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 832 , 240 , // 831 - yi
- 0x43d , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x989e, 1 , 832 , 240 , // 832 - yi-001
- 0x6a , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 835 , 835 , // 833 - yo
- 0x1000 , 0x4e4 , 0x1b5 , 0x2710, 0x1f4 , 0x1c , 1 , 834 , 240 , // 834 - yo-bj
- 0x46a , 0x4e4 , 0x1b5 , 0x2710, 0x25 , 0xaf , 1 , 835 , 835 , // 835 - yo-ng
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x68 , 1 , 837 , 240 , // 836 - yue
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x68 , 1 , 837 , 240 , // 837 - yue-hk
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 840 , 316 , // 838 - zgh
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 840 , 316 , // 839 - zgh-tfng
- 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x9f , 1 , 840 , 316 , // 840 - zgh-tfng-ma
- 0x7804 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 841 - zh
- 0x4 , 0x3a8 , 0x3a8 , 0x0 , 0x1f4 , 0x2d , 1 , 844 , 844 , // 842 - zh-chs
- 0x7c04 , 0x3b6 , 0x3b6 , 0x0 , 0x1f4 , 0x68 , 1 , 851 , 851 , // 843 - zh-cht
- 0x804 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 844 - zh-cn
- 0x50804, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 845 - zh-cn_phoneb
- 0x20804, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 846 - zh-cn_stroke
- 0x4 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x2d , 1 , 844 , 844 , // 847 - zh-hans
- 0x1000 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x68 , 1 , 848 , 240 , // 848 - zh-hans-hk
- 0x1000 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0x97 , 1 , 849 , 240 , // 849 - zh-hans-mo
- 0x7c04 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x68 , 1 , 851 , 851 , // 850 - zh-hant
- 0xc04 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x68 , 1 , 851 , 851 , // 851 - zh-hk
- 0x40c04, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x68 , 1 , 851 , 851 , // 852 - zh-hk_radstr
- 0x1404 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x97 , 1 , 853 , 853 , // 853 - zh-mo
- 0x41404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x97 , 1 , 853 , 853 , // 854 - zh-mo_radstr
- 0x21404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0x97 , 1 , 853 , 853 , // 855 - zh-mo_stroke
- 0x1004 , 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0xd7 , 1 , 856 , 856 , // 856 - zh-sg
- 0x51004, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0xd7 , 1 , 856 , 856 , // 857 - zh-sg_phoneb
- 0x21004, 0x3a8 , 0x3a8 , 0x2718, 0x1f4 , 0xd7 , 1 , 856 , 856 , // 858 - zh-sg_stroke
- 0x404 , 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0xed , 1 , 859 , 859 , // 859 - zh-tw
- 0x30404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0xed , 1 , 859 , 859 , // 860 - zh-tw_pronun
- 0x40404, 0x3b6 , 0x3b6 , 0x2712, 0x1f4 , 0xed , 1 , 859 , 859 , // 861 - zh-tw_radstr
- 0x35 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 863 , 863 , // 862 - zu
- 0x435 , 0x4e4 , 0x352 , 0x2710, 0x1f4 , 0xd1 , 1 , 863 , 863 , // 863 - zu-za
- };
-
- // s_lcids list all supported lcids. used to binary search and we use the index of the matched lcid to
- // get the index in s_localeNamesIndices using s_lcidToCultureNameIndices
- private static readonly int[] s_lcids = new int[]
- {
- // Lcid , index - index in c_localeNames
- 0x1 , // 0 - 52
- 0x2 , // 1 - 301
- 0x3 , // 2 - 421
- 0x4 , // 3 - 4139
- 0x5 , // 4 - 502
- 0x6 , // 5 - 523
- 0x7 , // 6 - 544
- 0x8 , // 7 - 664
- 0x9 , // 8 - 676
- 0xa , // 9 - 1214
- 0xb , // 10 - 1423
- 0xc , // 11 - 1451
- 0xd , // 12 - 1825
- 0xe , // 13 - 1860
- 0xf , // 14 - 1929
- 0x10 , // 15 - 1936
- 0x11 , // 16 - 1989
- 0x12 , // 17 - 2179
- 0x13 , // 18 - 2685
- 0x14 , // 19 - 2747
- 0x15 , // 20 - 2864
- 0x16 , // 21 - 2897
- 0x17 , // 22 - 3041
- 0x18 , // 23 - 3055
- 0x19 , // 24 - 3076
- 0x1a , // 25 - 1839
- 0x1b , // 26 - 3284
- 0x1c , // 27 - 3387
- 0x1d , // 28 - 3553
- 0x1e , // 29 - 3673
- 0x1f , // 30 - 3727
- 0x20 , // 31 - 3847
- 0x21 , // 32 - 1908
- 0x22 , // 33 - 3840
- 0x23 , // 34 - 276
- 0x24 , // 35 - 3291
- 0x25 , // 36 - 1354
- 0x26 , // 37 - 2429
- 0x27 , // 38 - 2397
- 0x28 , // 39 - 3654
- 0x29 , // 40 - 1377
- 0x2a , // 41 - 3960
- 0x2b , // 42 - 1879
- 0x2c , // 43 - 224
- 0x2d , // 44 - 1361
- 0x2e , // 45 - 1851
- 0x2f , // 46 - 2501
- 0x30 , // 47 - 3541
- 0x31 , // 48 - 3739
- 0x32 , // 49 - 3708
- 0x33 , // 50 - 3953
- 0x34 , // 51 - 4020
- 0x35 , // 52 - 4277
- 0x36 , // 53 - 17
- 0x37 , // 54 - 2062
- 0x38 , // 55 - 1439
- 0x39 , // 56 - 1832
- 0x3a , // 57 - 2598
- 0x3b , // 58 - 3194
- 0x3c , // 59 - 1705
- 0x3d , // 60 - 4045
- 0x3e , // 61 - 2581
- 0x3f , // 62 - 2133
- 0x40 , // 63 - 2306
- 0x41 , // 64 - 3570
- 0x42 , // 65 - 3701
- 0x43 , // 66 - 3859
- 0x44 , // 67 - 3746
- 0x45 , // 68 - 336
- 0x46 , // 69 - 2830
- 0x47 , // 70 - 1754
- 0x48 , // 71 - 2811
- 0x49 , // 72 - 3610
- 0x4a , // 73 - 3632
- 0x4b , // 74 - 2172
- 0x4c , // 75 - 2508
- 0x4d , // 76 - 199
- 0x4e , // 77 - 2574
- 0x4f , // 78 - 3124
- 0x50 , // 79 - 2515
- 0x51 , // 80 - 348
- 0x52 , // 81 - 516
- 0x53 , // 82 - 2165
- 0x54 , // 83 - 2375
- 0x55 , // 84 - 2614
- 0x56 , // 85 - 1719
- 0x57 , // 86 - 2191
- 0x58 , // 87 - 2556
- 0x59 , // 88 - 3158
- 0x5a , // 89 - 3601
- 0x5b , // 90 - 3277
- 0x5c , // 91 - 473
- 0x5d , // 92 - 1953
- 0x5e , // 93 - 45
- 0x5f , // 94 - 3762
- 0x60 , // 95 - 2207
- 0x61 , // 96 - 2673
- 0x62 , // 97 - 1698
- 0x63 , // 98 - 2890
- 0x64 , // 99 - 1430
- 0x65 , // 100 - 620
- 0x66 , // 101 - 308
- 0x67 , // 102 - 1384
- 0x68 , // 103 - 1777
- 0x69 , // 104 - 1899
- 0x6a , // 105 - 4053
- 0x6b , // 106 - 3020
- 0x6c , // 107 - 2765
- 0x6d , // 108 - 260
- 0x6e , // 109 - 2330
- 0x6f , // 110 - 2149
- 0x70 , // 111 - 1915
- 0x71 , // 112 - 2200
- 0x72 , // 113 - 2799
- 0x73 , // 114 - 3680
- 0x74 , // 115 - 1726
- 0x75 , // 116 - 1816
- 0x76 , // 117 - 2313
- 0x77 , // 118 - 3365
- 0x78 , // 119 - 1922
- 0x79 , // 120 - 2854
- 0x7a , // 121 - 190
- 0x7c , // 122 - 2565
- 0x7e , // 123 - 360
- 0x80 , // 124 - 3833
- 0x81 , // 125 - 2494
- 0x82 , // 126 - 2792
- 0x83 , // 127 - 495
- 0x84 , // 128 - 1733
- 0x85 , // 129 - 3131
- 0x86 , // 130 - 2998
- 0x87 , // 131 - 3108
- 0x88 , // 132 - 4002
- 0x8c , // 133 - 2881
- 0x91 , // 134 - 1712
- 0x92 , // 135 - 2270
- 0x401 , // 136 - 150
- 0x402 , // 137 - 303
- 0x403 , // 138 - 428
- 0x404 , // 139 - 4248
- 0x405 , // 140 - 504
- 0x406 , // 141 - 525
- 0x407 , // 142 - 561
- 0x408 , // 143 - 671
- 0x409 , // 144 - 1161
- 0x40a , // 145 - 1272
- 0x40b , // 146 - 1425
- 0x40c , // 147 - 1529
- 0x40d , // 148 - 1827
- 0x40e , // 149 - 1862
- 0x40f , // 150 - 1931
- 0x410 , // 151 - 1943
- 0x411 , // 152 - 1991
- 0x412 , // 153 - 2186
- 0x413 , // 154 - 2707
- 0x414 , // 155 - 2641
- 0x415 , // 156 - 2866
- 0x416 , // 157 - 2904
- 0x417 , // 158 - 3043
- 0x418 , // 159 - 3062
- 0x419 , // 160 - 3098
- 0x41a , // 161 - 1846
- 0x41b , // 162 - 3286
- 0x41c , // 163 - 3389
- 0x41d , // 164 - 3565
- 0x41e , // 165 - 3675
- 0x41f , // 166 - 3734
- 0x420 , // 167 - 3854
- 0x421 , // 168 - 1910
- 0x422 , // 169 - 3842
- 0x423 , // 170 - 278
- 0x424 , // 171 - 3293
- 0x425 , // 172 - 1356
- 0x426 , // 173 - 2431
- 0x427 , // 174 - 2399
- 0x428 , // 175 - 3663
- 0x429 , // 176 - 1379
- 0x42a , // 177 - 3962
- 0x42b , // 178 - 1881
- 0x42c , // 179 - 250
- 0x42d , // 180 - 1363
- 0x42e , // 181 - 1854
- 0x42f , // 182 - 2503
- 0x430 , // 183 - 3548
- 0x431 , // 184 - 3741
- 0x432 , // 185 - 3715
- 0x433 , // 186 - 3955
- 0x434 , // 187 - 4022
- 0x435 , // 188 - 4279
- 0x436 , // 189 - 24
- 0x437 , // 190 - 2064
- 0x438 , // 191 - 1446
- 0x439 , // 192 - 1834
- 0x43a , // 193 - 2600
- 0x43b , // 194 - 3201
- 0x43d , // 195 - 4047
- 0x43e , // 196 - 2588
- 0x43f , // 197 - 2135
- 0x440 , // 198 - 2308
- 0x441 , // 199 - 3577
- 0x442 , // 200 - 3703
- 0x443 , // 201 - 3902
- 0x444 , // 202 - 3748
- 0x445 , // 203 - 343
- 0x446 , // 204 - 2849
- 0x447 , // 205 - 1756
- 0x448 , // 206 - 2813
- 0x449 , // 207 - 3612
- 0x44a , // 208 - 3634
- 0x44b , // 209 - 2174
- 0x44c , // 210 - 2510
- 0x44d , // 211 - 201
- 0x44e , // 212 - 2576
- 0x44f , // 213 - 3126
- 0x450 , // 214 - 2524
- 0x451 , // 215 - 350
- 0x452 , // 216 - 518
- 0x453 , // 217 - 2167
- 0x454 , // 218 - 2377
- 0x455 , // 219 - 2616
- 0x456 , // 220 - 1721
- 0x457 , // 221 - 2194
- 0x458 , // 222 - 2559
- 0x459 , // 223 - 3184
- 0x45a , // 224 - 3604
- 0x45b , // 225 - 3279
- 0x45c , // 226 - 484
- 0x45d , // 227 - 1962
- 0x45e , // 228 - 47
- 0x45f , // 229 - 3773
- 0x460 , // 230 - 2209
- 0x461 , // 231 - 2680
- 0x462 , // 232 - 1700
- 0x463 , // 233 - 2892
- 0x464 , // 234 - 1433
- 0x465 , // 235 - 622
- 0x466 , // 236 - 311
- 0x467 , // 237 - 1418
- 0x468 , // 238 - 1806
- 0x469 , // 239 - 1902
- 0x46a , // 240 - 4060
- 0x46b , // 241 - 3023
- 0x46c , // 242 - 2768
- 0x46d , // 243 - 262
- 0x46e , // 244 - 2332
- 0x46f , // 245 - 2151
- 0x470 , // 246 - 1917
- 0x471 , // 247 - 2202
- 0x472 , // 248 - 2801
- 0x473 , // 249 - 3687
- 0x474 , // 250 - 1728
- 0x475 , // 251 - 1819
- 0x476 , // 252 - 2315
- 0x477 , // 253 - 3382
- 0x478 , // 254 - 1924
- 0x479 , // 255 - 2857
- 0x47a , // 256 - 193
- 0x47c , // 257 - 2568
- 0x47e , // 258 - 362
- 0x480 , // 259 - 3835
- 0x481 , // 260 - 2496
- 0x482 , // 261 - 2794
- 0x483 , // 262 - 497
- 0x484 , // 263 - 1742
- 0x485 , // 264 - 3134
- 0x486 , // 265 - 3009
- 0x487 , // 266 - 3110
- 0x488 , // 267 - 4004
- 0x48c , // 268 - 2884
- 0x491 , // 269 - 1714
- 0x492 , // 270 - 2279
- 0x501 , // 271 - 2972
- 0x5fe , // 272 - 2980
- 0x801 , // 273 - 95
- 0x803 , // 274 - 433
- 0x804 , // 275 - 4110
- 0x807 , // 276 - 556
- 0x809 , // 277 - 831
- 0x80a , // 278 - 1299
- 0x80c , // 279 - 1459
- 0x810 , // 280 - 1938
- 0x813 , // 281 - 2692
- 0x814 , // 282 - 2733
- 0x816 , // 283 - 2944
- 0x818 , // 284 - 3057
- 0x819 , // 285 - 3093
- 0x81a , // 286 - 3480
- 0x81d , // 287 - 3560
- 0x820 , // 288 - 3849
- 0x82c , // 289 - 233
- 0x82e , // 290 - 605
- 0x832 , // 291 - 3710
- 0x83b , // 292 - 3206
- 0x83c , // 293 - 1707
- 0x83e , // 294 - 2583
- 0x843 , // 295 - 3885
- 0x845 , // 296 - 338
- 0x846 , // 297 - 2839
- 0x849 , // 298 - 3617
- 0x850 , // 299 - 2536
- 0x859 , // 300 - 3167
- 0x85d , // 301 - 1979
- 0x85f , // 302 - 3792
- 0x860 , // 303 - 2233
- 0x861 , // 304 - 2675
- 0x867 , // 305 - 1403
- 0x86b , // 306 - 3029
- 0x873 , // 307 - 3682
- 0x901 , // 308 - 2959
- 0x9ff , // 309 - 2989
- 0xc01 , // 310 - 80
- 0xc04 , // 311 - 4173
- 0xc07 , // 312 - 546
- 0xc09 , // 313 - 716
- 0xc0a , // 314 - 1267
- 0xc0c , // 315 - 1484
- 0xc1a , // 316 - 3423
- 0xc3b , // 317 - 3196
- 0xc50 , // 318 - 2546
- 0xc51 , // 319 - 638
- 0xc6b , // 320 - 3035
- 0x1001 , // 321 - 120
- 0x1004 , // 322 - 4219
- 0x1007 , // 323 - 588
- 0x1009 , // 324 - 756
- 0x100a , // 325 - 1289
- 0x100c , // 326 - 1504
- 0x101a , // 327 - 1841
- 0x103b , // 328 - 3316
- 0x105f , // 329 - 3822
- 0x1401 , // 330 - 75
- 0x1404 , // 331 - 4190
- 0x1407 , // 332 - 583
- 0x1409 , // 333 - 1026
- 0x140a , // 334 - 1247
- 0x140c , // 335 - 1569
- 0x141a , // 336 - 402
- 0x143b , // 337 - 3322
- 0x1801 , // 338 - 125
- 0x1809 , // 339 - 881
- 0x180a , // 340 - 1309
- 0x180c , // 341 - 1579
- 0x181a , // 342 - 3470
- 0x183b , // 343 - 3301
- 0x1c01 , // 344 - 180
- 0x1c09 , // 345 - 1191
- 0x1c0a , // 346 - 1257
- 0x1c0c , // 347 - 1453
- 0x1c1a , // 348 - 3413
- 0x1c3b , // 349 - 3307
- 0x2001 , // 350 - 135
- 0x2009 , // 351 - 911
- 0x200a , // 352 - 1349
- 0x200c , // 353 - 1634
- 0x201a , // 354 - 385
- 0x203b , // 355 - 3340
- 0x2401 , // 356 - 185
- 0x2409 , // 357 - 684
- 0x240a , // 358 - 1242
- 0x240c , // 359 - 1489
- 0x241a , // 360 - 3500
- 0x243b , // 361 - 3331
- 0x2801 , // 362 - 170
- 0x2809 , // 363 - 751
- 0x280a , // 364 - 1314
- 0x280c , // 365 - 1649
- 0x281a , // 366 - 3443
- 0x2c01 , // 367 - 100
- 0x2c09 , // 368 - 1136
- 0x2c0a , // 369 - 1222
- 0x2c0c , // 370 - 1514
- 0x2c1a , // 371 - 3490
- 0x3001 , // 372 - 115
- 0x3009 , // 373 - 1201
- 0x300a , // 374 - 1262
- 0x300c , // 375 - 1509
- 0x301a , // 376 - 3433
- 0x3401 , // 377 - 110
- 0x3409 , // 378 - 1036
- 0x340a , // 379 - 1237
- 0x340c , // 380 - 1594
- 0x3801 , // 381 - 60
- 0x3809 , // 382 - 876
- 0x380a , // 383 - 1344
- 0x380c , // 384 - 1574
- 0x3c01 , // 385 - 65
- 0x3c09 , // 386 - 871
- 0x3c0a , // 387 - 1329
- 0x3c0c , // 388 - 1559
- 0x4001 , // 389 - 145
- 0x4009 , // 390 - 896
- 0x400a , // 391 - 1227
- 0x4409 , // 392 - 991
- 0x440a , // 393 - 1334
- 0x4809 , // 394 - 1086
- 0x480a , // 395 - 1294
- 0x4c0a , // 396 - 1304
- 0x500a , // 397 - 1324
- 0x540a , // 398 - 1339
- 0x580a , // 399 - 1216
- 0x5c0a , // 400 - 1252
- 0x641a , // 401 - 378
- 0x681a , // 402 - 395
- 0x6c1a , // 403 - 3406
- 0x701a , // 404 - 3463
- 0x703b , // 405 - 3328
- 0x742c , // 406 - 226
- 0x743b , // 407 - 3337
- 0x7804 , // 408 - 4096
- 0x7814 , // 409 - 2731
- 0x781a , // 410 - 376
- 0x782c , // 411 - 243
- 0x783b , // 412 - 3298
- 0x7843 , // 413 - 3878
- 0x7850 , // 414 - 2517
- 0x785d , // 415 - 1955
- 0x785f , // 416 - 3814
- 0x7c04 , // 417 - 4166
- 0x7c14 , // 418 - 2639
- 0x7c1a , // 419 - 3404
- 0x7c28 , // 420 - 3656
- 0x7c2e , // 421 - 602
- 0x7c3b , // 422 - 3313
- 0x7c43 , // 423 - 3895
- 0x7c46 , // 424 - 2832
- 0x7c50 , // 425 - 2529
- 0x7c59 , // 426 - 3160
- 0x7c5c , // 427 - 476
- 0x7c5d , // 428 - 1972
- 0x7c5f , // 429 - 3784
- 0x7c67 , // 430 - 1396
- 0x7c68 , // 431 - 1779
- 0x7c86 , // 432 - 3001
- 0x7c92 , // 433 - 2272
- 0x1007f, // 434 - 4009
- 0x10407, // 435 - 566
- 0x1040e, // 436 - 1867
- 0x10437, // 437 - 2069
- 0x20804, // 438 - 4127
- 0x21004, // 439 - 4236
- 0x21404, // 440 - 4207
- 0x30404, // 441 - 4253
- 0x40404, // 442 - 4265
- 0x40411, // 443 - 1996
- 0x40c04, // 444 - 4178
- 0x41404, // 445 - 4195
- 0x50804, // 446 - 4115
- 0x51004 // 447 - 4224
- };
- // each element in s_lcidToCultureNameIndices is index to s_localeNamesIndices
- private static readonly int[] s_lcidToCultureNameIndices = new int[]
- {
- // Index to s_localeNamesIndices, index to this array - lcid - index to the c_localeNames
- 13 , // 0 - 1 - 52
- 64 , // 1 - 2 - 301
- 88 , // 2 - 3 - 421
- 847 , // 3 - 4 - 4139
- 103 , // 4 - 5 - 502
- 109 , // 5 - 6 - 523
- 114 , // 6 - 7 - 544
- 140 , // 7 - 8 - 664
- 143 , // 8 - 9 - 676
- 251 , // 9 - a - 1214
- 293 , // 10 - b - 1423
- 300 , // 11 - c - 1451
- 377 , // 12 - d - 1825
- 386 , // 13 - e - 1860
- 402 , // 14 - f - 1929
- 404 , // 15 - 10 - 1936
- 413 , // 16 - 11 - 1989
- 452 , // 17 - 12 - 2179
- 564 , // 18 - 13 - 2685
- 578 , // 19 - 14 - 2747
- 605 , // 20 - 15 - 2864
- 613 , // 21 - 16 - 2897
- 637 , // 22 - 17 - 3041
- 641 , // 23 - 18 - 3055
- 646 , // 24 - 19 - 3076
- 381 , // 25 - 1a - 1839
- 687 , // 26 - 1b - 3284
- 709 , // 27 - 1c - 3387
- 734 , // 28 - 1d - 3553
- 760 , // 29 - 1e - 3673
- 774 , // 30 - 1f - 3727
- 795 , // 31 - 20 - 3847
- 396 , // 32 - 21 - 1908
- 793 , // 33 - 22 - 3840
- 58 , // 34 - 23 - 276
- 689 , // 35 - 24 - 3291
- 278 , // 36 - 25 - 1354
- 506 , // 37 - 26 - 2429
- 498 , // 38 - 27 - 2397
- 757 , // 39 - 28 - 3654
- 284 , // 40 - 29 - 1377
- 812 , // 41 - 2a - 3960
- 389 , // 42 - 2b - 1879
- 49 , // 43 - 2c - 224
- 280 , // 44 - 2d - 1361
- 384 , // 45 - 2e - 1851
- 523 , // 46 - 2f - 2501
- 731 , // 47 - 30 - 3541
- 777 , // 48 - 31 - 3739
- 769 , // 49 - 32 - 3708
- 810 , // 50 - 33 - 3953
- 825 , // 51 - 34 - 4020
- 862 , // 52 - 35 - 4277
- 4 , // 53 - 36 - 17
- 425 , // 54 - 37 - 2062
- 297 , // 55 - 38 - 1439
- 379 , // 56 - 39 - 1832
- 543 , // 57 - 3a - 2598
- 670 , // 58 - 3b - 3194
- 352 , // 59 - 3c - 1705
- 831 , // 60 - 3d - 4045
- 539 , // 61 - 3e - 2581
- 440 , // 62 - 3f - 2133
- 476 , // 63 - 40 - 2306
- 738 , // 64 - 41 - 3570
- 767 , // 65 - 42 - 3701
- 798 , // 66 - 43 - 3859
- 779 , // 67 - 44 - 3746
- 71 , // 68 - 45 - 336
- 599 , // 69 - 46 - 2830
- 364 , // 70 - 47 - 1754
- 594 , // 71 - 48 - 2811
- 747 , // 72 - 49 - 3610
- 752 , // 73 - 4a - 3632
- 450 , // 74 - 4b - 2172
- 525 , // 75 - 4c - 2508
- 43 , // 76 - 4d - 199
- 537 , // 77 - 4e - 2574
- 657 , // 78 - 4f - 3124
- 527 , // 79 - 50 - 2515
- 74 , // 80 - 51 - 348
- 107 , // 81 - 52 - 516
- 448 , // 82 - 53 - 2165
- 493 , // 83 - 54 - 2375
- 547 , // 84 - 55 - 2614
- 356 , // 85 - 56 - 1719
- 455 , // 86 - 57 - 2191
- 533 , // 87 - 58 - 2556
- 665 , // 88 - 59 - 3158
- 745 , // 89 - 5a - 3601
- 685 , // 90 - 5b - 3277
- 98 , // 91 - 5c - 473
- 408 , // 92 - 5d - 1953
- 11 , // 93 - 5e - 45
- 783 , // 94 - 5f - 3762
- 459 , // 95 - 60 - 2207
- 561 , // 96 - 61 - 2673
- 350 , // 97 - 62 - 1698
- 611 , // 98 - 63 - 2890
- 295 , // 99 - 64 - 1430
- 129 , // 100 - 65 - 620
- 66 , // 101 - 66 - 308
- 286 , // 102 - 67 - 1384
- 370 , // 103 - 68 - 1777
- 394 , // 104 - 69 - 1899
- 833 , // 105 - 6a - 4053
- 633 , // 106 - 6b - 3020
- 583 , // 107 - 6c - 2765
- 54 , // 108 - 6d - 260
- 482 , // 109 - 6e - 2330
- 444 , // 110 - 6f - 2149
- 398 , // 111 - 70 - 1915
- 457 , // 112 - 71 - 2200
- 591 , // 113 - 72 - 2799
- 762 , // 114 - 73 - 3680
- 358 , // 115 - 74 - 1726
- 375 , // 116 - 75 - 1816
- 478 , // 117 - 76 - 2313
- 704 , // 118 - 77 - 3365
- 400 , // 119 - 78 - 1922
- 603 , // 120 - 79 - 2854
- 41 , // 121 - 7a - 190
- 535 , // 122 - 7c - 2565
- 77 , // 123 - 7e - 360
- 791 , // 124 - 80 - 3833
- 521 , // 125 - 81 - 2494
- 589 , // 126 - 82 - 2792
- 101 , // 127 - 83 - 495
- 360 , // 128 - 84 - 1733
- 659 , // 129 - 85 - 3131
- 630 , // 130 - 86 - 2998
- 653 , // 131 - 87 - 3108
- 822 , // 132 - 88 - 4002
- 609 , // 133 - 8c - 2881
- 354 , // 134 - 91 - 1712
- 470 , // 135 - 92 - 2270
- 33 , // 136 - 401 - 150
- 65 , // 137 - 402 - 303
- 90 , // 138 - 403 - 428
- 859 , // 139 - 404 - 4248
- 104 , // 140 - 405 - 504
- 110 , // 141 - 406 - 525
- 118 , // 142 - 407 - 561
- 142 , // 143 - 408 - 671
- 240 , // 144 - 409 - 1161
- 263 , // 145 - 40a - 1272
- 294 , // 146 - 40b - 1425
- 316 , // 147 - 40c - 1529
- 378 , // 148 - 40d - 1827
- 387 , // 149 - 40e - 1862
- 403 , // 150 - 40f - 1931
- 406 , // 151 - 410 - 1943
- 414 , // 152 - 411 - 1991
- 454 , // 153 - 412 - 2186
- 569 , // 154 - 413 - 2707
- 554 , // 155 - 414 - 2641
- 606 , // 156 - 415 - 2866
- 615 , // 157 - 416 - 2904
- 638 , // 158 - 417 - 3043
- 643 , // 159 - 418 - 3062
- 651 , // 160 - 419 - 3098
- 383 , // 161 - 41a - 1846
- 688 , // 162 - 41b - 3286
- 710 , // 163 - 41c - 3389
- 737 , // 164 - 41d - 3565
- 761 , // 165 - 41e - 3675
- 776 , // 166 - 41f - 3734
- 797 , // 167 - 420 - 3854
- 397 , // 168 - 421 - 1910
- 794 , // 169 - 422 - 3842
- 59 , // 170 - 423 - 278
- 690 , // 171 - 424 - 3293
- 279 , // 172 - 425 - 1356
- 507 , // 173 - 426 - 2431
- 499 , // 174 - 427 - 2399
- 759 , // 175 - 428 - 3663
- 285 , // 176 - 429 - 1379
- 813 , // 177 - 42a - 3962
- 390 , // 178 - 42b - 1881
- 53 , // 179 - 42c - 250
- 281 , // 180 - 42d - 1363
- 385 , // 181 - 42e - 1854
- 524 , // 182 - 42f - 2503
- 733 , // 183 - 430 - 3548
- 778 , // 184 - 431 - 3741
- 771 , // 185 - 432 - 3715
- 811 , // 186 - 433 - 3955
- 826 , // 187 - 434 - 4022
- 863 , // 188 - 435 - 4279
- 6 , // 189 - 436 - 24
- 426 , // 190 - 437 - 2064
- 299 , // 191 - 438 - 1446
- 380 , // 192 - 439 - 1834
- 544 , // 193 - 43a - 2600
- 672 , // 194 - 43b - 3201
- 832 , // 195 - 43d - 4047
- 541 , // 196 - 43e - 2588
- 441 , // 197 - 43f - 2135
- 477 , // 198 - 440 - 2308
- 740 , // 199 - 441 - 3577
- 768 , // 200 - 442 - 3703
- 804 , // 201 - 443 - 3902
- 780 , // 202 - 444 - 3748
- 73 , // 203 - 445 - 343
- 602 , // 204 - 446 - 2849
- 365 , // 205 - 447 - 1756
- 595 , // 206 - 448 - 2813
- 748 , // 207 - 449 - 3612
- 753 , // 208 - 44a - 3634
- 451 , // 209 - 44b - 2174
- 526 , // 210 - 44c - 2510
- 44 , // 211 - 44d - 201
- 538 , // 212 - 44e - 2576
- 658 , // 213 - 44f - 3126
- 529 , // 214 - 450 - 2524
- 75 , // 215 - 451 - 350
- 108 , // 216 - 452 - 518
- 449 , // 217 - 453 - 2167
- 494 , // 218 - 454 - 2377
- 548 , // 219 - 455 - 2616
- 357 , // 220 - 456 - 1721
- 456 , // 221 - 457 - 2194
- 534 , // 222 - 458 - 2559
- 669 , // 223 - 459 - 3184
- 746 , // 224 - 45a - 3604
- 686 , // 225 - 45b - 3279
- 100 , // 226 - 45c - 484
- 410 , // 227 - 45d - 1962
- 12 , // 228 - 45e - 47
- 785 , // 229 - 45f - 3773
- 460 , // 230 - 460 - 2209
- 563 , // 231 - 461 - 2680
- 351 , // 232 - 462 - 1700
- 612 , // 233 - 463 - 2892
- 296 , // 234 - 464 - 1433
- 130 , // 235 - 465 - 622
- 67 , // 236 - 466 - 311
- 292 , // 237 - 467 - 1418
- 374 , // 238 - 468 - 1806
- 395 , // 239 - 469 - 1902
- 835 , // 240 - 46a - 4060
- 634 , // 241 - 46b - 3023
- 584 , // 242 - 46c - 2768
- 55 , // 243 - 46d - 262
- 483 , // 244 - 46e - 2332
- 445 , // 245 - 46f - 2151
- 399 , // 246 - 470 - 1917
- 458 , // 247 - 471 - 2202
- 592 , // 248 - 472 - 2801
- 764 , // 249 - 473 - 3687
- 359 , // 250 - 474 - 1728
- 376 , // 251 - 475 - 1819
- 479 , // 252 - 476 - 2315
- 708 , // 253 - 477 - 3382
- 401 , // 254 - 478 - 1924
- 604 , // 255 - 479 - 2857
- 42 , // 256 - 47a - 193
- 536 , // 257 - 47c - 2568
- 78 , // 258 - 47e - 362
- 792 , // 259 - 480 - 3835
- 522 , // 260 - 481 - 2496
- 590 , // 261 - 482 - 2794
- 102 , // 262 - 483 - 497
- 362 , // 263 - 484 - 1742
- 660 , // 264 - 485 - 3134
- 632 , // 265 - 486 - 3009
- 654 , // 266 - 487 - 3110
- 823 , // 267 - 488 - 4004
- 610 , // 268 - 48c - 2884
- 355 , // 269 - 491 - 1714
- 472 , // 270 - 492 - 2279
- 627 , // 271 - 501 - 2972
- 628 , // 272 - 5fe - 2980
- 22 , // 273 - 801 - 95
- 91 , // 274 - 803 - 433
- 844 , // 275 - 804 - 4110
- 117 , // 276 - 807 - 556
- 174 , // 277 - 809 - 831
- 267 , // 278 - 80a - 1299
- 302 , // 279 - 80c - 1459
- 405 , // 280 - 810 - 1938
- 566 , // 281 - 813 - 2692
- 575 , // 282 - 814 - 2733
- 623 , // 283 - 816 - 2944
- 642 , // 284 - 818 - 3057
- 650 , // 285 - 819 - 3093
- 722 , // 286 - 81a - 3480
- 736 , // 287 - 81d - 3560
- 796 , // 288 - 820 - 3849
- 51 , // 289 - 82c - 233
- 126 , // 290 - 82e - 605
- 770 , // 291 - 832 - 3710
- 673 , // 292 - 83b - 3206
- 353 , // 293 - 83c - 1707
- 540 , // 294 - 83e - 2583
- 802 , // 295 - 843 - 3885
- 72 , // 296 - 845 - 338
- 601 , // 297 - 846 - 2839
- 749 , // 298 - 849 - 3617
- 531 , // 299 - 850 - 2536
- 667 , // 300 - 859 - 3167
- 412 , // 301 - 85d - 1979
- 787 , // 302 - 85f - 3792
- 463 , // 303 - 860 - 2233
- 562 , // 304 - 861 - 2675
- 290 , // 305 - 867 - 1403
- 635 , // 306 - 86b - 3029
- 763 , // 307 - 873 - 3682
- 626 , // 308 - 901 - 2959
- 629 , // 309 - 9ff - 2989
- 19 , // 310 - c01 - 80
- 851 , // 311 - c04 - 4173
- 115 , // 312 - c07 - 546
- 151 , // 313 - c09 - 716
- 262 , // 314 - c0a - 1267
- 307 , // 315 - c0c - 1484
- 716 , // 316 - c1a - 3423
- 671 , // 317 - c3b - 3196
- 532 , // 318 - c50 - 2546
- 134 , // 319 - c51 - 638
- 636 , // 320 - c6b - 3035
- 27 , // 321 - 1001 - 120
- 856 , // 322 - 1004 - 4219
- 122 , // 323 - 1007 - 588
- 159 , // 324 - 1009 - 756
- 265 , // 325 - 100a - 1289
- 311 , // 326 - 100c - 1504
- 382 , // 327 - 101a - 1841
- 695 , // 328 - 103b - 3316
- 790 , // 329 - 105f - 3822
- 18 , // 330 - 1401 - 75
- 853 , // 331 - 1404 - 4190
- 121 , // 332 - 1407 - 583
- 213 , // 333 - 1409 - 1026
- 258 , // 334 - 140a - 1247
- 324 , // 335 - 140c - 1569
- 85 , // 336 - 141a - 402
- 696 , // 337 - 143b - 3322
- 28 , // 338 - 1801 - 125
- 184 , // 339 - 1809 - 881
- 269 , // 340 - 180a - 1309
- 326 , // 341 - 180c - 1579
- 721 , // 342 - 181a - 3470
- 692 , // 343 - 183b - 3301
- 39 , // 344 - 1c01 - 180
- 246 , // 345 - 1c09 - 1191
- 260 , // 346 - 1c0a - 1257
- 301 , // 347 - 1c0c - 1453
- 715 , // 348 - 1c1a - 3413
- 693 , // 349 - 1c3b - 3307
- 30 , // 350 - 2001 - 135
- 190 , // 351 - 2009 - 911
- 277 , // 352 - 200a - 1349
- 337 , // 353 - 200c - 1634
- 83 , // 354 - 201a - 385
- 700 , // 355 - 203b - 3340
- 40 , // 356 - 2401 - 185
- 145 , // 357 - 2409 - 684
- 257 , // 358 - 240a - 1242
- 308 , // 359 - 240c - 1489
- 724 , // 360 - 241a - 3500
- 698 , // 361 - 243b - 3331
- 37 , // 362 - 2801 - 170
- 158 , // 363 - 2809 - 751
- 270 , // 364 - 280a - 1314
- 340 , // 365 - 280c - 1649
- 718 , // 366 - 281a - 3443
- 23 , // 367 - 2c01 - 100
- 235 , // 368 - 2c09 - 1136
- 253 , // 369 - 2c0a - 1222
- 313 , // 370 - 2c0c - 1514
- 723 , // 371 - 2c1a - 3490
- 26 , // 372 - 3001 - 115
- 248 , // 373 - 3009 - 1201
- 261 , // 374 - 300a - 1262
- 312 , // 375 - 300c - 1509
- 717 , // 376 - 301a - 3433
- 25 , // 377 - 3401 - 110
- 215 , // 378 - 3409 - 1036
- 256 , // 379 - 340a - 1237
- 329 , // 380 - 340c - 1594
- 15 , // 381 - 3801 - 60
- 183 , // 382 - 3809 - 876
- 276 , // 383 - 380a - 1344
- 325 , // 384 - 380c - 1574
- 16 , // 385 - 3c01 - 65
- 182 , // 386 - 3c09 - 871
- 273 , // 387 - 3c0a - 1329
- 322 , // 388 - 3c0c - 1559
- 32 , // 389 - 4001 - 145
- 187 , // 390 - 4009 - 896
- 254 , // 391 - 400a - 1227
- 206 , // 392 - 4409 - 991
- 274 , // 393 - 440a - 1334
- 225 , // 394 - 4809 - 1086
- 266 , // 395 - 480a - 1294
- 268 , // 396 - 4c0a - 1304
- 272 , // 397 - 500a - 1324
- 275 , // 398 - 540a - 1339
- 252 , // 399 - 580a - 1216
- 259 , // 400 - 5c0a - 1252
- 82 , // 401 - 641a - 378
- 84 , // 402 - 681a - 395
- 714 , // 403 - 6c1a - 3406
- 720 , // 404 - 701a - 3463
- 697 , // 405 - 703b - 3328
- 50 , // 406 - 742c - 226
- 699 , // 407 - 743b - 3337
- 841 , // 408 - 7804 - 4096
- 574 , // 409 - 7814 - 2731
- 81 , // 410 - 781a - 376
- 52 , // 411 - 782c - 243
- 691 , // 412 - 783b - 3298
- 801 , // 413 - 7843 - 3878
- 528 , // 414 - 7850 - 2517
- 409 , // 415 - 785d - 1955
- 789 , // 416 - 785f - 3814
- 850 , // 417 - 7c04 - 4166
- 553 , // 418 - 7c14 - 2639
- 713 , // 419 - 7c1a - 3404
- 758 , // 420 - 7c28 - 3656
- 125 , // 421 - 7c2e - 602
- 694 , // 422 - 7c3b - 3313
- 803 , // 423 - 7c43 - 3895
- 600 , // 424 - 7c46 - 2832
- 530 , // 425 - 7c50 - 2529
- 666 , // 426 - 7c59 - 3160
- 99 , // 427 - 7c5c - 476
- 411 , // 428 - 7c5d - 1972
- 786 , // 429 - 7c5f - 3784
- 289 , // 430 - 7c67 - 1396
- 371 , // 431 - 7c68 - 1779
- 631 , // 432 - 7c86 - 3001
- 471 , // 433 - 7c92 - 2272
- 824 , // 434 - 1007f - 4009
- 119 , // 435 - 10407 - 566
- 388 , // 436 - 1040e - 1867
- 427 , // 437 - 10437 - 2069
- 846 , // 438 - 20804 - 4127
- 858 , // 439 - 21004 - 4236
- 855 , // 440 - 21404 - 4207
- 860 , // 441 - 30404 - 4253
- 861 , // 442 - 40404 - 4265
- 415 , // 443 - 40411 - 1996
- 852 , // 444 - 40c04 - 4178
- 854 , // 445 - 41404 - 4195
- 845 , // 446 - 50804 - 4115
- 857 // 447 - 51004 - 4224
- };
-
- internal static string? LCIDToLocaleName(int culture)
- {
- int left = 0;
- int right = s_lcids.Length - 1;
- int index;
-
- Debug.Assert(s_lcids.Length == s_lcidToCultureNameIndices.Length);
-
- while (left <= right)
- {
- index = (right + left) / 2;
-
- if (culture == s_lcids[index])
- {
- int indexToLocaleNamesIndices = s_lcidToCultureNameIndices[index];
- Debug.Assert(indexToLocaleNamesIndices < s_localeNamesIndices.Length - 1);
-
- return c_localeNames.Substring(s_localeNamesIndices[indexToLocaleNamesIndices],
- s_localeNamesIndices[indexToLocaleNamesIndices + 1] -
- s_localeNamesIndices[indexToLocaleNamesIndices]);
- }
- else if (culture < s_lcids[index])
- {
- right = index - 1;
- }
- else
- {
- left = index + 1;
- }
- }
-
- return null;
- }
-
- internal static int GetLocaleDataNumericPart(string cultureName, LocaleDataParts part)
- {
- int index = SearchCultureName(cultureName);
- if (index < 0)
- {
- return -1;
- }
-
- Debug.Assert((s_localeNamesIndices.Length-1 == (s_nameIndexToNumericData.Length/NUMERIC_LOCALE_DATA_COUNT_PER_ROW)) &&
- index < s_localeNamesIndices.Length);
-
- return s_nameIndexToNumericData[index * NUMERIC_LOCALE_DATA_COUNT_PER_ROW + (int) part];
- }
-
- internal static string? GetThreeLetterWindowsLanguageName(string cultureName)
- {
- int index = SearchCultureName(cultureName);
- if (index < 0)
- {
- return null;
- }
-
- Debug.Assert(s_localeNamesIndices.Length-1 == (c_threeLetterWindowsLanguageName.Length / 3));
- return c_threeLetterWindowsLanguageName.Substring(index * 3, 3);
- }
-
- internal static string GetLocaleDataMappedCulture(string cultureName, LocaleDataParts part)
- {
- int indexToIndicesTable = GetLocaleDataNumericPart(cultureName, part);
- if (indexToIndicesTable < 0)
- {
- return ""; // fallback to invariant
- }
-
- Debug.Assert(indexToIndicesTable < s_localeNamesIndices.Length-1);
-
- return c_localeNames.Substring(s_localeNamesIndices[indexToIndicesTable],
- s_localeNamesIndices[indexToIndicesTable+1] - s_localeNamesIndices[indexToIndicesTable]);
- }
-
- internal static string GetSpecificCultureName(string cultureName)
- {
- return GetLocaleDataMappedCulture(cultureName, LocaleDataParts.SpecificLocaleIndex);
- }
-
- internal static string GetConsoleUICulture(string cultureName)
- {
- return GetLocaleDataMappedCulture(cultureName, LocaleDataParts.ConsoleLocaleIndex);
- }
-
- // SearchCultureName will binary search c_localeNames using s_localeNamesIndices.
- // return index in s_localeNamesIndices, or -1 if it fail finding any match
- private static int SearchCultureName(string name)
- {
- int left = 0;
- int right = s_localeNamesIndices.Length - 2;
- int index;
- int result;
-
- Debug.Assert(s_localeNamesIndices[s_localeNamesIndices.Length - 1] == c_localeNames.Length);
-
- name = CultureData.AnsiToLower(name);
-
- // Binary search the array until we have only a couple of elements left and then
- // just walk those elements.
- while ((right - left) > 3)
- {
- index = ((right - left) / 2) + left;
-
- Debug.Assert(index < s_localeNamesIndices.Length - 1);
- result = CompareOrdinal(name, c_localeNames, s_localeNamesIndices[index], s_localeNamesIndices[index + 1] - s_localeNamesIndices[index]);
- if (result == 0)
- {
- return index;
- }
- else if (result < 0)
- {
- right = index;
- }
- else
- {
- left = index;
- }
- }
-
- // Walk the remaining elements (it'll be 3 or fewer).
- for (; left <= right; left++)
- {
- Debug.Assert(left < s_localeNamesIndices.Length - 1);
- if (CompareOrdinal(name, c_localeNames, s_localeNamesIndices[left], s_localeNamesIndices[left + 1] - s_localeNamesIndices[left]) == 0)
- {
- return (left);
- }
- }
-
- // couldn't find culture name
- return -1;
- }
-
- // optimized to avoid parameters checking
- private static int CompareOrdinal(string s1, string s2, int index, int length)
- {
- int count = s1.Length;
- if (count > length)
- count = length;
-
- int i = 0;
- while (i < count && s1[i] == s2[index + i])
- i++;
-
- if (i < count)
- return (int)(s1[i] - s2[index + i]);
-
- return s1.Length - length;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Unix.cs
deleted file mode 100644
index 37c9024c33d..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Unix.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Text;
-
-namespace System.Globalization
-{
- internal static partial class Normalization
- {
- internal static bool IsNormalized(string strInput, NormalizationForm normalizationForm)
- {
- if (GlobalizationMode.Invariant)
- {
- // In Invariant mode we assume all characters are normalized.
- // This is because we don't support any linguistic operation on the strings
- return true;
- }
-
- ValidateArguments(strInput, normalizationForm);
-
- int ret = Interop.Globalization.IsNormalized(normalizationForm, strInput, strInput.Length);
-
- if (ret == -1)
- {
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
- }
-
- return ret == 1;
- }
-
- internal static string Normalize(string strInput, NormalizationForm normalizationForm)
- {
- if (GlobalizationMode.Invariant)
- {
- // In Invariant mode we assume all characters are normalized.
- // This is because we don't support any linguistic operation on the strings
- return strInput;
- }
-
- ValidateArguments(strInput, normalizationForm);
-
- char[] buf = new char[strInput.Length];
-
- for (int attempts = 2; attempts > 0; attempts--)
- {
- int realLen = Interop.Globalization.NormalizeString(normalizationForm, strInput, strInput.Length, buf, buf.Length);
-
- if (realLen == -1)
- {
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
- }
-
- if (realLen <= buf.Length)
- {
- return new string(buf, 0, realLen);
- }
-
- buf = new char[realLen];
- }
-
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
- }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
-
- private static void ValidateArguments(string strInput, NormalizationForm normalizationForm)
- {
- Debug.Assert(strInput != null);
-
- if (normalizationForm != NormalizationForm.FormC && normalizationForm != NormalizationForm.FormD &&
- normalizationForm != NormalizationForm.FormKC && normalizationForm != NormalizationForm.FormKD)
- {
- throw new ArgumentException(SR.Argument_InvalidNormalizationForm, nameof(normalizationForm));
- }
-
- if (HasInvalidUnicodeSequence(strInput))
- {
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
- }
- }
-
- /// <summary>
- /// ICU does not signal an error during normalization if the input string has invalid unicode,
- /// unlike Windows (which uses the ERROR_NO_UNICODE_TRANSLATION error value to signal an error).
- ///
- /// We walk the string ourselves looking for these bad sequences so we can continue to throw
- /// ArgumentException in these cases.
- /// </summary>
- private static bool HasInvalidUnicodeSequence(string s)
- {
- for (int i = 0; i < s.Length; i++)
- {
- char c = s[i];
-
- if (c < '\ud800')
- {
- continue;
- }
-
- if (c == '\uFFFE')
- {
- return true;
- }
-
- // If we see low surrogate before a high one, the string is invalid.
- if (char.IsLowSurrogate(c))
- {
- return true;
- }
-
- if (char.IsHighSurrogate(c))
- {
- if (i + 1 >= s.Length || !char.IsLowSurrogate(s[i + 1]))
- {
- // A high surrogate at the end of the string or a high surrogate
- // not followed by a low surrogate
- return true;
- }
- else
- {
- i++; // consume the low surrogate.
- continue;
- }
- }
- }
-
- return false;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Windows.cs
deleted file mode 100644
index e96789d1695..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/Normalization.Windows.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace System.Globalization
-{
- internal static partial class Normalization
- {
- internal static bool IsNormalized(string strInput, NormalizationForm normalizationForm)
- {
- if (GlobalizationMode.Invariant)
- {
- // In Invariant mode we assume all characters are normalized.
- // This is because we don't support any linguistic operation on the strings
- return true;
- }
-
- Debug.Assert(strInput != null);
-
- // The only way to know if IsNormalizedString failed is through checking the Win32 last error
- // IsNormalizedString pinvoke has SetLastError attribute property which will set the last error
- // to 0 (ERROR_SUCCESS) before executing the calls.
- bool result = Interop.Normaliz.IsNormalizedString((int)normalizationForm, strInput, strInput.Length);
-
- int lastError = Marshal.GetLastWin32Error();
- switch (lastError)
- {
- case Interop.Errors.ERROR_SUCCESS:
- break;
-
- case Interop.Errors.ERROR_INVALID_PARAMETER:
- case Interop.Errors.ERROR_NO_UNICODE_TRANSLATION:
- if (normalizationForm != NormalizationForm.FormC &&
- normalizationForm != NormalizationForm.FormD &&
- normalizationForm != NormalizationForm.FormKC &&
- normalizationForm != NormalizationForm.FormKD)
- {
- throw new ArgumentException(SR.Argument_InvalidNormalizationForm, nameof(normalizationForm));
- }
-
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
-
- case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY:
- throw new OutOfMemoryException();
-
- default:
- throw new InvalidOperationException(SR.Format(SR.UnknownError_Num, lastError));
- }
-
- return result;
- }
-
- internal static string Normalize(string strInput, NormalizationForm normalizationForm)
- {
- if (GlobalizationMode.Invariant)
- {
- // In Invariant mode we assume all characters are normalized.
- // This is because we don't support any linguistic operation on the strings
- return strInput;
- }
-
- Debug.Assert(strInput != null);
-
- // we depend on Win32 last error when calling NormalizeString
- // NormalizeString pinvoke has SetLastError attribute property which will set the last error
- // to 0 (ERROR_SUCCESS) before executing the calls.
-
- // Guess our buffer size first
- int iLength = Interop.Normaliz.NormalizeString((int)normalizationForm, strInput, strInput.Length, null, 0);
-
- int lastError = Marshal.GetLastWin32Error();
- // Could have an error (actually it'd be quite hard to have an error here)
- if ((lastError != Interop.Errors.ERROR_SUCCESS) || iLength < 0)
- {
- if (lastError == Interop.Errors.ERROR_INVALID_PARAMETER)
- {
- if (normalizationForm != NormalizationForm.FormC &&
- normalizationForm != NormalizationForm.FormD &&
- normalizationForm != NormalizationForm.FormKC &&
- normalizationForm != NormalizationForm.FormKD)
- {
- throw new ArgumentException(SR.Argument_InvalidNormalizationForm, nameof(normalizationForm));
- }
-
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
- }
-
- // We shouldn't really be able to get here..., guessing length is
- // a trivial math function...
- // Can't really be Out of Memory, but just in case:
- if (lastError == Interop.Errors.ERROR_NOT_ENOUGH_MEMORY)
- throw new OutOfMemoryException();
-
- // Who knows what happened? Not us!
- throw new InvalidOperationException(SR.Format(SR.UnknownError_Num, lastError));
- }
-
- // Don't break for empty strings (only possible for D & KD and not really possible at that)
- if (iLength == 0) return string.Empty;
-
- // Someplace to stick our buffer
- char[] cBuffer;
-
- while (true)
- {
- // (re)allocation buffer and normalize string
- cBuffer = new char[iLength];
-
- // NormalizeString pinvoke has SetLastError attribute property which will set the last error
- // to 0 (ERROR_SUCCESS) before executing the calls.
- iLength = Interop.Normaliz.NormalizeString((int)normalizationForm, strInput, strInput.Length, cBuffer, cBuffer.Length);
- lastError = Marshal.GetLastWin32Error();
-
- if (lastError == Interop.Errors.ERROR_SUCCESS)
- break;
-
- // Could have an error (actually it'd be quite hard to have an error here)
- switch (lastError)
- {
- // Do appropriate stuff for the individual errors:
- case Interop.Errors.ERROR_INSUFFICIENT_BUFFER:
- iLength = Math.Abs(iLength);
- Debug.Assert(iLength > cBuffer.Length, "Buffer overflow should have iLength > cBuffer.Length");
- continue;
-
- case Interop.Errors.ERROR_INVALID_PARAMETER:
- case Interop.Errors.ERROR_NO_UNICODE_TRANSLATION:
- // Illegal code point or order found. Ie: FFFE or D800 D800, etc.
- throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput));
-
- case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY:
- throw new OutOfMemoryException();
-
- default:
- // We shouldn't get here...
- throw new InvalidOperationException(SR.Format(SR.UnknownError_Num, lastError));
- }
- }
-
- // Copy our buffer into our new string, which will be the appropriate size
- return new string(cBuffer, 0, iLength);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
deleted file mode 100644
index d5fa16edcdc..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
+++ /dev/null
@@ -1,750 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Property Default Description
- /// PositiveSign '+' Character used to indicate positive values.
- /// NegativeSign '-' Character used to indicate negative values.
- /// NumberDecimalSeparator '.' The character used as the decimal separator.
- /// NumberGroupSeparator ',' The character used to separate groups of
- /// digits to the left of the decimal point.
- /// NumberDecimalDigits 2 The default number of decimal places.
- /// NumberGroupSizes 3 The number of digits in each group to the
- /// left of the decimal point.
- /// NaNSymbol "NaN" The string used to represent NaN values.
- /// PositiveInfinitySymbol"Infinity" The string used to represent positive
- /// infinities.
- /// NegativeInfinitySymbol"-Infinity" The string used to represent negative
- /// infinities.
- ///
- /// Property Default Description
- /// CurrencyDecimalSeparator '.' The character used as the decimal
- /// separator.
- /// CurrencyGroupSeparator ',' The character used to separate groups
- /// of digits to the left of the decimal
- /// point.
- /// CurrencyDecimalDigits 2 The default number of decimal places.
- /// CurrencyGroupSizes 3 The number of digits in each group to
- /// the left of the decimal point.
- /// CurrencyPositivePattern 0 The format of positive values.
- /// CurrencyNegativePattern 0 The format of negative values.
- /// CurrencySymbol "$" String used as local monetary symbol.
- /// </remarks>
- public sealed class NumberFormatInfo : IFormatProvider, ICloneable
- {
- private static volatile NumberFormatInfo? s_invariantInfo;
-
- internal int[] _numberGroupSizes = new int[] { 3 };
- internal int[] _currencyGroupSizes = new int[] { 3 };
- internal int[] _percentGroupSizes = new int[] { 3 };
- internal string _positiveSign = "+";
- internal string _negativeSign = "-";
- internal string _numberDecimalSeparator = ".";
- internal string _numberGroupSeparator = ",";
- internal string _currencyGroupSeparator = ",";
- internal string _currencyDecimalSeparator = ".";
- internal string _currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
- internal string _nanSymbol = "NaN";
- internal string _positiveInfinitySymbol = "Infinity";
- internal string _negativeInfinitySymbol = "-Infinity";
- internal string _percentDecimalSeparator = ".";
- internal string _percentGroupSeparator = ",";
- internal string _percentSymbol = "%";
- internal string _perMilleSymbol = "\u2030";
-
- internal string[] _nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
- internal int _numberDecimalDigits = 2;
- internal int _currencyDecimalDigits = 2;
- internal int _currencyPositivePattern = 0;
- internal int _currencyNegativePattern = 0;
- internal int _numberNegativePattern = 1;
- internal int _percentPositivePattern = 0;
- internal int _percentNegativePattern = 0;
- internal int _percentDecimalDigits = 2;
-
- internal int _digitSubstitution = (int)DigitShapes.None;
-
- internal bool _isReadOnly = false;
-
- private bool _hasInvariantNumberSigns = true;
-
- public NumberFormatInfo()
- {
- }
-
- private static void VerifyDecimalSeparator(string decSep, string propertyName)
- {
- if (decSep == null)
- {
- throw new ArgumentNullException(propertyName);
- }
-
- if (decSep.Length == 0)
- {
- throw new ArgumentException(SR.Argument_EmptyDecString, propertyName);
- }
- }
-
- private static void VerifyGroupSeparator(string groupSep, string propertyName)
- {
- if (groupSep == null)
- {
- throw new ArgumentNullException(propertyName);
- }
- }
-
- private static void VerifyNativeDigits(string[] nativeDig, string propertyName)
- {
- if (nativeDig == null)
- {
- throw new ArgumentNullException(propertyName, SR.ArgumentNull_Array);
- }
-
- if (nativeDig.Length != 10)
- {
- throw new ArgumentException(SR.Argument_InvalidNativeDigitCount, propertyName);
- }
-
- for (int i = 0; i < nativeDig.Length; i++)
- {
- if (nativeDig[i] == null)
- {
- throw new ArgumentNullException(propertyName, SR.ArgumentNull_ArrayValue);
- }
-
- if (nativeDig[i].Length != 1)
- {
- if (nativeDig[i].Length != 2)
- {
- // Not 1 or 2 UTF-16 code points
- throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName);
- }
- else if (!char.IsSurrogatePair(nativeDig[i][0], nativeDig[i][1]))
- {
- // 2 UTF-6 code points, but not a surrogate pair
- throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName);
- }
- }
-
- if (CharUnicodeInfo.GetDecimalDigitValue(nativeDig[i], 0) != i &&
- CharUnicodeInfo.GetUnicodeCategory(nativeDig[i], 0) != UnicodeCategory.PrivateUse)
- {
- // Not the appropriate digit according to the Unicode data properties
- // (Digit 0 must be a 0, etc.).
- throw new ArgumentException(SR.Argument_InvalidNativeDigitValue, propertyName);
- }
- }
- }
-
- private static void VerifyDigitSubstitution(DigitShapes digitSub, string propertyName)
- {
- switch (digitSub)
- {
- case DigitShapes.Context:
- case DigitShapes.None:
- case DigitShapes.NativeNational:
- // Success.
- break;
-
- default:
- throw new ArgumentException(SR.Argument_InvalidDigitSubstitution, propertyName);
- }
- }
-
- internal bool HasInvariantNumberSigns => _hasInvariantNumberSigns;
-
- private void UpdateHasInvariantNumberSigns()
- {
- _hasInvariantNumberSigns = _positiveSign == "+" && _negativeSign == "-";
- }
-
- internal NumberFormatInfo(CultureData? cultureData)
- {
- if (cultureData != null)
- {
- // We directly use fields here since these data is coming from data table or Win32, so we
- // don't need to verify their values (except for invalid parsing situations).
- cultureData.GetNFIValues(this);
-
- UpdateHasInvariantNumberSigns();
- }
- }
-
- private void VerifyWritable()
- {
- if (_isReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- }
-
- /// <summary>
- /// Returns a default NumberFormatInfo that will be universally
- /// supported and constant irrespective of the current culture.
- /// Used by FromString methods.
- /// </summary>
- public static NumberFormatInfo InvariantInfo => s_invariantInfo ??=
- // Lazy create the invariant info. This cannot be done in a .cctor because exceptions can
- // be thrown out of a .cctor stack that will need this.
- new NumberFormatInfo { _isReadOnly = true };
-
- public static NumberFormatInfo GetInstance(IFormatProvider? formatProvider)
- {
- return formatProvider == null ?
- CurrentInfo : // Fast path for a null provider
- GetProviderNonNull(formatProvider);
-
- static NumberFormatInfo GetProviderNonNull(IFormatProvider provider)
- {
- // Fast path for a regular CultureInfo
- if (provider is CultureInfo cultureProvider && !cultureProvider._isInherited)
- {
- return cultureProvider._numInfo ?? cultureProvider.NumberFormat;
- }
-
- return
- provider as NumberFormatInfo ?? // Fast path for an NFI
- provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo ??
- CurrentInfo;
- }
- }
-
- public object Clone()
- {
- NumberFormatInfo n = (NumberFormatInfo)MemberwiseClone();
- n._isReadOnly = false;
- return n;
- }
-
- public int CurrencyDecimalDigits
- {
- get => _currencyDecimalDigits;
- set
- {
- if (value < 0 || value > 99)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 99));
- }
-
- VerifyWritable();
- _currencyDecimalDigits = value;
- }
- }
-
- public string CurrencyDecimalSeparator
- {
- get => _currencyDecimalSeparator;
- set
- {
- VerifyWritable();
- VerifyDecimalSeparator(value, nameof(value));
- _currencyDecimalSeparator = value;
- }
- }
-
- public bool IsReadOnly => _isReadOnly;
-
- /// <summary>
- /// Check the values of the groupSize array.
- /// Every element in the groupSize array should be between 1 and 9
- /// except the last element could be zero.
- /// </summary>
- internal static void CheckGroupSize(string propName, int[] groupSize)
- {
- for (int i = 0; i < groupSize.Length; i++)
- {
- if (groupSize[i] < 1)
- {
- if (i == groupSize.Length - 1 && groupSize[i] == 0)
- {
- return;
- }
-
- throw new ArgumentException(SR.Argument_InvalidGroupSize, propName);
- }
- else if (groupSize[i] > 9)
- {
- throw new ArgumentException(SR.Argument_InvalidGroupSize, propName);
- }
- }
- }
-
- public int[] CurrencyGroupSizes
- {
- get => (int[])_currencyGroupSizes.Clone();
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
-
- int[] inputSizes = (int[])value.Clone();
- CheckGroupSize(nameof(value), inputSizes);
- _currencyGroupSizes = inputSizes;
- }
- }
-
- public int[] NumberGroupSizes
- {
- get => (int[])_numberGroupSizes.Clone();
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
-
- int[] inputSizes = (int[])value.Clone();
- CheckGroupSize(nameof(value), inputSizes);
- _numberGroupSizes = inputSizes;
- }
- }
-
- public int[] PercentGroupSizes
- {
- get => (int[])_percentGroupSizes.Clone();
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- int[] inputSizes = (int[])value.Clone();
- CheckGroupSize(nameof(value), inputSizes);
- _percentGroupSizes = inputSizes;
- }
- }
-
- public string CurrencyGroupSeparator
- {
- get => _currencyGroupSeparator;
- set
- {
- VerifyWritable();
- VerifyGroupSeparator(value, nameof(value));
- _currencyGroupSeparator = value;
- }
- }
-
- public string CurrencySymbol
- {
- get => _currencySymbol;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _currencySymbol = value;
- }
- }
-
- /// <summary>
- /// Returns the current culture's NumberFormatInfo. Used by Parse methods.
- /// </summary>
-
- public static NumberFormatInfo CurrentInfo
- {
- get
- {
- System.Globalization.CultureInfo culture = CultureInfo.CurrentCulture;
- if (!culture._isInherited)
- {
- NumberFormatInfo? info = culture._numInfo;
- if (info != null)
- {
- return info;
- }
- }
- // returns non-nullable when passed typeof(NumberFormatInfo)
- return (NumberFormatInfo)culture.GetFormat(typeof(NumberFormatInfo))!;
- }
- }
-
- public string NaNSymbol
- {
- get => _nanSymbol;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _nanSymbol = value;
- }
- }
-
- public int CurrencyNegativePattern
- {
- get => _currencyNegativePattern;
- set
- {
- if (value < 0 || value > 15)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 15));
- }
-
- VerifyWritable();
- _currencyNegativePattern = value;
- }
- }
-
- public int NumberNegativePattern
- {
- get => _numberNegativePattern;
- set
- {
- // NOTENOTE: the range of value should correspond to negNumberFormats[] in vm\COMNumber.cpp.
- if (value < 0 || value > 4)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 4));
- }
-
- VerifyWritable();
- _numberNegativePattern = value;
- }
- }
-
- public int PercentPositivePattern
- {
- get => _percentPositivePattern;
- set
- {
- // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp.
- if (value < 0 || value > 3)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 3));
- }
-
- VerifyWritable();
- _percentPositivePattern = value;
- }
- }
-
- public int PercentNegativePattern
- {
- get => _percentNegativePattern;
- set
- {
- // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp.
- if (value < 0 || value > 11)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 11));
- }
-
- VerifyWritable();
- _percentNegativePattern = value;
- }
- }
-
- public string NegativeInfinitySymbol
- {
- get => _negativeInfinitySymbol;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _negativeInfinitySymbol = value;
- }
- }
-
- public string NegativeSign
- {
- get => _negativeSign;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _negativeSign = value;
- UpdateHasInvariantNumberSigns();
- }
- }
-
- public int NumberDecimalDigits
- {
- get => _numberDecimalDigits;
- set
- {
- if (value < 0 || value > 99)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 99));
- }
-
- VerifyWritable();
- _numberDecimalDigits = value;
- }
- }
-
- public string NumberDecimalSeparator
- {
- get => _numberDecimalSeparator;
- set
- {
- VerifyWritable();
- VerifyDecimalSeparator(value, nameof(value));
- _numberDecimalSeparator = value;
- }
- }
-
- public string NumberGroupSeparator
- {
- get => _numberGroupSeparator;
- set
- {
- VerifyWritable();
- VerifyGroupSeparator(value, nameof(value));
- _numberGroupSeparator = value;
- }
- }
-
- public int CurrencyPositivePattern
- {
- get => _currencyPositivePattern;
- set
- {
- if (value < 0 || value > 3)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 3));
- }
-
- VerifyWritable();
- _currencyPositivePattern = value;
- }
- }
-
- public string PositiveInfinitySymbol
- {
- get => _positiveInfinitySymbol;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _positiveInfinitySymbol = value;
- }
- }
-
- public string PositiveSign
- {
- get => _positiveSign;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _positiveSign = value;
- UpdateHasInvariantNumberSigns();
- }
- }
-
- public int PercentDecimalDigits
- {
- get => _percentDecimalDigits;
- set
- {
- if (value < 0 || value > 99)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 0, 99));
- }
-
- VerifyWritable();
- _percentDecimalDigits = value;
- }
- }
-
- public string PercentDecimalSeparator
- {
- get => _percentDecimalSeparator;
- set
- {
- VerifyWritable();
- VerifyDecimalSeparator(value, nameof(value));
- _percentDecimalSeparator = value;
- }
- }
-
- public string PercentGroupSeparator
- {
- get => _percentGroupSeparator;
- set
- {
- VerifyWritable();
- VerifyGroupSeparator(value, nameof(value));
- _percentGroupSeparator = value;
- }
- }
-
- public string PercentSymbol
- {
- get => _percentSymbol;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _percentSymbol = value;
- }
- }
-
- public string PerMilleSymbol
- {
- get => _perMilleSymbol;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _perMilleSymbol = value;
- }
- }
-
- public string[] NativeDigits
- {
- get => (string[])_nativeDigits.Clone();
- set
- {
- VerifyWritable();
- VerifyNativeDigits(value, nameof(value));
- _nativeDigits = value;
- }
- }
-
- public DigitShapes DigitSubstitution
- {
- get => (DigitShapes)_digitSubstitution;
- set
- {
- VerifyWritable();
- VerifyDigitSubstitution(value, nameof(value));
- _digitSubstitution = (int)value;
- }
- }
-
- public object? GetFormat(Type? formatType)
- {
- return formatType == typeof(NumberFormatInfo) ? this : null;
- }
-
- public static NumberFormatInfo ReadOnly(NumberFormatInfo nfi)
- {
- if (nfi == null)
- {
- throw new ArgumentNullException(nameof(nfi));
- }
-
- if (nfi.IsReadOnly)
- {
- return nfi;
- }
-
- NumberFormatInfo info = (NumberFormatInfo)(nfi.MemberwiseClone());
- info._isReadOnly = true;
- return info;
- }
-
- // private const NumberStyles InvalidNumberStyles = unchecked((NumberStyles) 0xFFFFFC00);
- private const NumberStyles InvalidNumberStyles = ~(NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite
- | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign
- | NumberStyles.AllowParentheses | NumberStyles.AllowDecimalPoint
- | NumberStyles.AllowThousands | NumberStyles.AllowExponent
- | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier);
-
- internal static void ValidateParseStyleInteger(NumberStyles style)
- {
- // Check for undefined flags or invalid hex number flags
- if ((style & (InvalidNumberStyles | NumberStyles.AllowHexSpecifier)) != 0
- && (style & ~NumberStyles.HexNumber) != 0)
- {
- throwInvalid(style);
-
- void throwInvalid(NumberStyles value)
- {
- if ((value & InvalidNumberStyles) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style));
- }
-
- throw new ArgumentException(SR.Arg_InvalidHexStyle);
- }
- }
- }
-
- internal static void ValidateParseStyleFloatingPoint(NumberStyles style)
- {
- // Check for undefined flags or hex number
- if ((style & (InvalidNumberStyles | NumberStyles.AllowHexSpecifier)) != 0)
- {
- throwInvalid(style);
-
- void throwInvalid(NumberStyles value)
- {
- if ((value & InvalidNumberStyles) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style));
- }
-
- throw new ArgumentException(SR.Arg_HexStyleNotSupported);
- }
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/NumberStyles.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/NumberStyles.cs
deleted file mode 100644
index cf5a081016a..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/NumberStyles.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <summary>
- /// Contains valid formats for Numbers recognized by the Number
- /// class' parsing code.
- /// </summary>
- [Flags]
- public enum NumberStyles
- {
- None = 0x00000000,
-
- /// <summary>
- /// Bit flag indicating that leading whitespace is allowed. Character values
- /// 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, and 0x0020 are considered to be
- /// whitespace.
- /// </summary>
- AllowLeadingWhite = 0x00000001,
-
- /// <summary>
- /// Bitflag indicating trailing whitespace is allowed.
- /// </summary>
- AllowTrailingWhite = 0x00000002,
-
- /// <summary>
- /// Can the number start with a sign char specified by
- /// NumberFormatInfo.PositiveSign and NumberFormatInfo.NegativeSign
- /// </summary>
- AllowLeadingSign = 0x00000004,
-
- /// <summary>
- /// Allow the number to end with a sign char
- /// </summary>
- AllowTrailingSign = 0x00000008,
-
- /// <summary>
- /// Allow the number to be enclosed in parens
- /// </summary>
- AllowParentheses = 0x00000010,
-
- AllowDecimalPoint = 0x00000020,
-
- AllowThousands = 0x00000040,
-
- AllowExponent = 0x00000080,
-
- AllowCurrencySymbol = 0x00000100,
-
- AllowHexSpecifier = 0x00000200,
-
- Integer = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign,
-
- HexNumber = AllowLeadingWhite | AllowTrailingWhite | AllowHexSpecifier,
-
- Number = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
- AllowDecimalPoint | AllowThousands,
-
- Float = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign |
- AllowDecimalPoint | AllowExponent,
-
- Currency = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
- AllowParentheses | AllowDecimalPoint | AllowThousands | AllowCurrencySymbol,
-
- Any = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
- AllowParentheses | AllowDecimalPoint | AllowThousands | AllowCurrencySymbol | AllowExponent,
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
deleted file mode 100644
index 40268efb18d..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
+++ /dev/null
@@ -1,418 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- /// <summary>
- /// Modern Persian calendar is a solar observation based calendar. Each new year begins on the day when the vernal equinox occurs before noon.
- /// The epoch is the date of the vernal equinox prior to the epoch of the Islamic calendar (March 19, 622 Julian or March 22, 622 Gregorian)
- /// There is no Persian year 0. Ordinary years have 365 days. Leap years have 366 days with the last month (Esfand) gaining the extra day.
- /// </summary>
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 0622/03/22 9999/12/31
- /// Persian 0001/01/01 9378/10/13
- /// </remarks>
- public class PersianCalendar : Calendar
- {
- public static readonly int PersianEra = 1;
-
- private static readonly long s_persianEpoch = new DateTime(622, 3, 22).Ticks / GregorianCalendar.TicksPerDay;
- private const int ApproximateHalfYear = 180;
-
- private const int DatePartYear = 0;
- private const int DatePartDayOfYear = 1;
- private const int DatePartMonth = 2;
- 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 const int MaxCalendarYear = 9378;
- private const int MaxCalendarMonth = 10;
- private const int MaxCalendarDay = 13;
-
- // Persian calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 3, day: 22)
- // This is the minimal Gregorian date that we support in the PersianCalendar.
- private static readonly DateTime s_minDate = new DateTime(622, 3, 22);
- private static readonly DateTime s_maxDate = DateTime.MaxValue;
-
- public override DateTime MinSupportedDateTime => s_minDate;
-
- public override DateTime MaxSupportedDateTime => s_maxDate;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- public PersianCalendar()
- {
- }
-
- internal override CalendarId BaseCalendarID => CalendarId.GREGORIAN;
-
- internal override CalendarId ID => CalendarId.PERSIAN;
-
- private long GetAbsoluteDatePersian(int year, int month, int day)
- {
- if (year < 1 || year > MaxCalendarYear || month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- // day is one based, make 0 based since this will be the number of days we add to beginning of year below
- int ordinalDay = DaysInPreviousMonths(month) + day - 1;
- int approximateDaysFromEpochForYearStart = (int)(CalendricalCalculationsHelper.MeanTropicalYearInDays * (year - 1));
- long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(s_persianEpoch + approximateDaysFromEpochForYearStart + ApproximateHalfYear);
- yearStart += ordinalDay;
- return yearStart;
- }
-
- internal static void CheckTicksRange(long ticks)
- {
- if (ticks < s_minDate.Ticks || ticks > s_maxDate.Ticks)
- {
- throw new ArgumentOutOfRangeException(
- "time",
- ticks,
- SR.Format(SR.ArgumentOutOfRange_CalendarRange, s_minDate, s_maxDate));
- }
- }
-
- internal static void CheckEraRange(int era)
- {
- if (era != CurrentEra && era != PersianEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- }
-
- internal static void CheckYearRange(int year, int era)
- {
- CheckEraRange(era);
- if (year < 1 || year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear));
- }
- }
-
- internal static void CheckYearMonthRange(int year, int month, int era)
- {
- CheckYearRange(year, era);
- if (year == MaxCalendarYear)
- {
- if (month > MaxCalendarMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(month),
- month,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxCalendarMonth));
- }
- }
-
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
- }
-
- private static int MonthFromOrdinalDay(int ordinalDay)
- {
- Debug.Assert(ordinalDay <= 366);
- int index = 0;
- while (ordinalDay > s_daysToMonth[index])
- {
- index++;
- }
-
- return index;
- }
-
- private static int DaysInPreviousMonths(int month)
- {
- Debug.Assert(1 <= month && month <= 12);
- // months are one based but for calculations use 0 based
- --month;
- return s_daysToMonth[month];
- }
-
- internal int GetDatePart(long ticks, int part)
- {
- CheckTicksRange(ticks);
-
- // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
- // 1/1/0001 is absolute date 1.
- long numDays = ticks / GregorianCalendar.TicksPerDay + 1;
-
- // Calculate the appromixate Persian Year.
- long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(numDays);
- int y = (int)(Math.Floor(((yearStart - s_persianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1;
- Debug.Assert(y >= 1);
-
- if (part == DatePartYear)
- {
- return y;
- }
-
- // Calculate the Persian Month.
- int ordinalDay = (int)(numDays - CalendricalCalculationsHelper.GetNumberOfDays(this.ToDateTime(y, 1, 1, 0, 0, 0, 0, 1)));
- if (part == DatePartDayOfYear)
- {
- return ordinalDay;
- }
-
- int m = MonthFromOrdinalDay(ordinalDay);
- Debug.Assert(ordinalDay >= 1);
- Debug.Assert(m >= 1 && m <= 12);
- if (part == DatePartMonth)
- {
- return m;
- }
-
- int d = ordinalDay - DaysInPreviousMonths(m);
- Debug.Assert(1 <= d);
- Debug.Assert(d <= 31);
-
- // Calculate the Persian Day.
- if (part == DatePartDay)
- {
- return d;
- }
-
- // Incorrect part value.
- throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
- }
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- months,
- SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
- }
-
- // Get the date in Persian calendar.
- int y = GetDatePart(time.Ticks, DatePartYear);
- int m = GetDatePart(time.Ticks, DatePartMonth);
- int d = GetDatePart(time.Ticks, DatePartDay);
- int i = m - 1 + months;
- if (i >= 0)
- {
- m = i % 12 + 1;
- y += i / 12;
- }
- else
- {
- m = 12 + (i + 1) % 12;
- y += (i - 11) / 12;
- }
- int days = GetDaysInMonth(y, m);
- if (d > days)
- {
- d = days;
- }
-
- long ticks = GetAbsoluteDatePersian(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay;
- Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return new DateTime(ticks);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return AddMonths(time, years * 12);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDay);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartDayOfYear);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- CheckYearMonthRange(year, month, era);
-
- if ((month == MaxCalendarMonth) && (year == MaxCalendarYear))
- {
- return MaxCalendarDay;
- }
-
- int daysInMonth = s_daysToMonth[month] - s_daysToMonth[month - 1];
- if ((month == MonthsPerYear) && !IsLeapYear(year))
- {
- Debug.Assert(daysInMonth == 30);
- --daysInMonth;
- }
-
- return daysInMonth;
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- CheckYearRange(year, era);
- if (year == MaxCalendarYear)
- {
- return s_daysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay;
- }
-
- return IsLeapYear(year, CurrentEra) ? 366 : 365;
- }
-
- public override int GetEra(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return PersianEra;
- }
-
- public override int[] Eras => new int[] { PersianEra };
-
- public override int GetMonth(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartMonth);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- CheckYearRange(year, era);
- if (year == MaxCalendarYear)
- {
- return MaxCalendarMonth;
- }
-
- return 12;
- }
-
- public override int GetYear(DateTime time)
- {
- return GetDatePart(time.Ticks, DatePartYear);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- // The year/month/era value checking is done in GetDaysInMonth().
- int daysInMonth = GetDaysInMonth(year, month, era);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
-
- return IsLeapYear(year, era) && month == 12 && day == 30;
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- CheckYearRange(year, era);
- return 0;
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- CheckYearMonthRange(year, month, era);
- return false;
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- CheckYearRange(year, era);
-
- if (year == MaxCalendarYear)
- {
- return false;
- }
-
- return (GetAbsoluteDatePersian(year + 1, 1, 1) - GetAbsoluteDatePersian(year, 1, 1)) == 366;
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- // The year/month/era checking is done in GetDaysInMonth().
- int daysInMonth = GetDaysInMonth(year, month, era);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
-
- long lDate = GetAbsoluteDatePersian(year, month, day);
-
- if (lDate < 0)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond));
- }
-
- private const int DefaultTwoDigitYearMax = 1410;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- if (year < 100)
- {
- return base.ToFourDigitYear(year);
- }
-
- if (year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxCalendarYear));
- }
-
- return year;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
deleted file mode 100644
index ccaa806adb6..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class represents settings specified by de jure or de facto
- /// standards for a particular country/region. In contrast to
- /// CultureInfo, the RegionInfo does not represent preferences of the
- /// user and does not depend on the user's language or culture.
- /// </summary>
- public class RegionInfo
- {
- // Name of this region (ie: es-US): serialized, the field used for deserialization
- private string _name;
-
- // The CultureData instance that we are going to read data from.
- private readonly CultureData _cultureData;
-
- // The RegionInfo for our current region
- internal static volatile RegionInfo? s_currentRegionInfo;
-
- public RegionInfo(string name)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
-
- // The InvariantCulture has no matching region
- if (name.Length == 0)
- {
- throw new ArgumentException(SR.Argument_NoRegionInvariantCulture, nameof(name));
- }
-
- // For CoreCLR we only want the region names that are full culture names
- _cultureData = CultureData.GetCultureDataForRegion(name, true) ??
- throw new ArgumentException(SR.Format(SR.Argument_InvalidCultureName, name), nameof(name));
-
- // Not supposed to be neutral
- if (_cultureData.IsNeutralCulture)
- {
- throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), nameof(name));
- }
-
- _name = _cultureData.RegionName;
- }
-
- public RegionInfo(int culture)
- {
- // The InvariantCulture has no matching region
- if (culture == CultureInfo.LOCALE_INVARIANT)
- {
- throw new ArgumentException(SR.Argument_NoRegionInvariantCulture);
- }
-
- if (culture == CultureInfo.LOCALE_NEUTRAL)
- {
- // Not supposed to be neutral
- throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture));
- }
-
- if (culture == CultureInfo.LOCALE_CUSTOM_DEFAULT)
- {
- // Not supposed to be neutral
- throw new ArgumentException(SR.Format(SR.Argument_CustomCultureCannotBePassedByNumber, culture), nameof(culture));
- }
-
- _cultureData = CultureData.GetCultureData(culture, true);
- _name = _cultureData.RegionName;
-
- if (_cultureData.IsNeutralCulture)
- {
- // Not supposed to be neutral
- throw new ArgumentException(SR.Format(SR.Argument_CultureIsNeutral, culture), nameof(culture));
- }
- }
-
- internal RegionInfo(CultureData cultureData)
- {
- _cultureData = cultureData;
- _name = _cultureData.RegionName;
- }
-
- /// <summary>
- /// This instance provides methods based on the current user settings.
- /// These settings are volatile and may change over the lifetime of the
- /// </summary>
- public static RegionInfo CurrentRegion
- {
- get
- {
- RegionInfo? temp = s_currentRegionInfo;
- if (temp == null)
- {
- temp = new RegionInfo(CultureInfo.CurrentCulture._cultureData);
-
- // Need full name for custom cultures
- temp._name = temp._cultureData.RegionName;
- s_currentRegionInfo = temp;
- }
- return temp;
- }
- }
-
- /// <summary>
- /// Returns the name of the region (ie: en-US)
- /// </summary>
- public virtual string Name
- {
- get
- {
- Debug.Assert(_name != null, "Expected RegionInfo._name to be populated already");
- return _name;
- }
- }
-
- /// <summary>
- /// Returns the name of the region in English. (ie: United States)
- /// </summary>
- public virtual string EnglishName => _cultureData.EnglishCountryName;
-
- /// <summary>
- /// Returns the display name (localized) of the region. (ie: United States
- /// if the current UI language is en-US)
- /// </summary>
- public virtual string DisplayName => _cultureData.LocalizedCountryName;
-
- /// <summary>
- /// Returns the native name of the region. (ie: Deutschland)
- /// WARNING: You need a full locale name for this to make sense.
- /// </summary>
- public virtual string NativeName => _cultureData.NativeCountryName;
-
- /// <summary>
- /// Returns the two letter ISO region name (ie: US)
- /// </summary>
- public virtual string TwoLetterISORegionName => _cultureData.TwoLetterISOCountryName;
-
- /// <summary>
- /// Returns the three letter ISO region name (ie: USA)
- /// </summary>
- public virtual string ThreeLetterISORegionName => _cultureData.ThreeLetterISOCountryName;
-
- /// <summary>
- /// Returns the three letter windows region name (ie: USA)
- /// </summary>
- public virtual string ThreeLetterWindowsRegionName => ThreeLetterISORegionName;
-
-
- /// <summary>
- /// Returns true if this region uses the metric measurement system
- /// </summary>
- public virtual bool IsMetric => _cultureData.MeasurementSystem == 0;
-
- public virtual int GeoId => _cultureData.GeoId;
-
- /// <summary>
- /// English name for this region's currency, ie: Swiss Franc
- /// </summary>
- public virtual string CurrencyEnglishName => _cultureData.CurrencyEnglishName;
-
- /// <summary>
- /// Native name for this region's currency, ie: Schweizer Franken
- /// WARNING: You need a full locale name for this to make sense.
- /// </summary>
- public virtual string CurrencyNativeName => _cultureData.CurrencyNativeName;
-
- /// <summary>
- /// Currency Symbol for this locale, ie: Fr. or $
- /// </summary>
- public virtual string CurrencySymbol => _cultureData.CurrencySymbol;
-
- /// <summary>
- /// ISO Currency Symbol for this locale, ie: CHF
- /// </summary>
- public virtual string ISOCurrencySymbol => _cultureData.ISOCurrencySymbol;
-
- /// <summary>
- /// Implements Object.Equals(). Returns a boolean indicating whether
- /// or not object refers to the same RegionInfo as the current instance.
- /// RegionInfos are considered equal if and only if they have the same name
- /// (ie: en-US)
- /// </summary>
- public override bool Equals(object? value)
- {
- return value is RegionInfo otherRegion
- && Name.Equals(otherRegion.Name);
- }
-
- public override int GetHashCode() => Name.GetHashCode();
-
- public override string ToString() => Name;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/SortKey.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
deleted file mode 100644
index b69cf9f5513..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class implements a set of methods for retrieving
- /// </summary>
- public partial class SortKey
- {
- private readonly string _localeName;
- private readonly CompareOptions _options;
- private readonly string _string;
- private readonly byte[] _keyData;
-
- /// <summary>
- /// The following constructor is designed to be called from CompareInfo to get the
- /// the sort key of specific string for synthetic culture
- /// </summary>
- internal SortKey(string localeName, string str, CompareOptions options, byte[] keyData)
- {
- _keyData = keyData;
- _localeName = localeName;
- _options = options;
- _string = str;
- }
-
- /// <summary>
- /// Returns the original string used to create the current instance
- /// of SortKey.
- /// </summary>
- public virtual string OriginalString => _string;
-
- /// <summary>
- /// Returns a byte array representing the current instance of the
- /// sort key.
- /// </summary>
- public virtual byte[] KeyData => (byte[])_keyData.Clone();
-
- /// <summary>
- /// Compares the two sort keys. Returns 0 if the two sort keys are
- /// equal, a number less than 0 if sortkey1 is less than sortkey2,
- /// and a number greater than 0 if sortkey1 is greater than sortkey2.
- /// </summary>
- public static int Compare(SortKey sortkey1, SortKey sortkey2)
- {
- if (sortkey1 == null)
- {
- throw new ArgumentNullException(nameof(sortkey1));
- }
- if (sortkey2 == null)
- {
- throw new ArgumentNullException(nameof(sortkey2));
- }
-
- byte[] key1Data = sortkey1._keyData;
- byte[] key2Data = sortkey2._keyData;
-
- Debug.Assert(key1Data != null, "key1Data != null");
- Debug.Assert(key2Data != null, "key2Data != null");
-
- if (key1Data.Length == 0)
- {
- if (key2Data.Length == 0)
- {
- return 0;
- }
-
- return -1;
- }
- if (key2Data.Length == 0)
- {
- return 1;
- }
-
- int compLen = (key1Data.Length < key2Data.Length) ? key1Data.Length : key2Data.Length;
- for (int i = 0; i < compLen; i++)
- {
- if (key1Data[i] > key2Data[i])
- {
- return 1;
- }
- if (key1Data[i] < key2Data[i])
- {
- return -1;
- }
- }
-
- return 0;
- }
-
- public override bool Equals(object? value)
- {
- return value is SortKey otherSortKey && Compare(this, otherSortKey) == 0;
- }
-
- public override int GetHashCode()
- {
- return CompareInfo.GetCompareInfo(_localeName).GetHashCodeOfString(_string, _options);
- }
-
- public override string ToString()
- {
- return "SortKey - " + _localeName + ", " + _options + ", " + _string;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
deleted file mode 100644
index 2cac2389d9f..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.CompilerServices;
-
-namespace System.Globalization
-{
- [Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public sealed class SortVersion :
-#nullable disable // to enable use with both T and T? for reference types due to IEquatable<T> being invariant
- IEquatable<SortVersion>
-#nullable restore
- {
- private readonly int m_NlsVersion; // Do not rename (binary serialization)
- private Guid m_SortId; // Do not rename (binary serialization)
-
- public int FullVersion => m_NlsVersion;
-
- public Guid SortId => m_SortId;
-
- public SortVersion(int fullVersion, Guid sortId)
- {
- m_SortId = sortId;
- m_NlsVersion = fullVersion;
- }
-
- internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion)
- {
- m_NlsVersion = nlsVersion;
-
- if (customVersion == Guid.Empty)
- {
- byte b1 = (byte)(effectiveId >> 24);
- byte b2 = (byte)((effectiveId & 0x00FF0000) >> 16);
- byte b3 = (byte)((effectiveId & 0x0000FF00) >> 8);
- byte b4 = (byte)(effectiveId & 0xFF);
- customVersion = new Guid(0, 0, 0, 0, 0, 0, 0, b1, b2, b3, b4);
- }
-
- m_SortId = customVersion;
- }
-
- public override bool Equals(object? obj)
- {
- return obj is SortVersion otherVersion && Equals(otherVersion);
- }
-
- public bool Equals(SortVersion? other)
- {
- if (other == null)
- {
- return false;
- }
-
- return m_NlsVersion == other.m_NlsVersion && m_SortId == other.m_SortId;
- }
-
- public override int GetHashCode()
- {
- return m_NlsVersion * 7 | m_SortId.GetHashCode();
- }
-
- // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(SortVersion? left, SortVersion? right)
- {
- // Test "right" first to allow branch elimination when inlined for null checks (== null)
- // so it can become a simple test
- if (right is null)
- {
- // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
- return (left is null) ? true : false;
- }
-
- return right.Equals(left);
- }
-
- public static bool operator !=(SortVersion? left, SortVersion? right) =>
- !(left == right);
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
deleted file mode 100644
index f82d3f618c1..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
+++ /dev/null
@@ -1,296 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- /// <summary>
- /// This class defines behaviors specific to a writing system.
- /// A writing system is the collection of scripts and orthographic rules
- /// required to represent a language as text.
- /// </summary>
- public class StringInfo
- {
- private string _str = null!; // initialized in helper called by ctors
-
- private int[]? _indexes;
-
- public StringInfo() : this(string.Empty)
- {
- }
-
- public StringInfo(string value)
- {
- this.String = value;
- }
-
- public override bool Equals(object? value)
- {
- return value is StringInfo otherStringInfo
- && _str.Equals(otherStringInfo._str);
- }
-
- public override int GetHashCode() => _str.GetHashCode();
-
- /// <summary>
- /// Our zero-based array of index values into the string. Initialize if
- /// our private array is not yet, in fact, initialized.
- /// </summary>
- private int[]? Indexes
- {
- get
- {
- if (_indexes == null && String.Length > 0)
- {
- _indexes = StringInfo.ParseCombiningCharacters(String);
- }
-
- return _indexes;
- }
- }
-
- public string String
- {
- get => _str;
- set
- {
- _str = value ?? throw new ArgumentNullException(nameof(value));
- _indexes = null;
- }
- }
-
- public int LengthInTextElements => Indexes?.Length ?? 0;
-
- public string SubstringByTextElements(int startingTextElement)
- {
- // If the string is empty, no sense going further.
- if (Indexes == null)
- {
- if (startingTextElement < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(startingTextElement), startingTextElement, SR.ArgumentOutOfRange_NeedPosNum);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(startingTextElement), startingTextElement, SR.Arg_ArgumentOutOfRangeException);
- }
- }
-
- return SubstringByTextElements(startingTextElement, Indexes.Length - startingTextElement);
- }
-
- public string SubstringByTextElements(int startingTextElement, int lengthInTextElements)
- {
- if (startingTextElement < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(startingTextElement), startingTextElement, SR.ArgumentOutOfRange_NeedPosNum);
- }
- if (String.Length == 0 || startingTextElement >= Indexes!.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(startingTextElement), startingTextElement, SR.Arg_ArgumentOutOfRangeException);
- }
- if (lengthInTextElements < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), lengthInTextElements, SR.ArgumentOutOfRange_NeedPosNum);
- }
- if (startingTextElement > Indexes.Length - lengthInTextElements)
- {
- throw new ArgumentOutOfRangeException(nameof(lengthInTextElements), lengthInTextElements, SR.Arg_ArgumentOutOfRangeException);
- }
-
- int start = Indexes[startingTextElement];
-
- if (startingTextElement + lengthInTextElements == Indexes.Length)
- {
- // We are at the last text element in the string and because of that
- // must handle the call differently.
- return String.Substring(start);
- }
- else
- {
- return String[start..Indexes[lengthInTextElements + startingTextElement]];
- }
- }
-
- public static string GetNextTextElement(string str) => GetNextTextElement(str, 0);
-
- /// <summary>
- /// Get the code point count of the current text element.
- ///
- /// A combining class is defined as:
- /// A character/surrogate that has the following Unicode category:
- /// * NonSpacingMark (e.g. U+0300 COMBINING GRAVE ACCENT)
- /// * SpacingCombiningMark (e.g. U+ 0903 DEVANGARI SIGN VISARGA)
- /// * EnclosingMark (e.g. U+20DD COMBINING ENCLOSING CIRCLE)
- ///
- /// In the context of GetNextTextElement() and ParseCombiningCharacters(), a text element is defined as:
- /// 1. If a character/surrogate is in the following category, it is a text element.
- /// It can NOT further combine with characters in the combinging class to form a text element.
- /// * one of the Unicode category in the combinging class
- /// * UnicodeCategory.Format
- /// * UnicodeCateogry.Control
- /// * UnicodeCategory.OtherNotAssigned
- /// 2. Otherwise, the character/surrogate can be combined with characters in the combinging class to form a text element.
- /// </summary>
- /// <returns>The length of the current text element</returns>
- internal static int GetCurrentTextElementLen(string str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount)
- {
- Debug.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len);
- Debug.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len);
- if (index + currentCharCount == len)
- {
- // This is the last character/surrogate in the string.
- return currentCharCount;
- }
-
- // Call an internal GetUnicodeCategory, which will tell us both the unicode category, and also tell us if it is a surrogate pair or not.
- int nextCharCount;
- UnicodeCategory ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index + currentCharCount, out nextCharCount);
- if (CharUnicodeInfo.IsCombiningCategory(ucNext))
- {
- // The next element is a combining class.
- // Check if the current text element to see if it is a valid base category (i.e. it should not be a combining category,
- // not a format character, and not a control character).
- if (CharUnicodeInfo.IsCombiningCategory(ucCurrent)
- || (ucCurrent == UnicodeCategory.Format)
- || (ucCurrent == UnicodeCategory.Control)
- || (ucCurrent == UnicodeCategory.OtherNotAssigned)
- || (ucCurrent == UnicodeCategory.Surrogate)) // An unpair high surrogate or low surrogate
- {
- // Will fall thru and return the currentCharCount
- }
- else
- {
- // Remember the current index.
- int startIndex = index;
-
- // We have a valid base characters, and we have a character (or surrogate) that is combining.
- // Check if there are more combining characters to follow.
- // Check if the next character is a nonspacing character.
- index += currentCharCount + nextCharCount;
-
- while (index < len)
- {
- ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out nextCharCount);
- if (!CharUnicodeInfo.IsCombiningCategory(ucNext))
- {
- ucCurrent = ucNext;
- currentCharCount = nextCharCount;
- break;
- }
- index += nextCharCount;
- }
-
- return index - startIndex;
- }
- }
-
- // The return value will be the currentCharCount.
- int ret = currentCharCount;
- ucCurrent = ucNext;
- // Update currentCharCount.
- currentCharCount = nextCharCount;
- return ret;
- }
-
- /// <summary>
- /// Returns the str containing the next text element in str starting at
- /// index index. If index is not supplied, then it will start at the beginning
- /// of str. It recognizes a base character plus one or more combining
- /// characters or a properly formed surrogate pair as a text element.
- /// See also the ParseCombiningCharacters() and the ParseSurrogates() methods.
- /// </summary>
- public static string GetNextTextElement(string str, int index)
- {
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- int len = str.Length;
- if (index < 0 || index >= len)
- {
- if (index == len)
- {
- return string.Empty;
- }
-
- throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index);
- }
-
- int charLen;
- UnicodeCategory uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
- return str.Substring(index, GetCurrentTextElementLen(str, index, len, ref uc, ref charLen));
- }
-
- public static TextElementEnumerator GetTextElementEnumerator(string str)
- {
- return GetTextElementEnumerator(str, 0);
- }
-
- public static TextElementEnumerator GetTextElementEnumerator(string str, int index)
- {
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- int len = str.Length;
- if (index < 0 || index > len)
- {
- throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_Index);
- }
-
- return new TextElementEnumerator(str, index, len);
- }
-
- /// <summary>
- /// Returns the indices of each base character or properly formed surrogate
- /// pair within the str. It recognizes a base character plus one or more
- /// combining characters or a properly formed surrogate pair as a text
- /// element and returns the index of the base character or high surrogate.
- /// Each index is the beginning of a text element within a str. The length
- /// of each element is easily computed as the difference between successive
- /// indices. The length of the array will always be less than or equal to
- /// the length of the str. For example, given the str
- /// \u4f00\u302a\ud800\udc00\u4f01, this method would return the indices:
- /// 0, 2, 4.
- /// </summary>
- public static int[] ParseCombiningCharacters(string str)
- {
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- int len = str.Length;
- int[] result = new int[len];
- if (len == 0)
- {
- return result;
- }
-
- int resultCount = 0;
-
- int i = 0;
- int currentCharLen;
- UnicodeCategory currentCategory = CharUnicodeInfo.InternalGetUnicodeCategory(str, 0, out currentCharLen);
-
- while (i < len)
- {
- result[resultCount++] = i;
- i += GetCurrentTextElementLen(str, i, len, ref currentCategory, ref currentCharLen);
- }
-
- if (resultCount < len)
- {
- int[] returnArray = new int[resultCount];
- Array.Copy(result, returnArray, resultCount);
- return returnArray;
- }
- return result;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
deleted file mode 100644
index 03003826dfa..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <summary>
- /// Taiwan calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar.
- /// That is,
- /// Taiwan year = Gregorian year - 1911. So 1912/01/01 A.D. is Taiwan 1/01/01
- /// </summary>
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1912/01/01 9999/12/31
- /// Taiwan 01/01/01 8088/12/31
- /// </remarks>
- public class TaiwanCalendar : Calendar
- {
- // Since
- // Gregorian Year = Era Year + yearOffset
- // When Gregorian Year 1912 is year 1, so that
- // 1912 = 1 + yearOffset
- // So yearOffset = 1911
- private static readonly EraInfo[] s_taiwanEraInfo = new EraInfo[]
- {
- new EraInfo(1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear
- };
-
- private static volatile Calendar? s_defaultInstance;
-
- private readonly GregorianCalendarHelper _helper;
-
- internal static Calendar GetDefaultInstance() => s_defaultInstance ??= new TaiwanCalendar();
-
- private static readonly DateTime s_calendarMinValue = new DateTime(1912, 1, 1);
-
- public override DateTime MinSupportedDateTime => s_calendarMinValue;
-
- public override DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- public TaiwanCalendar()
- {
- try
- {
- new CultureInfo("zh-TW");
- }
- catch (ArgumentException e)
- {
- throw new TypeInitializationException(GetType().ToString(), e);
- }
-
- _helper = new GregorianCalendarHelper(this, s_taiwanEraInfo);
- }
-
- internal override CalendarId ID => CalendarId.TAIWAN;
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- return _helper.AddMonths(time, months);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return _helper.AddYears(time, years);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- return _helper.GetDaysInMonth(year, month, era);
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- return _helper.GetDaysInYear(year, era);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return _helper.GetDayOfMonth(time);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return _helper.GetDayOfWeek(time);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return _helper.GetDayOfYear(time);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- return _helper.GetMonthsInYear(year, era);
- }
-
- public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
- {
- return _helper.GetWeekOfYear(time, rule, firstDayOfWeek);
- }
-
- public override int GetEra(DateTime time)
- {
- return _helper.GetEra(time);
- }
-
- public override int GetMonth(DateTime time)
- {
- return _helper.GetMonth(time);
- }
-
- public override int GetYear(DateTime time)
- {
- return _helper.GetYear(time);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- return _helper.IsLeapDay(year, month, day, era);
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- return _helper.IsLeapYear(year, era);
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- return _helper.GetLeapMonth(year, era);
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- return _helper.IsLeapMonth(year, month, era);
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- return _helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era);
- }
-
- public override int[] Eras => _helper.Eras;
-
- private const int DefaultTwoDigitYearMax = 99;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > _helper.MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, _helper.MaxYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- /// <summary>
- /// For Taiwan calendar, four digit year is not used.
- /// Therefore, for any two digit number, we just return the original number.
- /// </summary>
-
- public override int ToFourDigitYear(int year)
- {
- if (year <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedPosNum);
- }
- if (year > _helper.MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, 1, _helper.MaxYear));
- }
-
- return year;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
deleted file mode 100644
index cecbf6a7ed4..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
+++ /dev/null
@@ -1,234 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1912/02/18 2051/02/10
- /// TaiwanLunisolar 1912/01/01 2050/13/29
- /// </remarks>
- public class TaiwanLunisolarCalendar : EastAsianLunisolarCalendar
- {
- // Since
- // Gregorian Year = Era Year + yearOffset
- // When Gregorian Year 1912 is year 1, so that
- // 1912 = 1 + yearOffset
- // So yearOffset = 1911
- private static readonly EraInfo[] s_taiwanLunisolarEraInfo = new EraInfo[]
- {
- new EraInfo(1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear
- };
-
- private readonly GregorianCalendarHelper _helper;
-
- private const int MinLunisolarYear = 1912;
- private const int MaxLunisolarYear = 2050;
-
- private static readonly DateTime s_minDate = new DateTime(1912, 2, 18);
- private static readonly DateTime s_maxDate = new DateTime((new DateTime(2051, 2, 10, 23, 59, 59, 999)).Ticks + 9999);
-
- public override DateTime MinSupportedDateTime => s_minDate;
-
- public override DateTime MaxSupportedDateTime => s_maxDate;
-
- protected override int DaysInYearBeforeMinSupportedYear =>
- // 1911 from ChineseLunisolarCalendar
- 384;
-
- private static readonly int[,] s_yinfo =
- {
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 1912 */
- { 0, 2, 18, 42192 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1913 */ { 0, 2, 6, 53840 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1914 */ { 5, 1, 26, 54568 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1915 */ { 0, 2, 14, 46400 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1916 */ { 0, 2, 3, 54944 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1917 */ { 2, 1, 23, 38608 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */ { 0, 2, 11, 38320 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1919 */ { 7, 2, 1, 18872 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1920 */ { 0, 2, 20, 18800 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1921 */ { 0, 2, 8, 42160 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1922 */ { 5, 1, 28, 45656 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */ { 0, 2, 16, 27216 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1924 */ { 0, 2, 5, 27968 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1925 */ { 4, 1, 24, 44456 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1926 */ { 0, 2, 13, 11104 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1927 */ { 0, 2, 2, 38256 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1928 */ { 2, 1, 23, 18808 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1929 */ { 0, 2, 10, 18800 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1930 */ { 6, 1, 30, 25776 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */ { 0, 2, 17, 54432 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1932 */ { 0, 2, 6, 59984 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1933 */ { 5, 1, 26, 27976 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */ { 0, 2, 14, 23248 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1935 */ { 0, 2, 4, 11104 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1936 */ { 3, 1, 24, 37744 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1937 */ { 0, 2, 11, 37600 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1938 */ { 7, 1, 31, 51560 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */ { 0, 2, 19, 51536 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1940 */ { 0, 2, 8, 54432 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1941 */ { 6, 1, 27, 55888 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */ { 0, 2, 15, 46416 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1943 */ { 0, 2, 5, 22176 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1944 */ { 4, 1, 25, 43736 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1945 */ { 0, 2, 13, 9680 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1946 */ { 0, 2, 2, 37584 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1947 */ { 2, 1, 22, 51544 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */ { 0, 2, 10, 43344 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1949 */ { 7, 1, 29, 46248 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1950 */ { 0, 2, 17, 27808 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
-1951 */ { 0, 2, 6, 46416 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1952 */ { 5, 1, 27, 21928 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1953 */ { 0, 2, 14, 19872 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1954 */ { 0, 2, 3, 42416 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1955 */ { 3, 1, 24, 21176 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */ { 0, 2, 12, 21168 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1957 */ { 8, 1, 31, 43344 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1958 */ { 0, 2, 18, 59728 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1959 */ { 0, 2, 8, 27296 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1960 */ { 6, 1, 28, 44368 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */ { 0, 2, 15, 43856 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */ { 0, 2, 5, 19296 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1963 */ { 4, 1, 25, 42352 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */ { 0, 2, 13, 42352 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */ { 0, 2, 2, 21088 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
-1966 */ { 3, 1, 21, 59696 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1967 */ { 0, 2, 9, 55632 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */ { 7, 1, 30, 23208 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1969 */ { 0, 2, 17, 22176 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */ { 0, 2, 6, 38608 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1971 */ { 5, 1, 27, 19176 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */ { 0, 2, 15, 19152 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-1973 */ { 0, 2, 3, 42192 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1974 */ { 4, 1, 23, 53864 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */ { 0, 2, 11, 53840 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */ { 8, 1, 31, 54568 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1977 */ { 0, 2, 18, 46400 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */ { 0, 2, 7, 46752 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-1979 */ { 6, 1, 28, 38608 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */ { 0, 2, 16, 38320 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */ { 0, 2, 5, 18864 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */ { 4, 1, 25, 42168 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1983 */ { 0, 2, 13, 42160 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */ { 10, 2, 2, 45656 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */ { 0, 2, 20, 27216 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */ { 0, 2, 9, 27968 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */ { 6, 1, 29, 44448 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
-1988 */ { 0, 2, 17, 43872 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1989 */ { 0, 2, 6, 38256 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1990 */ { 5, 1, 27, 18808 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1991 */ { 0, 2, 15, 18800 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */ { 0, 2, 4, 25776 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */ { 3, 1, 23, 27216 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */ { 0, 2, 10, 59984 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */ { 8, 1, 31, 27432 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1996 */ { 0, 2, 19, 23232 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1997 */ { 0, 2, 7, 43872 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1998 */ { 5, 1, 28, 37736 }, /* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
-1999 */ { 0, 2, 16, 37600 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */ { 0, 2, 5, 51552 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */ { 4, 1, 24, 54440 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2002 */ { 0, 2, 12, 54432 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */ { 0, 2, 1, 55888 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */ { 2, 1, 22, 23208 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */ { 0, 2, 9, 22176 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-2006 */ { 7, 1, 29, 43736 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */ { 0, 2, 18, 9680 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */ { 0, 2, 7, 37584 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */ { 5, 1, 26, 51544 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */ { 0, 2, 14, 43344 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */ { 0, 2, 3, 46240 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */ { 4, 1, 23, 46416 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2013 */ { 0, 2, 10, 44368 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2014 */ { 9, 1, 31, 21928 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */ { 0, 2, 19, 19360 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */ { 0, 2, 8, 42416 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */ { 6, 1, 28, 21176 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */ { 0, 2, 16, 21168 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */ { 0, 2, 5, 43312 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
-2020 */ { 4, 1, 25, 29864 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */ { 0, 2, 12, 27296 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */ { 0, 2, 1, 44368 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */ { 2, 1, 22, 19880 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2024 */ { 0, 2, 10, 19296 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */ { 6, 1, 29, 42352 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */ { 0, 2, 17, 42208 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-2027 */ { 0, 2, 6, 53856 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-2028 */ { 5, 1, 26, 59696 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2029 */ { 0, 2, 13, 54576 }, /* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
-2030 */ { 0, 2, 3, 23200 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */ { 3, 1, 23, 27472 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */ { 0, 2, 11, 38608 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */ { 11, 1, 31, 19176 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */ { 0, 2, 19, 19152 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-2035 */ { 0, 2, 8, 42192 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */ { 6, 1, 28, 53848 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-2037 */ { 0, 2, 15, 53840 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */ { 0, 2, 4, 54560 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */ { 5, 1, 24, 55968 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */ { 0, 2, 12, 46496 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-2041 */ { 0, 2, 1, 22224 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */ { 2, 1, 22, 19160 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */ { 0, 2, 10, 18864 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */ { 7, 1, 30, 42168 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */ { 0, 2, 17, 42160 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */ { 0, 2, 6, 43600 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-2047 */ { 5, 1, 26, 46376 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */ { 0, 2, 14, 27936 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-2049 */ { 0, 2, 2, 44448 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-2050 */ { 3, 1, 23, 21936 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
- */ };
-
-
- internal override int MinCalendarYear => MinLunisolarYear;
-
- internal override int MaxCalendarYear => MaxLunisolarYear;
-
- internal override DateTime MinDate => s_minDate;
-
- internal override DateTime MaxDate => s_maxDate;
-
- internal override EraInfo[]? CalEraInfo => s_taiwanLunisolarEraInfo;
-
- internal override int GetYearInfo(int lunarYear, int index)
- {
- if ((lunarYear < MinLunisolarYear) || (lunarYear > MaxLunisolarYear))
- {
- throw new ArgumentOutOfRangeException(
- "year",
- lunarYear,
- SR.Format(SR.ArgumentOutOfRange_Range, MinLunisolarYear, MaxLunisolarYear));
- }
-
- return s_yinfo[lunarYear - MinLunisolarYear, index];
- }
-
- internal override int GetYear(int year, DateTime time)
- {
- return _helper.GetYear(year, time);
- }
-
- internal override int GetGregorianYear(int year, int era)
- {
- return _helper.GetGregorianYear(year, era);
- }
-
- public TaiwanLunisolarCalendar()
- {
- _helper = new GregorianCalendarHelper(this, s_taiwanLunisolarEraInfo);
- }
-
- public override int GetEra(DateTime time) => _helper.GetEra(time);
-
- internal override CalendarId BaseCalendarID => CalendarId.TAIWAN;
-
- internal override CalendarId ID => CalendarId.TAIWANLUNISOLAR;
-
- public override int[] Eras => _helper.Eras;
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
deleted file mode 100644
index 7ee564a9347..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections;
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- public class TextElementEnumerator : IEnumerator
- {
- private readonly string _str;
- private int _index;
- private readonly int _startIndex;
-
- // This is the length of the total string, counting from the beginning of string.
- private readonly int _strLen;
-
- // The current text element lenght after MoveNext() is called.
- private int _currTextElementLen;
-
- private UnicodeCategory _uc;
-
- // The next abstract char to look at after MoveNext() is called.
- // It could be 1 or 2, depending on if it is a surrogate or not.
- private int _charLen;
-
- internal TextElementEnumerator(string str, int startIndex, int strLen)
- {
- Debug.Assert(str != null, "TextElementEnumerator(): str != null");
- Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
- Debug.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex");
- _str = str;
- _startIndex = startIndex;
- _strLen = strLen;
- Reset();
- }
-
- public bool MoveNext()
- {
- if (_index >= _strLen)
- {
- // Make the _index to be greater than _strLen so that we can throw exception if GetTextElement() is called.
- _index = _strLen + 1;
- return false;
- }
-
- _currTextElementLen = StringInfo.GetCurrentTextElementLen(_str, _index, _strLen, ref _uc, ref _charLen);
- _index += _currTextElementLen;
- return true;
- }
-
- public object Current => GetTextElement();
-
- public string GetTextElement()
- {
- if (_index == _startIndex)
- {
- throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
- }
- if (_index > _strLen)
- {
- throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
- }
-
- return _str.Substring(_index - _currTextElementLen, _currTextElementLen);
- }
-
- public int ElementIndex
- {
- get
- {
- if (_index == _startIndex)
- {
- throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
- }
-
- return _index - _currTextElementLen;
- }
- }
-
- public void Reset()
- {
- _index = _startIndex;
- if (_index < _strLen)
- {
- // If we have more than 1 character, get the category of the current char.
- _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen);
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
deleted file mode 100644
index 02e7c5f50b9..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Text;
-
-namespace System.Globalization
-{
- public partial class TextInfo
- {
- private Tristate _needsTurkishCasing = Tristate.NotInitialized;
-
- private void FinishInitialization() { }
-
- // -----------------------------
- // ---- PAL layer ends here ----
- // -----------------------------
-
- private static bool NeedsTurkishCasing(string localeName)
- {
- Debug.Assert(localeName != null);
-
- return CultureInfo.GetCultureInfo(localeName).CompareInfo.Compare("\u0131", "I", CompareOptions.IgnoreCase) == 0;
- }
-
- private bool IsInvariant { get { return _cultureName.Length == 0; } }
-
- internal unsafe void ChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- if (IsInvariant)
- {
- Interop.Globalization.ChangeCaseInvariant(src, srcLen, dstBuffer, dstBufferCapacity, bToUpper);
- }
- else
- {
- if (_needsTurkishCasing == Tristate.NotInitialized)
- {
- _needsTurkishCasing = NeedsTurkishCasing(_textInfoName) ? Tristate.True : Tristate.False;
- }
- if (_needsTurkishCasing == Tristate.True)
- {
- Interop.Globalization.ChangeCaseTurkish(src, srcLen, dstBuffer, dstBufferCapacity, bToUpper);
- }
- else
- {
- Interop.Globalization.ChangeCase(src, srcLen, dstBuffer, dstBufferCapacity, bToUpper);
- }
- }
- }
-
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
deleted file mode 100644
index 948644769da..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- public partial class TextInfo
- {
- private unsafe void FinishInitialization()
- {
- _sortHandle = CompareInfo.GetSortHandle(_textInfoName);
- }
-
- private unsafe void ChangeCase(char* pSource, int pSourceLen, char* pResult, int pResultLen, bool toUpper)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(pSource != null);
- Debug.Assert(pResult != null);
- Debug.Assert(pSourceLen >= 0);
- Debug.Assert(pResultLen >= 0);
- Debug.Assert(pSourceLen <= pResultLen);
-
- // Check for Invariant to avoid A/V in LCMapStringEx
- uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
-
- int ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
- pSource,
- pSourceLen,
- pResult,
- pSourceLen,
- null,
- null,
- _sortHandle);
- if (ret == 0)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
-
- Debug.Assert(ret == pSourceLen, "Expected getting the same length of the original string");
- }
-
- // PAL Ends here
-
- private IntPtr _sortHandle;
-
- private const uint LCMAP_LINGUISTIC_CASING = 0x01000000;
- private const uint LCMAP_LOWERCASE = 0x00000100;
- private const uint LCMAP_UPPERCASE = 0x00000200;
-
- private static bool IsInvariantLocale(string localeName) => localeName == "";
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
deleted file mode 100644
index d1f6b8d343b..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
+++ /dev/null
@@ -1,870 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
-using System.Text;
-using System.Text.Unicode;
-using Internal.Runtime.CompilerServices;
-
-#pragma warning disable SA1121 // explicitly using type aliases instead of built-in types
-#if BIT64
-using nuint = System.UInt64;
-#else // BIT64
-using nuint = System.UInt32;
-#endif // BIT64
-
-namespace System.Globalization
-{
- /// <summary>
- /// This Class defines behaviors specific to a writing system.
- /// A writing system is the collection of scripts and orthographic rules
- /// required to represent a language as text.
- /// </summary>
- public partial class TextInfo : ICloneable, IDeserializationCallback
- {
- private enum Tristate : byte
- {
- NotInitialized = 0,
- False = 1,
- True = 2
- }
-
- private string? _listSeparator;
- private bool _isReadOnly = false;
-
- private readonly string _cultureName;
- private readonly CultureData _cultureData;
-
- // // Name of the text info we're using (ie: _cultureData.TextInfoName)
- private readonly string _textInfoName;
-
- private Tristate _isAsciiCasingSameAsInvariant = Tristate.NotInitialized;
-
- // Invariant text info
- internal static TextInfo Invariant => s_invariant ??= new TextInfo(CultureData.Invariant);
-
- private static volatile TextInfo? s_invariant;
-
- internal TextInfo(CultureData cultureData)
- {
- // This is our primary data source, we don't need most of the rest of this
- _cultureData = cultureData;
- _cultureName = _cultureData.CultureName;
- _textInfoName = _cultureData.TextInfoName;
-
- FinishInitialization();
- }
-
- void IDeserializationCallback.OnDeserialization(object? sender)
- {
- throw new PlatformNotSupportedException();
- }
-
- public virtual int ANSICodePage => _cultureData.ANSICodePage;
-
- public virtual int OEMCodePage => _cultureData.OEMCodePage;
-
- public virtual int MacCodePage => _cultureData.MacCodePage;
-
- public virtual int EBCDICCodePage => _cultureData.EBCDICCodePage;
-
- // Just use the LCID from our text info name
- public int LCID => CultureInfo.GetCultureInfo(_textInfoName).LCID;
-
- public string CultureName => _textInfoName;
-
- public bool IsReadOnly => _isReadOnly;
-
- public virtual object Clone()
- {
- object o = MemberwiseClone();
- ((TextInfo)o).SetReadOnlyState(false);
- return o;
- }
-
- /// <summary>
- /// Create a cloned readonly instance or return the input one if it is
- /// readonly.
- /// </summary>
- public static TextInfo ReadOnly(TextInfo textInfo)
- {
- if (textInfo == null)
- {
- throw new ArgumentNullException(nameof(textInfo));
- }
-
- if (textInfo.IsReadOnly)
- {
- return textInfo;
- }
-
- TextInfo clonedTextInfo = (TextInfo)(textInfo.MemberwiseClone());
- clonedTextInfo.SetReadOnlyState(true);
- return clonedTextInfo;
- }
-
- private void VerifyWritable()
- {
- if (_isReadOnly)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
- }
-
- internal void SetReadOnlyState(bool readOnly)
- {
- _isReadOnly = readOnly;
- }
-
- /// <summary>
- /// Returns the string used to separate items in a list.
- /// </summary>
- public virtual string ListSeparator
- {
- get => _listSeparator ??= _cultureData.ListSeparator;
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- VerifyWritable();
- _listSeparator = value;
- }
- }
-
- /// <summary>
- /// Converts the character or string to lower case. Certain locales
- /// have different casing semantics from the file systems in Win32.
- /// </summary>
- public virtual char ToLower(char c)
- {
- if (GlobalizationMode.Invariant || (IsAscii(c) && IsAsciiCasingSameAsInvariant))
- {
- return ToLowerAsciiInvariant(c);
- }
-
- return ChangeCase(c, toUpper: false);
- }
-
- public virtual string ToLower(string str)
- {
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- if (GlobalizationMode.Invariant)
- {
- return ToLowerAsciiInvariant(str);
- }
-
- return ChangeCaseCommon<ToLowerConversion>(str);
- }
-
- private unsafe char ChangeCase(char c, bool toUpper)
- {
- Debug.Assert(!GlobalizationMode.Invariant);
-
- char dst = default;
- ChangeCase(&c, 1, &dst, 1, toUpper);
- return dst;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ChangeCaseToLower(ReadOnlySpan<char> source, Span<char> destination)
- {
- Debug.Assert(destination.Length >= source.Length);
- ChangeCaseCommon<ToLowerConversion>(ref MemoryMarshal.GetReference(source), ref MemoryMarshal.GetReference(destination), source.Length);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ChangeCaseToUpper(ReadOnlySpan<char> source, Span<char> destination)
- {
- Debug.Assert(destination.Length >= source.Length);
- ChangeCaseCommon<ToUpperConversion>(ref MemoryMarshal.GetReference(source), ref MemoryMarshal.GetReference(destination), source.Length);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ChangeCaseCommon<TConversion>(ReadOnlySpan<char> source, Span<char> destination) where TConversion : struct
- {
- Debug.Assert(destination.Length >= source.Length);
- ChangeCaseCommon<TConversion>(ref MemoryMarshal.GetReference(source), ref MemoryMarshal.GetReference(destination), source.Length);
- }
-
- private unsafe void ChangeCaseCommon<TConversion>(ref char source, ref char destination, int charCount) where TConversion : struct
- {
- Debug.Assert(typeof(TConversion) == typeof(ToUpperConversion) || typeof(TConversion) == typeof(ToLowerConversion));
- bool toUpper = typeof(TConversion) == typeof(ToUpperConversion); // JIT will treat this as a constant in release builds
-
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(charCount >= 0);
-
- if (charCount == 0)
- {
- goto Return;
- }
-
- fixed (char* pSource = &source)
- fixed (char* pDestination = &destination)
- {
- nuint currIdx = 0; // in chars
-
- if (IsAsciiCasingSameAsInvariant)
- {
- // Read 4 chars (two 32-bit integers) at a time
-
- if (charCount >= 4)
- {
- nuint lastIndexWhereCanReadFourChars = (uint)charCount - 4;
- do
- {
- // This is a mostly branchless case change routine. Generally speaking, we assume that the majority
- // of input is ASCII, so the 'if' checks below should normally evaluate to false. However, within
- // the ASCII data, we expect that characters of either case might be about equally distributed, so
- // we want the case change operation itself to be branchless. This gives optimal performance in the
- // common case. We also expect that developers aren't passing very long (16+ character) strings into
- // this method, so we won't bother vectorizing until data shows us that it's worthwhile to do so.
-
- uint tempValue = Unsafe.ReadUnaligned<uint>(pSource + currIdx);
- if (!Utf16Utility.AllCharsInUInt32AreAscii(tempValue))
- {
- goto NonAscii;
- }
- tempValue = (toUpper) ? Utf16Utility.ConvertAllAsciiCharsInUInt32ToUppercase(tempValue) : Utf16Utility.ConvertAllAsciiCharsInUInt32ToLowercase(tempValue);
- Unsafe.WriteUnaligned<uint>(pDestination + currIdx, tempValue);
-
- tempValue = Unsafe.ReadUnaligned<uint>(pSource + currIdx + 2);
- if (!Utf16Utility.AllCharsInUInt32AreAscii(tempValue))
- {
- goto NonAsciiSkipTwoChars;
- }
- tempValue = (toUpper) ? Utf16Utility.ConvertAllAsciiCharsInUInt32ToUppercase(tempValue) : Utf16Utility.ConvertAllAsciiCharsInUInt32ToLowercase(tempValue);
- Unsafe.WriteUnaligned<uint>(pDestination + currIdx + 2, tempValue);
- currIdx += 4;
- } while (currIdx <= lastIndexWhereCanReadFourChars);
-
- // At this point, there are fewer than 4 characters remaining to convert.
- Debug.Assert((uint)charCount - currIdx < 4);
- }
-
- // If there are 2 or 3 characters left to convert, we'll convert 2 of them now.
- if ((charCount & 2) != 0)
- {
- uint tempValue = Unsafe.ReadUnaligned<uint>(pSource + currIdx);
- if (!Utf16Utility.AllCharsInUInt32AreAscii(tempValue))
- {
- goto NonAscii;
- }
- tempValue = (toUpper) ? Utf16Utility.ConvertAllAsciiCharsInUInt32ToUppercase(tempValue) : Utf16Utility.ConvertAllAsciiCharsInUInt32ToLowercase(tempValue);
- Unsafe.WriteUnaligned<uint>(pDestination + currIdx, tempValue);
- currIdx += 2;
- }
-
- // If there's a single character left to convert, do it now.
- if ((charCount & 1) != 0)
- {
- uint tempValue = pSource[currIdx];
- if (tempValue > 0x7Fu)
- {
- goto NonAscii;
- }
- tempValue = (toUpper) ? Utf16Utility.ConvertAllAsciiCharsInUInt32ToUppercase(tempValue) : Utf16Utility.ConvertAllAsciiCharsInUInt32ToLowercase(tempValue);
- pDestination[currIdx] = (char)tempValue;
- }
-
- // And we're finished!
-
- goto Return;
-
- // If we reached this point, we found non-ASCII data.
- // Fall back down the p/invoke code path.
-
- NonAsciiSkipTwoChars:
- currIdx += 2;
-
- NonAscii:
- Debug.Assert(currIdx < (uint)charCount, "We somehow read past the end of the buffer.");
- charCount -= (int)currIdx;
- }
-
- // We encountered non-ASCII data and therefore can't perform invariant case conversion; or the requested culture
- // has a case conversion that's different from the invariant culture, even for ASCII data (e.g., tr-TR converts
- // 'i' (U+0069) to Latin Capital Letter I With Dot Above (U+0130)).
-
- ChangeCase(pSource + currIdx, charCount, pDestination + currIdx, charCount, toUpper);
- }
-
- Return:
- return;
- }
-
- private unsafe string ChangeCaseCommon<TConversion>(string source) where TConversion : struct
- {
- Debug.Assert(typeof(TConversion) == typeof(ToUpperConversion) || typeof(TConversion) == typeof(ToLowerConversion));
- bool toUpper = typeof(TConversion) == typeof(ToUpperConversion); // JIT will treat this as a constant in release builds
-
- Debug.Assert(!GlobalizationMode.Invariant);
- Debug.Assert(source != null);
-
- // If the string is empty, we're done.
- if (source.Length == 0)
- {
- return string.Empty;
- }
-
- fixed (char* pSource = source)
- {
- nuint currIdx = 0; // in chars
-
- // If this culture's casing for ASCII is the same as invariant, try to take
- // a fast path that'll work in managed code and ASCII rather than calling out
- // to the OS for culture-aware casing.
- if (IsAsciiCasingSameAsInvariant)
- {
- // Read 2 chars (one 32-bit integer) at a time
-
- if (source.Length >= 2)
- {
- nuint lastIndexWhereCanReadTwoChars = (uint)source.Length - 2;
- do
- {
- // See the comments in ChangeCaseCommon<TConversion>(ROS<char>, Span<char>) for a full explanation of the below code.
-
- uint tempValue = Unsafe.ReadUnaligned<uint>(pSource + currIdx);
- if (!Utf16Utility.AllCharsInUInt32AreAscii(tempValue))
- {
- goto NotAscii;
- }
- if ((toUpper) ? Utf16Utility.UInt32ContainsAnyLowercaseAsciiChar(tempValue) : Utf16Utility.UInt32ContainsAnyUppercaseAsciiChar(tempValue))
- {
- goto AsciiMustChangeCase;
- }
-
- currIdx += 2;
- } while (currIdx <= lastIndexWhereCanReadTwoChars);
- }
-
- // If there's a single character left to convert, do it now.
- if ((source.Length & 1) != 0)
- {
- uint tempValue = pSource[currIdx];
- if (tempValue > 0x7Fu)
- {
- goto NotAscii;
- }
- if ((toUpper) ? ((tempValue - 'a') <= (uint)('z' - 'a')) : ((tempValue - 'A') <= (uint)('Z' - 'A')))
- {
- goto AsciiMustChangeCase;
- }
- }
-
- // We got through all characters without finding anything that needed to change - done!
- return source;
-
- AsciiMustChangeCase:
- {
- // We reached ASCII data that requires a case change.
- // This will necessarily allocate a new string, but let's try to stay within the managed (non-localization tables)
- // conversion code path if we can.
-
- string result = string.FastAllocateString(source.Length); // changing case uses simple folding: doesn't change UTF-16 code unit count
-
- // copy existing known-good data into the result
- Span<char> resultSpan = new Span<char>(ref result.GetRawStringData(), result.Length);
- source.AsSpan(0, (int)currIdx).CopyTo(resultSpan);
-
- // and re-run the fast span-based logic over the remainder of the data
- ChangeCaseCommon<TConversion>(source.AsSpan((int)currIdx), resultSpan.Slice((int)currIdx));
- return result;
- }
- }
-
- NotAscii:
- {
- // We reached non-ASCII data *or* the requested culture doesn't map ASCII data the same way as the invariant culture.
- // In either case we need to fall back to the localization tables.
-
- string result = string.FastAllocateString(source.Length); // changing case uses simple folding: doesn't change UTF-16 code unit count
-
- if (currIdx > 0)
- {
- // copy existing known-good data into the result
- Span<char> resultSpan = new Span<char>(ref result.GetRawStringData(), result.Length);
- source.AsSpan(0, (int)currIdx).CopyTo(resultSpan);
- }
-
- // and run the culture-aware logic over the remainder of the data
- fixed (char* pResult = result)
- {
- ChangeCase(pSource + currIdx, source.Length - (int)currIdx, pResult + currIdx, result.Length - (int)currIdx, toUpper);
- }
- return result;
- }
- }
- }
-
- internal static unsafe string ToLowerAsciiInvariant(string s)
- {
- if (s.Length == 0)
- {
- return string.Empty;
- }
-
- fixed (char* pSource = s)
- {
- int i = 0;
- while (i < s.Length)
- {
- if ((uint)(pSource[i] - 'A') <= (uint)('Z' - 'A'))
- {
- break;
- }
- i++;
- }
-
- if (i >= s.Length)
- {
- return s;
- }
-
- string result = string.FastAllocateString(s.Length);
- fixed (char* pResult = result)
- {
- for (int j = 0; j < i; j++)
- {
- pResult[j] = pSource[j];
- }
-
- pResult[i] = (char)(pSource[i] | 0x20);
- i++;
-
- while (i < s.Length)
- {
- pResult[i] = ToLowerAsciiInvariant(pSource[i]);
- i++;
- }
- }
-
- return result;
- }
- }
-
- internal static void ToLowerAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
- {
- Debug.Assert(destination.Length >= source.Length);
-
- for (int i = 0; i < source.Length; i++)
- {
- destination[i] = ToLowerAsciiInvariant(source[i]);
- }
- }
-
- private static unsafe string ToUpperAsciiInvariant(string s)
- {
- if (s.Length == 0)
- {
- return string.Empty;
- }
-
- fixed (char* pSource = s)
- {
- int i = 0;
- while (i < s.Length)
- {
- if ((uint)(pSource[i] - 'a') <= (uint)('z' - 'a'))
- {
- break;
- }
- i++;
- }
-
- if (i >= s.Length)
- {
- return s;
- }
-
- string result = string.FastAllocateString(s.Length);
- fixed (char* pResult = result)
- {
- for (int j = 0; j < i; j++)
- {
- pResult[j] = pSource[j];
- }
-
- pResult[i] = (char)(pSource[i] & ~0x20);
- i++;
-
- while (i < s.Length)
- {
- pResult[i] = ToUpperAsciiInvariant(pSource[i]);
- i++;
- }
- }
-
- return result;
- }
- }
-
- internal static void ToUpperAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
- {
- Debug.Assert(destination.Length >= source.Length);
-
- for (int i = 0; i < source.Length; i++)
- {
- destination[i] = ToUpperAsciiInvariant(source[i]);
- }
- }
-
- private static char ToLowerAsciiInvariant(char c)
- {
- if ((uint)(c - 'A') <= (uint)('Z' - 'A'))
- {
- c = (char)(c | 0x20);
- }
- return c;
- }
-
- /// <summary>
- /// Converts the character or string to upper case. Certain locales
- /// have different casing semantics from the file systems in Win32.
- /// </summary>
- public virtual char ToUpper(char c)
- {
- if (GlobalizationMode.Invariant || (IsAscii(c) && IsAsciiCasingSameAsInvariant))
- {
- return ToUpperAsciiInvariant(c);
- }
-
- return ChangeCase(c, toUpper: true);
- }
-
- public virtual string ToUpper(string str)
- {
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- if (GlobalizationMode.Invariant)
- {
- return ToUpperAsciiInvariant(str);
- }
-
- return ChangeCaseCommon<ToUpperConversion>(str);
- }
-
- internal static char ToUpperAsciiInvariant(char c)
- {
- if ((uint)(c - 'a') <= (uint)('z' - 'a'))
- {
- c = (char)(c & ~0x20);
- }
- return c;
- }
-
- private static bool IsAscii(char c) => c < 0x80;
-
- private bool IsAsciiCasingSameAsInvariant
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- if (_isAsciiCasingSameAsInvariant == Tristate.NotInitialized)
- {
- PopulateIsAsciiCasingSameAsInvariant();
- }
-
- Debug.Assert(_isAsciiCasingSameAsInvariant == Tristate.True || _isAsciiCasingSameAsInvariant == Tristate.False);
- return _isAsciiCasingSameAsInvariant == Tristate.True;
- }
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private void PopulateIsAsciiCasingSameAsInvariant()
- {
- bool compareResult = CultureInfo.GetCultureInfo(_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", CompareOptions.IgnoreCase) == 0;
- _isAsciiCasingSameAsInvariant = (compareResult) ? Tristate.True : Tristate.False;
- }
-
- /// <summary>
- /// Returns true if the dominant direction of text and UI such as the
- /// relative position of buttons and scroll bars
- /// </summary>
- public bool IsRightToLeft => _cultureData.IsRightToLeft;
-
- public override bool Equals(object? obj)
- {
- return obj is TextInfo otherTextInfo
- && CultureName.Equals(otherTextInfo.CultureName);
- }
-
- public override int GetHashCode() => CultureName.GetHashCode();
-
- public override string ToString()
- {
- return "TextInfo - " + _cultureData.CultureName;
- }
-
- /// <summary>
- /// Titlecasing refers to a casing practice wherein the first letter of a word is an uppercase letter
- /// and the rest of the letters are lowercase. The choice of which words to titlecase in headings
- /// and titles is dependent on language and local conventions. For example, "The Merry Wives of Windor"
- /// is the appropriate titlecasing of that play's name in English, with the word "of" not titlecased.
- /// In German, however, the title is "Die lustigen Weiber von Windsor," and both "lustigen" and "von"
- /// are not titlecased. In French even fewer words are titlecased: "Les joyeuses commeres de Windsor."
- ///
- /// Moreover, the determination of what actually constitutes a word is language dependent, and this can
- /// influence which letter or letters of a "word" are uppercased when titlecasing strings. For example
- /// "l'arbre" is considered two words in French, whereas "can't" is considered one word in English.
- /// </summary>
- public unsafe string ToTitleCase(string str)
- {
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- if (str.Length == 0)
- {
- return str;
- }
-
- StringBuilder result = new StringBuilder();
- string? lowercaseData = null;
- // Store if the current culture is Dutch (special case)
- bool isDutchCulture = CultureName.StartsWith("nl-", StringComparison.OrdinalIgnoreCase);
-
- for (int i = 0; i < str.Length; i++)
- {
- int charLen;
- UnicodeCategory charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen);
- if (char.CheckLetter(charType))
- {
- // Special case to check for Dutch specific titlecasing with "IJ" characters
- // at the beginning of a word
- if (isDutchCulture && i < str.Length - 1 && (str[i] == 'i' || str[i] == 'I') && (str[i + 1] == 'j' || str[i + 1] == 'J'))
- {
- result.Append("IJ");
- i += 2;
- }
- else
- {
- // Do the titlecasing for the first character of the word.
- i = AddTitlecaseLetter(ref result, ref str, i, charLen) + 1;
- }
-
- // Convert the characters until the end of the this word
- // to lowercase.
- int lowercaseStart = i;
-
- // Use hasLowerCase flag to prevent from lowercasing acronyms (like "URT", "USA", etc)
- // This is in line with Word 2000 behavior of titlecasing.
- bool hasLowerCase = (charType == UnicodeCategory.LowercaseLetter);
-
- // Use a loop to find all of the other letters following this letter.
- while (i < str.Length)
- {
- charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen);
- if (IsLetterCategory(charType))
- {
- if (charType == UnicodeCategory.LowercaseLetter)
- {
- hasLowerCase = true;
- }
- i += charLen;
- }
- else if (str[i] == '\'')
- {
- i++;
- if (hasLowerCase)
- {
- if (lowercaseData == null)
- {
- lowercaseData = ToLower(str);
- }
- result.Append(lowercaseData, lowercaseStart, i - lowercaseStart);
- }
- else
- {
- result.Append(str, lowercaseStart, i - lowercaseStart);
- }
- lowercaseStart = i;
- hasLowerCase = true;
- }
- else if (!IsWordSeparator(charType))
- {
- // This category is considered to be part of the word.
- // This is any category that is marked as false in wordSeprator array.
- i += charLen;
- }
- else
- {
- // A word separator. Break out of the loop.
- break;
- }
- }
-
- int count = i - lowercaseStart;
-
- if (count > 0)
- {
- if (hasLowerCase)
- {
- if (lowercaseData == null)
- {
- lowercaseData = ToLower(str);
- }
- result.Append(lowercaseData, lowercaseStart, count);
- }
- else
- {
- result.Append(str, lowercaseStart, count);
- }
- }
-
- if (i < str.Length)
- {
- // not a letter, just append it
- i = AddNonLetter(ref result, ref str, i, charLen);
- }
- }
- else
- {
- // not a letter, just append it
- i = AddNonLetter(ref result, ref str, i, charLen);
- }
- }
- return result.ToString();
- }
-
- private static int AddNonLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
- {
- Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddNonLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!");
- if (charLen == 2)
- {
- // Surrogate pair
- result.Append(input[inputIndex++]);
- result.Append(input[inputIndex]);
- }
- else
- {
- result.Append(input[inputIndex]);
- }
- return inputIndex;
- }
-
- private int AddTitlecaseLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
- {
- Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!");
-
- if (charLen == 2)
- {
- // for surrogate pairs do a ToUpper operation on the substring
- ReadOnlySpan<char> src = input.AsSpan(inputIndex, 2);
- if (GlobalizationMode.Invariant)
- {
- result.Append(src); // surrogate pair in invariant mode, so changing case is a nop
- }
- else
- {
- Span<char> dst = stackalloc char[2];
- ChangeCaseToUpper(src, dst);
- result.Append(dst);
- }
- inputIndex++;
- }
- else
- {
- switch (input[inputIndex])
- {
- // For AppCompat, the Titlecase Case Mapping data from NDP 2.0 is used below.
- case (char)0x01C4: // DZ with Caron -> Dz with Caron
- case (char)0x01C5: // Dz with Caron -> Dz with Caron
- case (char)0x01C6: // dz with Caron -> Dz with Caron
- result.Append((char)0x01C5);
- break;
- case (char)0x01C7: // LJ -> Lj
- case (char)0x01C8: // Lj -> Lj
- case (char)0x01C9: // lj -> Lj
- result.Append((char)0x01C8);
- break;
- case (char)0x01CA: // NJ -> Nj
- case (char)0x01CB: // Nj -> Nj
- case (char)0x01CC: // nj -> Nj
- result.Append((char)0x01CB);
- break;
- case (char)0x01F1: // DZ -> Dz
- case (char)0x01F2: // Dz -> Dz
- case (char)0x01F3: // dz -> Dz
- result.Append((char)0x01F2);
- break;
- default:
- result.Append(ToUpper(input[inputIndex]));
- break;
- }
- }
- return inputIndex;
- }
-
- // Used in ToTitleCase():
- // When we find a starting letter, the following array decides if a category should be
- // considered as word seprator or not.
- private const int c_wordSeparatorMask =
- /* false */ (0 << 0) | // UppercaseLetter = 0,
- /* false */ (0 << 1) | // LowercaseLetter = 1,
- /* false */ (0 << 2) | // TitlecaseLetter = 2,
- /* false */ (0 << 3) | // ModifierLetter = 3,
- /* false */ (0 << 4) | // OtherLetter = 4,
- /* false */ (0 << 5) | // NonSpacingMark = 5,
- /* false */ (0 << 6) | // SpacingCombiningMark = 6,
- /* false */ (0 << 7) | // EnclosingMark = 7,
- /* false */ (0 << 8) | // DecimalDigitNumber = 8,
- /* false */ (0 << 9) | // LetterNumber = 9,
- /* false */ (0 << 10) | // OtherNumber = 10,
- /* true */ (1 << 11) | // SpaceSeparator = 11,
- /* true */ (1 << 12) | // LineSeparator = 12,
- /* true */ (1 << 13) | // ParagraphSeparator = 13,
- /* true */ (1 << 14) | // Control = 14,
- /* true */ (1 << 15) | // Format = 15,
- /* false */ (0 << 16) | // Surrogate = 16,
- /* false */ (0 << 17) | // PrivateUse = 17,
- /* true */ (1 << 18) | // ConnectorPunctuation = 18,
- /* true */ (1 << 19) | // DashPunctuation = 19,
- /* true */ (1 << 20) | // OpenPunctuation = 20,
- /* true */ (1 << 21) | // ClosePunctuation = 21,
- /* true */ (1 << 22) | // InitialQuotePunctuation = 22,
- /* true */ (1 << 23) | // FinalQuotePunctuation = 23,
- /* true */ (1 << 24) | // OtherPunctuation = 24,
- /* true */ (1 << 25) | // MathSymbol = 25,
- /* true */ (1 << 26) | // CurrencySymbol = 26,
- /* true */ (1 << 27) | // ModifierSymbol = 27,
- /* true */ (1 << 28) | // OtherSymbol = 28,
- /* false */ (0 << 29); // OtherNotAssigned = 29;
-
- private static bool IsWordSeparator(UnicodeCategory category)
- {
- return (c_wordSeparatorMask & (1 << (int)category)) != 0;
- }
-
- private static bool IsLetterCategory(UnicodeCategory uc)
- {
- return uc == UnicodeCategory.UppercaseLetter
- || uc == UnicodeCategory.LowercaseLetter
- || uc == UnicodeCategory.TitlecaseLetter
- || uc == UnicodeCategory.ModifierLetter
- || uc == UnicodeCategory.OtherLetter;
- }
-
- // A dummy struct that is used for 'ToUpper' in generic parameters
- private readonly struct ToUpperConversion { }
-
- // A dummy struct that is used for 'ToLower' in generic parameters
- private readonly struct ToLowerConversion { }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
deleted file mode 100644
index 96ecea765de..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- /// <summary>
- /// ThaiBuddhistCalendar is based on Gregorian calendar.
- /// Its year value has an offset to the Gregorain calendar.
- /// </summary>
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 0001/01/01 9999/12/31
- /// Thai 0544/01/01 10542/12/31
- /// </remarks>
- public class ThaiBuddhistCalendar : Calendar
- {
- private static readonly EraInfo[] s_thaiBuddhistEraInfo = new EraInfo[]
- {
- new EraInfo(1, 1, 1, 1, -543, 544, GregorianCalendar.MaxYear + 543) // era #, start year/month/day, yearOffset, minEraYear
- };
-
- public const int ThaiBuddhistEra = 1;
-
- private readonly GregorianCalendarHelper _helper;
-
- public override DateTime MinSupportedDateTime => DateTime.MinValue;
-
- public override DateTime MaxSupportedDateTime => DateTime.MaxValue;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.SolarCalendar;
-
- public ThaiBuddhistCalendar()
- {
- _helper = new GregorianCalendarHelper(this, s_thaiBuddhistEraInfo);
- }
-
- internal override CalendarId ID => CalendarId.THAI;
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- return _helper.AddMonths(time, months);
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return _helper.AddYears(time, years);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- return _helper.GetDaysInMonth(year, month, era);
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- return _helper.GetDaysInYear(year, era);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return _helper.GetDayOfMonth(time);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return _helper.GetDayOfWeek(time);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return _helper.GetDayOfYear(time);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- return _helper.GetMonthsInYear(year, era);
- }
-
- public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
- {
- return _helper.GetWeekOfYear(time, rule, firstDayOfWeek);
- }
-
- public override int GetEra(DateTime time)
- {
- return _helper.GetEra(time);
- }
-
- public override int GetMonth(DateTime time)
- {
- return _helper.GetMonth(time);
- }
-
- public override int GetYear(DateTime time)
- {
- return _helper.GetYear(time);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- return _helper.IsLeapDay(year, month, day, era);
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- return _helper.IsLeapYear(year, era);
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- return _helper.GetLeapMonth(year, era);
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- return _helper.IsLeapMonth(year, month, era);
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- return _helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era);
- }
-
- public override int[] Eras => _helper.Eras;
-
- private const int DefaultTwoDigitYearMax = 2572;
-
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- VerifyWritable();
- if (value < 99 || value > _helper.MaxYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, 99, _helper.MaxYear));
- }
-
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
-
- return _helper.ToFourDigitYear(year, TwoDigitYearMax);
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
deleted file mode 100644
index 08ffc3269aa..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
+++ /dev/null
@@ -1,658 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers.Text;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace System.Globalization
-{
- internal static class TimeSpanFormat
- {
- internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: false);
- internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: true);
-
- /// <summary>Main method called from TimeSpan.ToString.</summary>
- internal static string Format(TimeSpan value, string? format, IFormatProvider? formatProvider)
- {
- if (string.IsNullOrEmpty(format))
- {
- return FormatC(value); // formatProvider ignored, as "c" is invariant
- }
-
- if (format.Length == 1)
- {
- char c = format[0];
-
- if (c == 'c' || (c | 0x20) == 't') // special-case to optimize the default TimeSpan format
- {
- return FormatC(value); // formatProvider ignored, as "c" is invariant
- }
-
- if ((c | 0x20) == 'g') // special-case to optimize the remaining 'g'/'G' standard formats
- {
- return FormatG(value, DateTimeFormatInfo.GetInstance(formatProvider), c == 'G' ? StandardFormat.G : StandardFormat.g);
- }
-
- throw new FormatException(SR.Format_InvalidString);
- }
-
- return StringBuilderCache.GetStringAndRelease(FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null));
- }
-
- /// <summary>Main method called from TimeSpan.TryFormat.</summary>
- internal static bool TryFormat(TimeSpan value, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? formatProvider)
- {
- if (format.Length == 0)
- {
- return TryFormatStandard(value, StandardFormat.C, null, destination, out charsWritten);
- }
-
- if (format.Length == 1)
- {
- char c = format[0];
- if (c == 'c' || ((c | 0x20) == 't'))
- {
- return TryFormatStandard(value, StandardFormat.C, null, destination, out charsWritten);
- }
- else
- {
- StandardFormat sf =
- c == 'g' ? StandardFormat.g :
- c == 'G' ? StandardFormat.G :
- throw new FormatException(SR.Format_InvalidString);
- return TryFormatStandard(value, sf, DateTimeFormatInfo.GetInstance(formatProvider).DecimalSeparator, destination, out charsWritten);
- }
- }
-
- StringBuilder sb = FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null);
-
- if (sb.Length <= destination.Length)
- {
- sb.CopyTo(0, destination, sb.Length);
- charsWritten = sb.Length;
- StringBuilderCache.Release(sb);
- return true;
- }
-
- charsWritten = 0;
- StringBuilderCache.Release(sb);
- return false;
- }
-
- internal static string FormatC(TimeSpan value)
- {
- Span<char> destination = stackalloc char[26]; // large enough for any "c" TimeSpan
- TryFormatStandard(value, StandardFormat.C, null, destination, out int charsWritten);
- return new string(destination.Slice(0, charsWritten));
- }
-
- private static string FormatG(TimeSpan value, DateTimeFormatInfo dtfi, StandardFormat format)
- {
- string decimalSeparator = dtfi.DecimalSeparator;
- int maxLength = 25 + decimalSeparator.Length; // large enough for any "g"/"G" TimeSpan
- Span<char> destination = maxLength < 128 ?
- stackalloc char[maxLength] :
- new char[maxLength]; // the chances of needing this case are almost 0, as DecimalSeparator.Length will basically always == 1
- TryFormatStandard(value, format, decimalSeparator, destination, out int charsWritten);
- return new string(destination.Slice(0, charsWritten));
- }
-
- private enum StandardFormat { C, G, g }
-
- private static bool TryFormatStandard(TimeSpan value, StandardFormat format, string? decimalSeparator, Span<char> destination, out int charsWritten)
- {
- Debug.Assert(format == StandardFormat.C || format == StandardFormat.G || format == StandardFormat.g);
-
- // First, calculate how large an output buffer is needed to hold the entire output.
- int requiredOutputLength = 8; // start with "hh:mm:ss" and adjust as necessary
-
- uint fraction;
- ulong totalSecondsRemaining;
- {
- // Turn this into a non-negative TimeSpan if possible.
- long ticks = value.Ticks;
- if (ticks < 0)
- {
- requiredOutputLength = 9; // requiredOutputLength + 1 for the leading '-' sign
- ticks = -ticks;
- if (ticks < 0)
- {
- Debug.Assert(ticks == long.MinValue /* -9223372036854775808 */);
-
- // We computed these ahead of time; they're straight from the decimal representation of Int64.MinValue.
- fraction = 4775808;
- totalSecondsRemaining = 922337203685;
- goto AfterComputeFraction;
- }
- }
-
- totalSecondsRemaining = Math.DivRem((ulong)ticks, TimeSpan.TicksPerSecond, out ulong fraction64);
- fraction = (uint)fraction64;
- }
-
- AfterComputeFraction:
- // Only write out the fraction if it's non-zero, and in that
- // case write out the entire fraction (all digits).
- Debug.Assert(fraction < 10_000_000);
- int fractionDigits = 0;
- switch (format)
- {
- case StandardFormat.C:
- // "c": Write out a fraction only if it's non-zero, and write out all 7 digits of it.
- if (fraction != 0)
- {
- fractionDigits = DateTimeFormat.MaxSecondsFractionDigits;
- requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
- }
- break;
-
- case StandardFormat.G:
- // "G": Write out a fraction regardless of whether it's 0, and write out all 7 digits of it.
- fractionDigits = DateTimeFormat.MaxSecondsFractionDigits;
- requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
- break;
-
- default:
- // "g": Write out a fraction only if it's non-zero, and write out only the most significant digits.
- Debug.Assert(format == StandardFormat.g);
- if (fraction != 0)
- {
- fractionDigits = DateTimeFormat.MaxSecondsFractionDigits - FormattingHelpers.CountDecimalTrailingZeros(fraction, out fraction);
- requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
- }
- break;
- }
-
- ulong totalMinutesRemaining = 0, seconds = 0;
- if (totalSecondsRemaining > 0)
- {
- // Only compute minutes if the TimeSpan has an absolute value of >= 1 minute.
- totalMinutesRemaining = Math.DivRem(totalSecondsRemaining, 60 /* seconds per minute */, out seconds);
- Debug.Assert(seconds < 60);
- }
-
- ulong totalHoursRemaining = 0, minutes = 0;
- if (totalMinutesRemaining > 0)
- {
- // Only compute hours if the TimeSpan has an absolute value of >= 1 hour.
- totalHoursRemaining = Math.DivRem(totalMinutesRemaining, 60 /* minutes per hour */, out minutes);
- Debug.Assert(minutes < 60);
- }
-
- // At this point, we can switch over to 32-bit DivRem since the data has shrunk far enough.
- Debug.Assert(totalHoursRemaining <= uint.MaxValue);
-
- uint days = 0, hours = 0;
- if (totalHoursRemaining > 0)
- {
- // Only compute days if the TimeSpan has an absolute value of >= 1 day.
- days = Math.DivRem((uint)totalHoursRemaining, 24 /* hours per day */, out hours);
- Debug.Assert(hours < 24);
- }
-
- int hourDigits = 2;
- if (format == StandardFormat.g && hours < 10)
- {
- // "g": Only writing a one-digit hour, rather than expected two-digit hour
- hourDigits = 1;
- requiredOutputLength--;
- }
-
- int dayDigits = 0;
- if (days > 0)
- {
- dayDigits = FormattingHelpers.CountDigits(days);
- Debug.Assert(dayDigits <= 8);
- requiredOutputLength += dayDigits + 1; // for the leading "d."
- }
- else if (format == StandardFormat.G)
- {
- // "G": has a leading "0:" if days is 0
- requiredOutputLength += 2;
- dayDigits = 1;
- }
-
- if (destination.Length < requiredOutputLength)
- {
- charsWritten = 0;
- return false;
- }
-
- // Write leading '-' if necessary
- int idx = 0;
- if (value.Ticks < 0)
- {
- destination[idx++] = '-';
- }
-
- // Write day and separator, if necessary
- if (dayDigits != 0)
- {
- WriteDigits(days, destination.Slice(idx, dayDigits));
- idx += dayDigits;
- destination[idx++] = format == StandardFormat.C ? '.' : ':';
- }
-
- // Write "[h]h:mm:ss
- Debug.Assert(hourDigits == 1 || hourDigits == 2);
- if (hourDigits == 2)
- {
- WriteTwoDigits(hours, destination.Slice(idx));
- idx += 2;
- }
- else
- {
- destination[idx++] = (char)('0' + hours);
- }
- destination[idx++] = ':';
- WriteTwoDigits((uint)minutes, destination.Slice(idx));
- idx += 2;
- destination[idx++] = ':';
- WriteTwoDigits((uint)seconds, destination.Slice(idx));
- idx += 2;
-
- // Write fraction and separator, if necessary
- if (fractionDigits != 0)
- {
- Debug.Assert(format == StandardFormat.C || decimalSeparator != null);
- if (format == StandardFormat.C)
- {
- destination[idx++] = '.';
- }
- else if (decimalSeparator!.Length == 1)
- {
- destination[idx++] = decimalSeparator[0];
- }
- else
- {
- decimalSeparator.AsSpan().CopyTo(destination);
- idx += decimalSeparator.Length;
- }
- WriteDigits(fraction, destination.Slice(idx, fractionDigits));
- idx += fractionDigits;
- }
-
- Debug.Assert(idx == requiredOutputLength);
- charsWritten = requiredOutputLength;
- return true;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void WriteTwoDigits(uint value, Span<char> buffer)
- {
- Debug.Assert(buffer.Length >= 2);
- uint temp = '0' + value;
- value /= 10;
- buffer[1] = (char)(temp - (value * 10));
- buffer[0] = (char)('0' + value);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void WriteDigits(uint value, Span<char> buffer)
- {
- Debug.Assert(buffer.Length > 0);
-
- for (int i = buffer.Length - 1; i >= 1; i--)
- {
- uint temp = '0' + value;
- value /= 10;
- buffer[i] = (char)(temp - (value * 10));
- }
-
- Debug.Assert(value < 10);
- buffer[0] = (char)('0' + value);
- }
-
- /// <summary>Format the TimeSpan instance using the specified format.</summary>
- private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, StringBuilder? result = null)
- {
- Debug.Assert(dtfi != null);
-
- bool resultBuilderIsPooled = false;
- if (result == null)
- {
- result = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
- resultBuilderIsPooled = true;
- }
-
- int day = (int)(value.Ticks / TimeSpan.TicksPerDay);
- long time = value.Ticks % TimeSpan.TicksPerDay;
-
- if (value.Ticks < 0)
- {
- day = -day;
- time = -time;
- }
- int hours = (int)(time / TimeSpan.TicksPerHour % 24);
- int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
- int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
- int fraction = (int)(time % TimeSpan.TicksPerSecond);
-
- long tmp = 0;
- int i = 0;
- int tokenLen;
-
- while (i < format.Length)
- {
- char ch = format[i];
- int nextChar;
- switch (ch)
- {
- case 'h':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 2)
- {
- goto default; // to release the builder and throw
- }
- DateTimeFormat.FormatDigits(result, hours, tokenLen);
- break;
- case 'm':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 2)
- {
- goto default; // to release the builder and throw
- }
- DateTimeFormat.FormatDigits(result, minutes, tokenLen);
- break;
- case 's':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 2)
- {
- goto default; // to release the builder and throw
- }
- DateTimeFormat.FormatDigits(result, seconds, tokenLen);
- break;
- case 'f':
- //
- // The fraction of a second in single-digit precision. The remaining digits are truncated.
- //
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
- {
- goto default; // to release the builder and throw
- }
-
- tmp = fraction;
- tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
- result.AppendSpanFormattable(tmp, DateTimeFormat.fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture);
- break;
- case 'F':
- //
- // Displays the most significant digit of the seconds fraction. Nothing is displayed if the digit is zero.
- //
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
- {
- goto default; // to release the builder and throw
- }
-
- tmp = fraction;
- tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
- int effectiveDigits = tokenLen;
- while (effectiveDigits > 0)
- {
- if (tmp % 10 == 0)
- {
- tmp /= 10;
- effectiveDigits--;
- }
- else
- {
- break;
- }
- }
- if (effectiveDigits > 0)
- {
- result.AppendSpanFormattable(tmp, DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture);
- }
- break;
- case 'd':
- //
- // tokenLen == 1 : Day as digits with no leading zero.
- // tokenLen == 2+: Day as digits with leading zero for single-digit days.
- //
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 8)
- {
- goto default; // to release the builder and throw
- }
-
- DateTimeFormat.FormatDigits(result, day, tokenLen, true);
- break;
- case '\'':
- case '\"':
- tokenLen = DateTimeFormat.ParseQuoteString(format, i, result);
- break;
- case '%':
- // Optional format character.
- // For example, format string "%d" will print day
- // Most of the cases, "%" can be ignored.
- nextChar = DateTimeFormat.ParseNextChar(format, i);
- // nextChar will be -1 if we already reach the end of the format string.
- // Besides, we will not allow "%%" appear in the pattern.
- if (nextChar >= 0 && nextChar != (int)'%')
- {
- char nextCharChar = (char)nextChar;
- StringBuilder origStringBuilder = FormatCustomized(value, MemoryMarshal.CreateReadOnlySpan<char>(ref nextCharChar, 1), dtfi, result);
- Debug.Assert(ReferenceEquals(origStringBuilder, result));
- tokenLen = 2;
- }
- else
- {
- //
- // This means that '%' is at the end of the format string or
- // "%%" appears in the format string.
- //
- goto default; // to release the builder and throw
- }
- break;
- case '\\':
- // Escaped character. Can be used to insert character into the format string.
- // For example, "\d" will insert the character 'd' into the string.
- //
- nextChar = DateTimeFormat.ParseNextChar(format, i);
- if (nextChar >= 0)
- {
- result.Append((char)nextChar);
- tokenLen = 2;
- }
- else
- {
- //
- // This means that '\' is at the end of the formatting string.
- //
- goto default; // to release the builder and throw
- }
- break;
- default:
- // Invalid format string
- if (resultBuilderIsPooled)
- {
- StringBuilderCache.Release(result);
- }
- throw new FormatException(SR.Format_InvalidString);
- }
- i += tokenLen;
- }
- return result;
- }
-
- internal struct FormatLiterals
- {
- internal string AppCompatLiteral;
- internal int dd;
- internal int hh;
- internal int mm;
- internal int ss;
- internal int ff;
-
- private string[] _literals;
-
- internal string Start => _literals[0];
- internal string DayHourSep => _literals[1];
- internal string HourMinuteSep => _literals[2];
- internal string MinuteSecondSep => _literals[3];
- internal string SecondFractionSep => _literals[4];
- internal string End => _literals[5];
-
- /* factory method for static invariant FormatLiterals */
- internal static FormatLiterals InitInvariant(bool isNegative)
- {
- FormatLiterals x = default;
- x._literals = new string[6];
- x._literals[0] = isNegative ? "-" : string.Empty;
- x._literals[1] = ".";
- x._literals[2] = ":";
- x._literals[3] = ":";
- x._literals[4] = ".";
- x._literals[5] = string.Empty;
- x.AppCompatLiteral = ":."; // MinuteSecondSep+SecondFractionSep;
- x.dd = 2;
- x.hh = 2;
- x.mm = 2;
- x.ss = 2;
- x.ff = DateTimeFormat.MaxSecondsFractionDigits;
- return x;
- }
-
- // For the "v1" TimeSpan localized patterns, the data is simply literal field separators with
- // the constants guaranteed to include DHMSF ordered greatest to least significant.
- // Once the data becomes more complex than this we will need to write a proper tokenizer for
- // parsing and formatting
- internal void Init(ReadOnlySpan<char> format, bool useInvariantFieldLengths)
- {
- dd = hh = mm = ss = ff = 0;
- _literals = new string[6];
- for (int i = 0; i < _literals.Length; i++)
- {
- _literals[i] = string.Empty;
- }
-
- StringBuilder sb = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
- bool inQuote = false;
- char quote = '\'';
- int field = 0;
-
- for (int i = 0; i < format.Length; i++)
- {
- switch (format[i])
- {
- case '\'':
- case '\"':
- if (inQuote && (quote == format[i]))
- {
- /* we were in a quote and found a matching exit quote, so we are outside a quote now */
- if (field >= 0 && field <= 5)
- {
- _literals[field] = sb.ToString();
- sb.Length = 0;
- inQuote = false;
- }
- else
- {
- Debug.Fail($"Unexpected field value: {field}");
- return; // how did we get here?
- }
- }
- else if (!inQuote)
- {
- /* we are at the start of a new quote block */
- quote = format[i];
- inQuote = true;
- }
- else
- {
- /* we were in a quote and saw the other type of quote character, so we are still in a quote */
- }
- break;
- case '%':
- Debug.Fail("Unexpected special token '%', Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- goto default;
- case '\\':
- if (!inQuote)
- {
- i++; /* skip next character that is escaped by this backslash or percent sign */
- break;
- }
- goto default;
- case 'd':
- if (!inQuote)
- {
- Debug.Assert((field == 0 && sb.Length == 0) || field == 1, "field == 0 || field == 1, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- field = 1; // DayHourSep
- dd++;
- }
- break;
- case 'h':
- if (!inQuote)
- {
- Debug.Assert((field == 1 && sb.Length == 0) || field == 2, "field == 1 || field == 2, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- field = 2; // HourMinuteSep
- hh++;
- }
- break;
- case 'm':
- if (!inQuote)
- {
- Debug.Assert((field == 2 && sb.Length == 0) || field == 3, "field == 2 || field == 3, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- field = 3; // MinuteSecondSep
- mm++;
- }
- break;
- case 's':
- if (!inQuote)
- {
- Debug.Assert((field == 3 && sb.Length == 0) || field == 4, "field == 3 || field == 4, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- field = 4; // SecondFractionSep
- ss++;
- }
- break;
- case 'f':
- case 'F':
- if (!inQuote)
- {
- Debug.Assert((field == 4 && sb.Length == 0) || field == 5, "field == 4 || field == 5, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- field = 5; // End
- ff++;
- }
- break;
- default:
- sb.Append(format[i]);
- break;
- }
- }
-
- Debug.Assert(field == 5);
- AppCompatLiteral = MinuteSecondSep + SecondFractionSep;
-
- Debug.Assert(0 < dd && dd < 3, "0 < dd && dd < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- Debug.Assert(0 < hh && hh < 3, "0 < hh && hh < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- Debug.Assert(0 < mm && mm < 3, "0 < mm && mm < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- Debug.Assert(0 < ss && ss < 3, "0 < ss && ss < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
- Debug.Assert(0 < ff && ff < 8, "0 < ff && ff < 8, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
-
- if (useInvariantFieldLengths)
- {
- dd = 2;
- hh = 2;
- mm = 2;
- ss = 2;
- ff = DateTimeFormat.MaxSecondsFractionDigits;
- }
- else
- {
- if (dd < 1 || dd > 2) dd = 2; // The DTFI property has a problem. let's try to make the best of the situation.
- if (hh < 1 || hh > 2) hh = 2;
- if (mm < 1 || mm > 2) mm = 2;
- if (ss < 1 || ss > 2) ss = 2;
- if (ff < 1 || ff > 7) ff = 7;
- }
- StringBuilderCache.Release(sb);
- }
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
deleted file mode 100644
index 0a2df773409..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
+++ /dev/null
@@ -1,1705 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Purpose: Used by TimeSpan to parse a time interval string.
-//
-// Standard Format:
-// -=-=-=-=-=-=-=-
-// "c": Constant format. [-][d'.']hh':'mm':'ss['.'fffffff]
-// Not culture sensitive. Default format (and null/empty format string) map to this format.
-//
-// "g": General format, short: [-][d':']h':'mm':'ss'.'FFFFFFF
-// Only print what's needed. Localized (if you want Invariant, pass in Invariant).
-// The fractional seconds separator is localized, equal to the culture's DecimalSeparator.
-//
-// "G": General format, long: [-]d':'hh':'mm':'ss'.'fffffff
-// Always print days and 7 fractional digits. Localized (if you want Invariant, pass in Invariant).
-// The fractional seconds separator is localized, equal to the culture's DecimalSeparator.
-//
-// * "TryParseTimeSpan" is the main method for Parse/TryParse
-//
-// - TimeSpanTokenizer.GetNextToken() is used to split the input string into number and literal tokens.
-// - TimeSpanRawInfo.ProcessToken() adds the next token into the parsing intermediary state structure
-// - ProcessTerminalState() uses the fully initialized TimeSpanRawInfo to find a legal parse match.
-// The terminal states are attempted as follows:
-// foreach (+InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern) try
-// 1 number => d
-// 2 numbers => h:m
-// 3 numbers => h:m:s | d.h:m | h:m:.f
-// 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f
-// 5 numbers => d.h:m:s.f
-//
-// Custom Format:
-// -=-=-=-=-=-=-=
-//
-// * "TryParseExactTimeSpan" is the main method for ParseExact/TryParseExact methods
-// * "TryParseExactMultipleTimeSpan" is the main method for ParseExact/TryparseExact
-// methods that take a string[] of formats
-//
-// - For single-letter formats "TryParseTimeSpan" is called (see above)
-// - For multi-letter formats "TryParseByFormat" is called
-// - TryParseByFormat uses helper methods (ParseExactLiteral, ParseExactDigits, etc)
-// which drive the underlying TimeSpanTokenizer. However, unlike standard formatting which
-// operates on whole-tokens, ParseExact operates at the character-level. As such,
-// TimeSpanTokenizer.NextChar and TimeSpanTokenizer.BackOne() are called directly.
-//
-////////////////////////////////////////////////////////////////////////////
-
-using System.Diagnostics;
-using System.Text;
-
-namespace System.Globalization
-{
- internal static class TimeSpanParse
- {
- private const int MaxFractionDigits = 7;
- private const int MaxDays = 10675199;
- private const int MaxHours = 23;
- private const int MaxMinutes = 59;
- private const int MaxSeconds = 59;
- private const int MaxFraction = 9999999;
-
- [Flags]
- private enum TimeSpanStandardStyles : byte
- {
- // Standard Format Styles
- None = 0x00000000,
- Invariant = 0x00000001, // Allow Invariant Culture
- Localized = 0x00000002, // Allow Localized Culture
- RequireFull = 0x00000004, // Require the input to be in DHMSF format
- Any = Invariant | Localized,
- }
-
- // TimeSpan Token Types
- private enum TTT : byte
- {
- None = 0, // None of the TimeSpanToken fields are set
- End = 1, // '\0'
- Num = 2, // Number
- Sep = 3, // literal
- NumOverflow = 4, // Number that overflowed
- }
-
- private ref struct TimeSpanToken
- {
- internal TTT _ttt;
- internal int _num; // Store the number that we are parsing (if any)
- internal int _zeroes; // Store the number of leading zeroes (if any)
- internal ReadOnlySpan<char> _sep; // Store the literal that we are parsing (if any)
-
- public TimeSpanToken(TTT type) : this(type, 0, 0, default) { }
-
- public TimeSpanToken(int number) : this(TTT.Num, number, 0, default) { }
-
- public TimeSpanToken(int number, int leadingZeroes) : this(TTT.Num, number, leadingZeroes, default) { }
-
- public TimeSpanToken(TTT type, int number, int leadingZeroes, ReadOnlySpan<char> separator)
- {
- _ttt = type;
- _num = number;
- _zeroes = leadingZeroes;
- _sep = separator;
- }
-
- public bool NormalizeAndValidateFraction()
- {
- Debug.Assert(_ttt == TTT.Num);
- Debug.Assert(_num > -1);
-
- if (_num == 0)
- return true;
-
- if (_zeroes == 0 && _num > MaxFraction)
- return false;
-
- int totalDigitsCount = ((int)Math.Floor(Math.Log10(_num))) + 1 + _zeroes;
-
- if (totalDigitsCount == MaxFractionDigits)
- {
- // Already normalized. no more action needed
- // .9999999 normalize to 9,999,999 ticks
- // .0000001 normalize to 1 ticks
- return true;
- }
-
- if (totalDigitsCount < MaxFractionDigits)
- {
- // normalize the fraction to the 7-digits
- // .999999 normalize to 9,999,990 ticks
- // .99999 normalize to 9,999,900 ticks
- // .000001 normalize to 10 ticks
- // .1 normalize to 1,000,000 ticks
-
- _num *= (int)Pow10(MaxFractionDigits - totalDigitsCount);
- return true;
- }
-
- // totalDigitsCount is greater then MaxFractionDigits, we'll need to do the rounding to 7-digits length
- // .00000001 normalized to 0 ticks
- // .00000005 normalized to 1 ticks
- // .09999999 normalize to 1,000,000 ticks
- // .099999999 normalize to 1,000,000 ticks
-
- Debug.Assert(_zeroes > 0); // Already validated that in the condition _zeroes == 0 && _num > MaxFraction
- _num = (int)Math.Round((double)_num / Pow10(totalDigitsCount - MaxFractionDigits), MidpointRounding.AwayFromZero);
- Debug.Assert(_num < MaxFraction);
-
- return true;
- }
- }
-
- private ref struct TimeSpanTokenizer
- {
- private readonly ReadOnlySpan<char> _value;
- private int _pos;
-
- internal TimeSpanTokenizer(ReadOnlySpan<char> input) : this(input, 0) { }
-
- internal TimeSpanTokenizer(ReadOnlySpan<char> input, int startPosition)
- {
- _value = input;
- _pos = startPosition;
- }
-
- /// <summary>Returns the next token in the input string</summary>
- /// <remarks>Used by the parsing routines that operate on standard-formats.</remarks>
- internal TimeSpanToken GetNextToken()
- {
- // Get the position of the next character to be processed. If there is no
- // next character, we're at the end.
- int pos = _pos;
- Debug.Assert(pos > -1);
- if (pos >= _value.Length)
- {
- return new TimeSpanToken(TTT.End);
- }
-
- // Now retrieve that character. If it's a digit, we're processing a number.
- int num = _value[pos] - '0';
- if ((uint)num <= 9)
- {
- int zeroes = 0;
- if (num == 0)
- {
- // Read all leading zeroes.
- zeroes = 1;
- while (true)
- {
- int digit;
- if (++_pos >= _value.Length || (uint)(digit = _value[_pos] - '0') > 9)
- {
- return new TimeSpanToken(TTT.Num, 0, zeroes, default);
- }
-
- if (digit == 0)
- {
- zeroes++;
- continue;
- }
-
- num = digit;
- break;
- }
- }
-
- // Continue to read as long as we're reading digits.
- while (++_pos < _value.Length)
- {
- int digit = _value[_pos] - '0';
- if ((uint)digit > 9)
- {
- break;
- }
-
- num = num * 10 + digit;
- if ((num & 0xF0000000) != 0) // Max limit we can support 268435455 which is FFFFFFF
- {
- return new TimeSpanToken(TTT.NumOverflow);
- }
- }
-
- return new TimeSpanToken(TTT.Num, num, zeroes, default);
- }
-
- // Otherwise, we're processing a separator, and we've already processed the first
- // character of it. Continue processing characters as long as they're not digits.
- int length = 1;
- while (true)
- {
- if (++_pos >= _value.Length || (uint)(_value[_pos] - '0') <= 9)
- {
- break;
- }
- length++;
- }
-
- // Return the separator.
- return new TimeSpanToken(TTT.Sep, 0, 0, _value.Slice(pos, length));
- }
-
- internal bool EOL => _pos >= (_value.Length - 1);
-
- internal void BackOne()
- {
- if (_pos > 0) --_pos;
- }
-
- internal char NextChar
- {
- get
- {
- int pos = ++_pos;
- return (uint)pos < (uint)_value.Length ?
- _value[pos] :
- (char)0;
- }
- }
- }
-
- /// <summary>Stores intermediary parsing state for the standard formats.</summary>
- private ref struct TimeSpanRawInfo
- {
- internal TimeSpanFormat.FormatLiterals PositiveLocalized
- {
- get
- {
- if (!_posLocInit)
- {
- _posLoc = default;
- _posLoc.Init(_fullPosPattern, false);
- _posLocInit = true;
- }
- return _posLoc;
- }
- }
-
- internal TimeSpanFormat.FormatLiterals NegativeLocalized
- {
- get
- {
- if (!_negLocInit)
- {
- _negLoc = default;
- _negLoc.Init(_fullNegPattern, false);
- _negLocInit = true;
- }
- return _negLoc;
- }
- }
-
- internal bool FullAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 5
- && _numCount == 4
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.DayHourSep)
- && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals3.EqualsOrdinal(pattern.AppCompatLiteral)
- && _literals4.EqualsOrdinal(pattern.End);
-
- internal bool PartialAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 4
- && _numCount == 3
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals2.EqualsOrdinal(pattern.AppCompatLiteral)
- && _literals3.EqualsOrdinal(pattern.End);
-
- /// <summary>DHMSF (all values matched)</summary>
- internal bool FullMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == MaxLiteralTokens
- && _numCount == MaxNumericTokens
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.DayHourSep)
- && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
- && _literals4.EqualsOrdinal(pattern.SecondFractionSep)
- && _literals5.EqualsOrdinal(pattern.End);
-
- /// <summary>D (no hours, minutes, seconds, or fractions)</summary>
- internal bool FullDMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 2
- && _numCount == 1
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.End);
-
- /// <summary>HM (no days, seconds, or fractions)</summary>
- internal bool FullHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 3
- && _numCount == 2
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals2.EqualsOrdinal(pattern.End);
-
- /// <summary>DHM (no seconds or fraction)</summary>
- internal bool FullDHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 4
- && _numCount == 3
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.DayHourSep)
- && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals3.EqualsOrdinal(pattern.End);
-
- /// <summary>HMS (no days or fraction)</summary>
- internal bool FullHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 4
- && _numCount == 3
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
- && _literals3.EqualsOrdinal(pattern.End);
-
- /// <summary>DHMS (no fraction)</summary>
- internal bool FullDHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 5
- && _numCount == 4
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.DayHourSep)
- && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
- && _literals4.EqualsOrdinal(pattern.End);
-
- /// <summary>HMSF (no days)</summary>
- internal bool FullHMSFMatch(TimeSpanFormat.FormatLiterals pattern) =>
- _sepCount == 5
- && _numCount == 4
- && _literals0.EqualsOrdinal(pattern.Start)
- && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
- && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
- && _literals3.EqualsOrdinal(pattern.SecondFractionSep)
- && _literals4.EqualsOrdinal(pattern.End);
-
- internal TTT _lastSeenTTT;
- internal int _tokenCount;
- internal int _sepCount;
- internal int _numCount;
-
- private TimeSpanFormat.FormatLiterals _posLoc;
- private TimeSpanFormat.FormatLiterals _negLoc;
- private bool _posLocInit;
- private bool _negLocInit;
- private string _fullPosPattern;
- private string _fullNegPattern;
-
- private const int MaxTokens = 11;
- private const int MaxLiteralTokens = 6;
- private const int MaxNumericTokens = 5;
-
- internal TimeSpanToken _numbers0, _numbers1, _numbers2, _numbers3, _numbers4; // MaxNumbericTokens = 5
- internal ReadOnlySpan<char> _literals0, _literals1, _literals2, _literals3, _literals4, _literals5; // MaxLiteralTokens=6
-
- internal void Init(DateTimeFormatInfo dtfi)
- {
- Debug.Assert(dtfi != null);
-
- _lastSeenTTT = TTT.None;
- _tokenCount = 0;
- _sepCount = 0;
- _numCount = 0;
-
- _fullPosPattern = dtfi.FullTimeSpanPositivePattern;
- _fullNegPattern = dtfi.FullTimeSpanNegativePattern;
- _posLocInit = false;
- _negLocInit = false;
- }
-
- internal bool ProcessToken(ref TimeSpanToken tok, ref TimeSpanResult result)
- {
- switch (tok._ttt)
- {
- case TTT.Num:
- if ((_tokenCount == 0 && !AddSep(default, ref result)) || !AddNum(tok, ref result))
- {
- return false;
- }
- break;
-
- case TTT.Sep:
- if (!AddSep(tok._sep, ref result))
- {
- return false;
- }
- break;
-
- case TTT.NumOverflow:
- return result.SetOverflowFailure();
-
- default:
- // Some unknown token or a repeat token type in the input
- return result.SetBadTimeSpanFailure();
- }
-
- _lastSeenTTT = tok._ttt;
- Debug.Assert(_tokenCount == (_sepCount + _numCount), "tokenCount == (SepCount + NumCount)");
- return true;
- }
-
- private bool AddSep(ReadOnlySpan<char> sep, ref TimeSpanResult result)
- {
- if (_sepCount >= MaxLiteralTokens || _tokenCount >= MaxTokens)
- {
- return result.SetBadTimeSpanFailure();
- }
-
- switch (_sepCount++)
- {
- case 0: _literals0 = sep; break;
- case 1: _literals1 = sep; break;
- case 2: _literals2 = sep; break;
- case 3: _literals3 = sep; break;
- case 4: _literals4 = sep; break;
- default: _literals5 = sep; break;
- }
-
- _tokenCount++;
- return true;
- }
- private bool AddNum(TimeSpanToken num, ref TimeSpanResult result)
- {
- if (_numCount >= MaxNumericTokens || _tokenCount >= MaxTokens)
- {
- return result.SetBadTimeSpanFailure();
- }
-
- switch (_numCount++)
- {
- case 0: _numbers0 = num; break;
- case 1: _numbers1 = num; break;
- case 2: _numbers2 = num; break;
- case 3: _numbers3 = num; break;
- default: _numbers4 = num; break;
- }
-
- _tokenCount++;
- return true;
- }
- }
-
- /// <summary>Store the result of the parsing.</summary>
- private ref struct TimeSpanResult
- {
- internal TimeSpan parsedTimeSpan;
- private readonly bool _throwOnFailure;
- private readonly ReadOnlySpan<char> _originalTimeSpanString;
-
- internal TimeSpanResult(bool throwOnFailure, ReadOnlySpan<char> originalTimeSpanString)
- {
- parsedTimeSpan = default;
- _throwOnFailure = throwOnFailure;
- _originalTimeSpanString = originalTimeSpanString;
- }
-
- internal bool SetNoFormatSpecifierFailure()
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- throw new FormatException(SR.Format_NoFormatSpecifier);
- }
-
- internal bool SetBadQuoteFailure(char failingCharacter)
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- throw new FormatException(SR.Format(SR.Format_BadQuote, failingCharacter));
- }
-
- internal bool SetInvalidStringFailure()
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- throw new FormatException(SR.Format_InvalidString);
- }
-
- internal bool SetArgumentNullFailure(string argumentName)
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- Debug.Assert(argumentName != null);
- throw new ArgumentNullException(argumentName, SR.ArgumentNull_String);
- }
-
- internal bool SetOverflowFailure()
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- throw new OverflowException(SR.Format(SR.Overflow_TimeSpanElementTooLarge, new string(_originalTimeSpanString)));
- }
-
- internal bool SetBadTimeSpanFailure()
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- throw new FormatException(SR.Format(SR.Format_BadTimeSpan, new string(_originalTimeSpanString)));
- }
-
- internal bool SetBadFormatSpecifierFailure(char? formatSpecifierCharacter = null)
- {
- if (!_throwOnFailure)
- {
- return false;
- }
-
- throw new FormatException(SR.Format(SR.Format_BadFormatSpecifier, formatSpecifierCharacter));
- }
- }
-
- internal static long Pow10(int pow)
- {
- return pow switch
- {
- 0 => 1,
- 1 => 10,
- 2 => 100,
- 3 => 1000,
- 4 => 10000,
- 5 => 100000,
- 6 => 1000000,
- 7 => 10000000,
- _ => (long)Math.Pow(10, pow),
- };
- }
-
- private static bool TryTimeToTicks(bool positive, TimeSpanToken days, TimeSpanToken hours, TimeSpanToken minutes, TimeSpanToken seconds, TimeSpanToken fraction, out long result)
- {
- if (days._num > MaxDays ||
- hours._num > MaxHours ||
- minutes._num > MaxMinutes ||
- seconds._num > MaxSeconds ||
- !fraction.NormalizeAndValidateFraction())
- {
- result = 0;
- return false;
- }
-
- long ticks = ((long)days._num * 3600 * 24 + (long)hours._num * 3600 + (long)minutes._num * 60 + seconds._num) * 1000;
- if (ticks > InternalGlobalizationHelper.MaxMilliSeconds || ticks < InternalGlobalizationHelper.MinMilliSeconds)
- {
- result = 0;
- return false;
- }
-
- result = ticks * TimeSpan.TicksPerMillisecond + fraction._num;
- if (positive && result < 0)
- {
- result = 0;
- return false;
- }
-
- return true;
- }
-
- internal static TimeSpan Parse(ReadOnlySpan<char> input, IFormatProvider? formatProvider)
- {
- var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
- bool success = TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult);
- Debug.Assert(success, "Should have thrown on failure");
- return parseResult.parsedTimeSpan;
- }
-
- internal static bool TryParse(ReadOnlySpan<char> input, IFormatProvider? formatProvider, out TimeSpan result)
- {
- var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
-
- if (TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult))
- {
- result = parseResult.parsedTimeSpan;
- return true;
- }
-
- result = default;
- return false;
- }
-
- internal static TimeSpan ParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider? formatProvider, TimeSpanStyles styles)
- {
- var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
- bool success = TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult);
- Debug.Assert(success, "Should have thrown on failure");
- return parseResult.parsedTimeSpan;
- }
-
- internal static bool TryParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result)
- {
- var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
-
- if (TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult))
- {
- result = parseResult.parsedTimeSpan;
- return true;
- }
-
- result = default;
- return false;
- }
-
- internal static TimeSpan ParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles)
- {
- var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
- bool success = TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult);
- Debug.Assert(success, "Should have thrown on failure");
- return parseResult.parsedTimeSpan;
- }
-
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result)
- {
- var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
-
- if (TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult))
- {
- result = parseResult.parsedTimeSpan;
- return true;
- }
-
- result = default;
- return false;
- }
-
- /// <summary>Common private Parse method called by both Parse and TryParse.</summary>
- private static bool TryParseTimeSpan(ReadOnlySpan<char> input, TimeSpanStandardStyles style, IFormatProvider? formatProvider, ref TimeSpanResult result)
- {
- input = input.Trim();
- if (input.IsEmpty)
- {
- return result.SetBadTimeSpanFailure();
- }
-
- var tokenizer = new TimeSpanTokenizer(input);
-
- TimeSpanRawInfo raw = default;
- raw.Init(DateTimeFormatInfo.GetInstance(formatProvider));
-
- TimeSpanToken tok = tokenizer.GetNextToken();
-
- // The following loop will break out when we reach the end of the str or
- // when we can determine that the input is invalid.
- while (tok._ttt != TTT.End)
- {
- if (!raw.ProcessToken(ref tok, ref result))
- {
- return result.SetBadTimeSpanFailure();
- }
- tok = tokenizer.GetNextToken();
- }
- Debug.Assert(tokenizer.EOL);
-
- if (!ProcessTerminalState(ref raw, style, ref result))
- {
- return result.SetBadTimeSpanFailure();
- }
-
- return true;
- }
-
- /// <summary>
- /// Validate the terminal state of a standard format parse.
- /// Sets result.parsedTimeSpan on success.
- /// Calculates the resultant TimeSpan from the TimeSpanRawInfo.
- /// </summary>
- /// <remarks>
- /// try => +InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern
- /// 1) Verify Start matches
- /// 2) Verify End matches
- /// 3) 1 number => d
- /// 2 numbers => h:m
- /// 3 numbers => h:m:s | d.h:m | h:m:.f
- /// 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f
- /// 5 numbers => d.h:m:s.f
- /// </remarks>
- private static bool ProcessTerminalState(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
- {
- if (raw._lastSeenTTT == TTT.Num)
- {
- TimeSpanToken tok = default;
- tok._ttt = TTT.Sep;
- if (!raw.ProcessToken(ref tok, ref result))
- {
- return result.SetBadTimeSpanFailure();
- }
- }
-
- return raw._numCount switch
- {
- 1 => ProcessTerminal_D(ref raw, style, ref result),
- 2 => ProcessTerminal_HM(ref raw, style, ref result),
- 3 => ProcessTerminal_HM_S_D(ref raw, style, ref result),
- 4 => ProcessTerminal_HMS_F_D(ref raw, style, ref result),
- 5 => ProcessTerminal_DHMSF(ref raw, style, ref result),
- _ => result.SetBadTimeSpanFailure(),
- };
- }
-
- /// <summary>Validate the 5-number "Days.Hours:Minutes:Seconds.Fraction" terminal case.</summary>
- private static bool ProcessTerminal_DHMSF(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
- {
- if (raw._sepCount != 6)
- {
- return result.SetBadTimeSpanFailure();
- }
- Debug.Assert(raw._numCount == 5);
-
- bool inv = (style & TimeSpanStandardStyles.Invariant) != 0;
- bool loc = (style & TimeSpanStandardStyles.Localized) != 0;
- bool positive = false;
- bool match = false;
-
- if (inv)
- {
- if (raw.FullMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- match = true;
- positive = true;
- }
- if (!match && raw.FullMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- match = true;
- positive = false;
- }
- }
-
- if (loc)
- {
- if (!match && raw.FullMatch(raw.PositiveLocalized))
- {
- match = true;
- positive = true;
- }
- if (!match && raw.FullMatch(raw.NegativeLocalized))
- {
- match = true;
- positive = false;
- }
- }
-
- if (match)
- {
- long ticks;
-
- if (!TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, raw._numbers4, out ticks))
- {
- return result.SetOverflowFailure();
- }
-
- if (!positive)
- {
- ticks = -ticks;
- if (ticks > 0)
- {
- return result.SetOverflowFailure();
- }
- }
-
- result.parsedTimeSpan = new TimeSpan(ticks);
- return true;
- }
-
- return result.SetBadTimeSpanFailure();
- }
-
-
- /// <summary>
- /// Validate the ambiguous 4-number "Hours:Minutes:Seconds.Fraction", "Days.Hours:Minutes:Seconds",
- /// or "Days.Hours:Minutes:.Fraction" terminal case.
- /// </summary>
- private static bool ProcessTerminal_HMS_F_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
- {
- if (raw._sepCount != 5 || (style & TimeSpanStandardStyles.RequireFull) != 0)
- {
- return result.SetBadTimeSpanFailure();
- }
- Debug.Assert(raw._numCount == 4);
-
- bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
- bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
-
- long ticks = 0;
- bool positive = false, match = false, overflow = false;
- var zero = new TimeSpanToken(0);
-
- if (inv)
- {
- if (raw.FullHMSFMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- positive = true;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMSMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- positive = true;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullAppCompatMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- positive = true;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullHMSFMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- positive = false;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMSMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- positive = false;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullAppCompatMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- positive = false;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
- }
-
- if (loc)
- {
- if (!match && raw.FullHMSFMatch(raw.PositiveLocalized))
- {
- positive = true;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMSMatch(raw.PositiveLocalized))
- {
- positive = true;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullAppCompatMatch(raw.PositiveLocalized))
- {
- positive = true;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullHMSFMatch(raw.NegativeLocalized))
- {
- positive = false;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMSMatch(raw.NegativeLocalized))
- {
- positive = false;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullAppCompatMatch(raw.NegativeLocalized))
- {
- positive = false;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, raw._numbers3, out ticks);
- overflow = overflow || !match;
- }
- }
-
- if (match)
- {
- if (!positive)
- {
- ticks = -ticks;
- if (ticks > 0)
- {
- return result.SetOverflowFailure();
- }
- }
-
- result.parsedTimeSpan = new TimeSpan(ticks);
- return true;
- }
-
- return overflow ?
- result.SetOverflowFailure() : // we found at least one literal pattern match but the numbers just didn't fit
- result.SetBadTimeSpanFailure(); // we couldn't find a thing
- }
-
- /// <summary>Validate the ambiguous 3-number "Hours:Minutes:Seconds", "Days.Hours:Minutes", or "Hours:Minutes:.Fraction" terminal case.</summary>
- private static bool ProcessTerminal_HM_S_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
- {
- if (raw._sepCount != 4 || (style & TimeSpanStandardStyles.RequireFull) != 0)
- {
- return result.SetBadTimeSpanFailure();
- }
- Debug.Assert(raw._numCount == 3);
-
- bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
- bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
-
- bool positive = false, match = false, overflow = false;
- var zero = new TimeSpanToken(0);
- long ticks = 0;
-
- if (inv)
- {
- if (raw.FullHMSMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- positive = true;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- positive = true;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.PartialAppCompatMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- positive = true;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullHMSMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- positive = false;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- positive = false;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.PartialAppCompatMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- positive = false;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
- overflow = overflow || !match;
- }
- }
-
- if (loc)
- {
- if (!match && raw.FullHMSMatch(raw.PositiveLocalized))
- {
- positive = true;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMMatch(raw.PositiveLocalized))
- {
- positive = true;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.PartialAppCompatMatch(raw.PositiveLocalized))
- {
- positive = true;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullHMSMatch(raw.NegativeLocalized))
- {
- positive = false;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, raw._numbers2, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.FullDHMMatch(raw.NegativeLocalized))
- {
- positive = false;
- match = TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, zero, zero, out ticks);
- overflow = overflow || !match;
- }
-
- if (!match && raw.PartialAppCompatMatch(raw.NegativeLocalized))
- {
- positive = false;
- match = TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, raw._numbers2, out ticks);
- overflow = overflow || !match;
- }
- }
-
- if (match)
- {
- if (!positive)
- {
- ticks = -ticks;
- if (ticks > 0)
- {
- return result.SetOverflowFailure();
- }
- }
-
- result.parsedTimeSpan = new TimeSpan(ticks);
- return true;
- }
-
- return overflow ?
- result.SetOverflowFailure() : // we found at least one literal pattern match but the numbers just didn't fit
- result.SetBadTimeSpanFailure(); // we couldn't find a thing
- }
-
- /// <summary>Validate the 2-number "Hours:Minutes" terminal case.</summary>
- private static bool ProcessTerminal_HM(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
- {
- if (raw._sepCount != 3 || (style & TimeSpanStandardStyles.RequireFull) != 0)
- {
- return result.SetBadTimeSpanFailure();
- }
- Debug.Assert(raw._numCount == 2);
-
- bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
- bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
-
- bool positive = false, match = false;
-
- if (inv)
- {
- if (raw.FullHMMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- match = true;
- positive = true;
- }
-
- if (!match && raw.FullHMMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- match = true;
- positive = false;
- }
- }
-
- if (loc)
- {
- if (!match && raw.FullHMMatch(raw.PositiveLocalized))
- {
- match = true;
- positive = true;
- }
-
- if (!match && raw.FullHMMatch(raw.NegativeLocalized))
- {
- match = true;
- positive = false;
- }
- }
-
- if (match)
- {
- long ticks;
- var zero = new TimeSpanToken(0);
-
- if (!TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, zero, out ticks))
- {
- return result.SetOverflowFailure();
- }
-
- if (!positive)
- {
- ticks = -ticks;
- if (ticks > 0)
- {
- return result.SetOverflowFailure();
- }
- }
-
- result.parsedTimeSpan = new TimeSpan(ticks);
- return true;
- }
-
- return result.SetBadTimeSpanFailure();
- }
-
- /// <summary>Validate the 1-number "Days" terminal case.</summary>
- private static bool ProcessTerminal_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result)
- {
- if (raw._sepCount != 2 || (style & TimeSpanStandardStyles.RequireFull) != 0)
- {
- return result.SetBadTimeSpanFailure();
- }
- Debug.Assert(raw._numCount == 1);
-
- bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
- bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
-
- bool positive = false, match = false;
-
- if (inv)
- {
- if (raw.FullDMatch(TimeSpanFormat.PositiveInvariantFormatLiterals))
- {
- match = true;
- positive = true;
- }
-
- if (!match && raw.FullDMatch(TimeSpanFormat.NegativeInvariantFormatLiterals))
- {
- match = true;
- positive = false;
- }
- }
-
- if (loc)
- {
- if (!match && raw.FullDMatch(raw.PositiveLocalized))
- {
- match = true;
- positive = true;
- }
-
- if (!match && raw.FullDMatch(raw.NegativeLocalized))
- {
- match = true;
- positive = false;
- }
- }
-
- if (match)
- {
- long ticks;
- var zero = new TimeSpanToken(0);
-
- if (!TryTimeToTicks(positive, raw._numbers0, zero, zero, zero, zero, out ticks))
- {
- return result.SetOverflowFailure();
- }
-
- if (!positive)
- {
- ticks = -ticks;
- if (ticks > 0)
- {
- return result.SetOverflowFailure();
- }
- }
-
- result.parsedTimeSpan = new TimeSpan(ticks);
- return true;
- }
-
- return result.SetBadTimeSpanFailure();
- }
-
- /// <summary>Common private ParseExact method called by both ParseExact and TryParseExact.</summary>
- private static bool TryParseExactTimeSpan(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider? formatProvider, TimeSpanStyles styles, ref TimeSpanResult result)
- {
- if (format.Length == 0)
- {
- return result.SetBadFormatSpecifierFailure();
- }
-
- if (format.Length == 1)
- {
- switch (format[0])
- {
- case 'c':
- case 't':
- case 'T':
- return TryParseTimeSpanConstant(input, ref result); // fast path for legacy style TimeSpan formats.
-
- case 'g':
- return TryParseTimeSpan(input, TimeSpanStandardStyles.Localized, formatProvider, ref result);
-
- case 'G':
- return TryParseTimeSpan(input, TimeSpanStandardStyles.Localized | TimeSpanStandardStyles.RequireFull, formatProvider, ref result);
-
- default:
- return result.SetBadFormatSpecifierFailure(format[0]);
- }
- }
-
- return TryParseByFormat(input, format, styles, ref result);
- }
-
- /// <summary>Parse the TimeSpan instance using the specified format. Used by TryParseExactTimeSpan.</summary>
- private static bool TryParseByFormat(ReadOnlySpan<char> input, ReadOnlySpan<char> format, TimeSpanStyles styles, ref TimeSpanResult result)
- {
- bool seenDD = false; // already processed days?
- bool seenHH = false; // already processed hours?
- bool seenMM = false; // already processed minutes?
- bool seenSS = false; // already processed seconds?
- bool seenFF = false; // already processed fraction?
-
- int dd = 0; // parsed days
- int hh = 0; // parsed hours
- int mm = 0; // parsed minutes
- int ss = 0; // parsed seconds
- int leadingZeroes = 0; // number of leading zeroes in the parsed fraction
- int ff = 0; // parsed fraction
- int i = 0; // format string position
- int tokenLen; // length of current format token, used to update index 'i'
-
- var tokenizer = new TimeSpanTokenizer(input, -1);
-
- while (i < format.Length)
- {
- char ch = format[i];
- int nextFormatChar;
- switch (ch)
- {
- case 'h':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 2 || seenHH || !ParseExactDigits(ref tokenizer, tokenLen, out hh))
- {
- return result.SetInvalidStringFailure();
- }
- seenHH = true;
- break;
-
- case 'm':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 2 || seenMM || !ParseExactDigits(ref tokenizer, tokenLen, out mm))
- {
- return result.SetInvalidStringFailure();
- }
- seenMM = true;
- break;
-
- case 's':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 2 || seenSS || !ParseExactDigits(ref tokenizer, tokenLen, out ss))
- {
- return result.SetInvalidStringFailure();
- }
- seenSS = true;
- break;
-
- case 'f':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF || !ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff))
- {
- return result.SetInvalidStringFailure();
- }
- seenFF = true;
- break;
-
- case 'F':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF)
- {
- return result.SetInvalidStringFailure();
- }
- ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff);
- seenFF = true;
- break;
-
- case 'd':
- tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
- if (tokenLen > 8 || seenDD || !ParseExactDigits(ref tokenizer, (tokenLen < 2) ? 1 : tokenLen, (tokenLen < 2) ? 8 : tokenLen, out _, out dd))
- {
- return result.SetInvalidStringFailure();
- }
- seenDD = true;
- break;
-
- case '\'':
- case '\"':
- StringBuilder enquotedString = StringBuilderCache.Acquire();
- if (!DateTimeParse.TryParseQuoteString(format, i, enquotedString, out tokenLen))
- {
- StringBuilderCache.Release(enquotedString);
- return result.SetBadQuoteFailure(ch);
- }
- if (!ParseExactLiteral(ref tokenizer, enquotedString))
- {
- StringBuilderCache.Release(enquotedString);
- return result.SetInvalidStringFailure();
- }
- StringBuilderCache.Release(enquotedString);
- break;
-
- case '%':
- // Optional format character.
- // For example, format string "%d" will print day
- // Most of the cases, "%" can be ignored.
- nextFormatChar = DateTimeFormat.ParseNextChar(format, i);
-
- // nextFormatChar will be -1 if we already reach the end of the format string.
- // Besides, we will not allow "%%" appear in the pattern.
- if (nextFormatChar >= 0 && nextFormatChar != '%')
- {
- tokenLen = 1; // skip the '%' and process the format character
- break;
- }
- else
- {
- // This means that '%' is at the end of the format string or
- // "%%" appears in the format string.
- return result.SetInvalidStringFailure();
- }
-
- case '\\':
- // Escaped character. Can be used to insert character into the format string.
- // For example, "\d" will insert the character 'd' into the string.
- //
- nextFormatChar = DateTimeFormat.ParseNextChar(format, i);
- if (nextFormatChar >= 0 && tokenizer.NextChar == (char)nextFormatChar)
- {
- tokenLen = 2;
- }
- else
- {
- // This means that '\' is at the end of the format string or the literal match failed.
- return result.SetInvalidStringFailure();
- }
- break;
-
- default:
- return result.SetInvalidStringFailure();
- }
-
- i += tokenLen;
- }
-
-
- if (!tokenizer.EOL)
- {
- // the custom format didn't consume the entire input
- return result.SetBadTimeSpanFailure();
- }
-
- bool positive = (styles & TimeSpanStyles.AssumeNegative) == 0;
- if (TryTimeToTicks(positive, new TimeSpanToken(dd),
- new TimeSpanToken(hh),
- new TimeSpanToken(mm),
- new TimeSpanToken(ss),
- new TimeSpanToken(ff, leadingZeroes),
- out long ticks))
- {
- if (!positive)
- {
- ticks = -ticks;
- }
-
- result.parsedTimeSpan = new TimeSpan(ticks);
- return true;
- }
- else
- {
- return result.SetOverflowFailure();
- }
- }
-
- private static bool ParseExactDigits(ref TimeSpanTokenizer tokenizer, int minDigitLength, out int result)
- {
- int maxDigitLength = (minDigitLength == 1) ? 2 : minDigitLength;
- return ParseExactDigits(ref tokenizer, minDigitLength, maxDigitLength, out _, out result);
- }
-
- private static bool ParseExactDigits(ref TimeSpanTokenizer tokenizer, int minDigitLength, int maxDigitLength, out int zeroes, out int result)
- {
- int tmpResult = 0, tmpZeroes = 0;
-
- int tokenLength = 0;
- while (tokenLength < maxDigitLength)
- {
- char ch = tokenizer.NextChar;
- if (ch < '0' || ch > '9')
- {
- tokenizer.BackOne();
- break;
- }
-
- tmpResult = tmpResult * 10 + (ch - '0');
- if (tmpResult == 0) tmpZeroes++;
- tokenLength++;
- }
-
- zeroes = tmpZeroes;
- result = tmpResult;
- return tokenLength >= minDigitLength;
- }
-
- private static bool ParseExactLiteral(ref TimeSpanTokenizer tokenizer, StringBuilder enquotedString)
- {
- for (int i = 0; i < enquotedString.Length; i++)
- {
- if (enquotedString[i] != tokenizer.NextChar)
- {
- return false;
- }
- }
-
- return true;
- }
-
- /// <summary>
- /// Parses the "c" (constant) format. This code is 100% identical to the non-globalized v1.0-v3.5 TimeSpan.Parse() routine
- /// and exists for performance/appcompat with legacy callers who cannot move onto the globalized Parse overloads.
- /// </summary>
- private static bool TryParseTimeSpanConstant(ReadOnlySpan<char> input, ref TimeSpanResult result) =>
- default(StringParser).TryParse(input, ref result);
-
- private ref struct StringParser
- {
- private ReadOnlySpan<char> _str;
- private char _ch;
- private int _pos;
- private int _len;
-
- internal void NextChar()
- {
- if (_pos < _len)
- {
- _pos++;
- }
-
- _ch = _pos < _len ?
- _str[_pos] :
- (char)0;
- }
-
- internal char NextNonDigit()
- {
- int i = _pos;
- while (i < _len)
- {
- char ch = _str[i];
- if (ch < '0' || ch > '9') return ch;
- i++;
- }
-
- return (char)0;
- }
-
- internal bool TryParse(ReadOnlySpan<char> input, ref TimeSpanResult result)
- {
- result.parsedTimeSpan = default;
-
- _str = input;
- _len = input.Length;
- _pos = -1;
- NextChar();
- SkipBlanks();
-
- bool negative = false;
- if (_ch == '-')
- {
- negative = true;
- NextChar();
- }
-
- long time;
- if (NextNonDigit() == ':')
- {
- if (!ParseTime(out time, ref result))
- {
- return false;
- }
- }
- else
- {
- int days;
- if (!ParseInt((int)(0x7FFFFFFFFFFFFFFFL / TimeSpan.TicksPerDay), out days, ref result))
- {
- return false;
- }
-
- time = days * TimeSpan.TicksPerDay;
-
- if (_ch == '.')
- {
- NextChar();
- long remainingTime;
- if (!ParseTime(out remainingTime, ref result))
- {
- return false;
- }
- time += remainingTime;
- }
- }
-
- if (negative)
- {
- time = -time;
- // Allow -0 as well
- if (time > 0)
- {
- return result.SetOverflowFailure();
- }
- }
- else
- {
- if (time < 0)
- {
- return result.SetOverflowFailure();
- }
- }
-
- SkipBlanks();
-
- if (_pos < _len)
- {
- return result.SetBadTimeSpanFailure();
- }
-
- result.parsedTimeSpan = new TimeSpan(time);
- return true;
- }
-
- internal bool ParseInt(int max, out int i, ref TimeSpanResult result)
- {
- i = 0;
- int p = _pos;
- while (_ch >= '0' && _ch <= '9')
- {
- if ((i & 0xF0000000) != 0)
- {
- return result.SetOverflowFailure();
- }
-
- i = i * 10 + _ch - '0';
- if (i < 0)
- {
- return result.SetOverflowFailure();
- }
-
- NextChar();
- }
-
- if (p == _pos)
- {
- return result.SetBadTimeSpanFailure();
- }
-
- if (i > max)
- {
- return result.SetOverflowFailure();
- }
-
- return true;
- }
-
- internal bool ParseTime(out long time, ref TimeSpanResult result)
- {
- time = 0;
- int unit;
-
- if (!ParseInt(23, out unit, ref result))
- {
- return false;
- }
-
- time = unit * TimeSpan.TicksPerHour;
- if (_ch != ':')
- {
- return result.SetBadTimeSpanFailure();
- }
-
- NextChar();
-
- if (!ParseInt(59, out unit, ref result))
- {
- return false;
- }
-
- time += unit * TimeSpan.TicksPerMinute;
-
- if (_ch == ':')
- {
- NextChar();
-
- // allow seconds with the leading zero
- if (_ch != '.')
- {
- if (!ParseInt(59, out unit, ref result))
- {
- return false;
- }
- time += unit * TimeSpan.TicksPerSecond;
- }
-
- if (_ch == '.')
- {
- NextChar();
- int f = (int)TimeSpan.TicksPerSecond;
- while (f > 1 && _ch >= '0' && _ch <= '9')
- {
- f /= 10;
- time += (_ch - '0') * f;
- NextChar();
- }
- }
- }
-
- return true;
- }
-
- internal void SkipBlanks()
- {
- while (_ch == ' ' || _ch == '\t') NextChar();
- }
- }
-
- /// <summary>Common private ParseExactMultiple method called by both ParseExactMultiple and TryParseExactMultiple.</summary>
- private static bool TryParseExactMultipleTimeSpan(ReadOnlySpan<char> input, string[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles, ref TimeSpanResult result)
- {
- if (formats == null)
- {
- return result.SetArgumentNullFailure(nameof(formats));
- }
-
- if (input.Length == 0)
- {
- return result.SetBadTimeSpanFailure();
- }
-
- if (formats.Length == 0)
- {
- return result.SetNoFormatSpecifierFailure();
- }
-
- // Do a loop through the provided formats and see if we can parse succesfully in
- // one of the formats.
- for (int i = 0; i < formats.Length; i++)
- {
- if (formats[i] == null || formats[i].Length == 0)
- {
- return result.SetBadFormatSpecifierFailure();
- }
-
- // Create a new non-throwing result each time to ensure the runs are independent.
- TimeSpanResult innerResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
-
- if (TryParseExactTimeSpan(input, formats[i], formatProvider, styles, ref innerResult))
- {
- result.parsedTimeSpan = innerResult.parsedTimeSpan;
- return true;
- }
- }
-
- return result.SetBadTimeSpanFailure();
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanStyles.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanStyles.cs
deleted file mode 100644
index 68a47bcbe60..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/TimeSpanStyles.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- [Flags]
- public enum TimeSpanStyles
- {
- None = 0x00000000,
- AssumeNegative = 0x00000001,
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
deleted file mode 100644
index ae5820841e4..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
+++ /dev/null
@@ -1,653 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Globalization
-{
- /// <remarks>
- /// Calendar support range:
- /// Calendar Minimum Maximum
- /// ========== ========== ==========
- /// Gregorian 1900/04/30 2077/05/13
- /// UmAlQura 1318/01/01 1500/12/30
- /// </remarks>
- public partial class UmAlQuraCalendar : Calendar
- {
- private const int MinCalendarYear = 1318;
- private const int MaxCalendarYear = 1500;
-
- private struct DateMapping
- {
- internal DateMapping(int MonthsLengthFlags, int GYear, int GMonth, int GDay)
- {
- HijriMonthsLengthFlags = MonthsLengthFlags;
- GregorianDate = new DateTime(GYear, GMonth, GDay);
- }
-
- internal int HijriMonthsLengthFlags;
- internal DateTime GregorianDate;
- }
-
- private static readonly DateMapping[] s_hijriYearInfo = InitDateMapping();
-
- private static DateMapping[] InitDateMapping()
- {
- short[] rawData = new short[]
- {
- // These data are taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync
- /* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12
- 1318*/0x02EA, 1900, 4, 30, /* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900
- 1319*/0x06E9, 1901, 4, 19, /* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901
- 1320*/0x0ED2, 1902, 4, 9, /* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902
- 1321*/0x0EA4, 1903, 3, 30, /* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903
- 1322*/0x0D4A, 1904, 3, 18, /* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904
- 1323*/0x0A96, 1905, 3, 7, /* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905
- 1324*/0x0536, 1906, 2, 24, /* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906
- 1325*/0x0AB5, 1907, 2, 13, /* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907
- 1326*/0x0DAA, 1908, 2, 3, /* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908
- 1327*/0x0BA4, 1909, 1, 23, /* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909
- 1328*/0x0B49, 1910, 1, 12, /* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910
- 1329*/0x0A93, 1911, 1, 1, /* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911
- 1330*/0x052B, 1911, 12, 21, /* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911
- 1331*/0x0A57, 1912, 12, 9, /* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912
- 1332*/0x04B6, 1913, 11, 29, /* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913
- 1333*/0x0AB5, 1914, 11, 18, /* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914
- 1334*/0x05AA, 1915, 11, 8, /* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915
- 1335*/0x0D55, 1916, 10, 27, /* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916
- 1336*/0x0D2A, 1917, 10, 17, /* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917
- 1337*/0x0A56, 1918, 10, 6, /* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918
- 1338*/0x04AE, 1919, 9, 25, /* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919
- 1339*/0x095D, 1920, 9, 13, /* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920
- 1340*/0x02EC, 1921, 9, 3, /* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921
- 1341*/0x06D5, 1922, 8, 23, /* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922
- 1342*/0x06AA, 1923, 8, 13, /* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923
- 1343*/0x0555, 1924, 8, 1, /* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924
- 1344*/0x04AB, 1925, 7, 21, /* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925
- 1345*/0x095B, 1926, 7, 10, /* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926
- 1346*/0x02BA, 1927, 6, 30, /* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927
- 1347*/0x0575, 1928, 6, 18, /* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928
- 1348*/0x0BB2, 1929, 6, 8, /* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929
- 1349*/0x0764, 1930, 5, 29, /* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930
- 1350*/0x0749, 1931, 5, 18, /* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931
- 1351*/0x0655, 1932, 5, 6, /* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932
- 1352*/0x02AB, 1933, 4, 25, /* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933
- 1353*/0x055B, 1934, 4, 14, /* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934
- 1354*/0x0ADA, 1935, 4, 4, /* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935
- 1355*/0x06D4, 1936, 3, 24, /* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936
- 1356*/0x0EC9, 1937, 3, 13, /* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937
- 1357*/0x0D92, 1938, 3, 3, /* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938
- 1358*/0x0D25, 1939, 2, 20, /* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939
- 1359*/0x0A4D, 1940, 2, 9, /* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940
- 1360*/0x02AD, 1941, 1, 28, /* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941
- 1361*/0x056D, 1942, 1, 17, /* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942
- 1362*/0x0B6A, 1943, 1, 7, /* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943
- 1363*/0x0B52, 1943, 12, 28, /* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943
- 1364*/0x0AA5, 1944, 12, 16, /* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944
- 1365*/0x0A4B, 1945, 12, 5, /* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945
- 1366*/0x0497, 1946, 11, 24, /* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946
- 1367*/0x0937, 1947, 11, 13, /* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947
- 1368*/0x02B6, 1948, 11, 2, /* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948
- 1369*/0x0575, 1949, 10, 22, /* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949
- 1370*/0x0D6A, 1950, 10, 12, /* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950
- 1371*/0x0D52, 1951, 10, 2, /* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951
- 1372*/0x0A96, 1952, 9, 20, /* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952
- 1373*/0x092D, 1953, 9, 9, /* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953
- 1374*/0x025D, 1954, 8, 29, /* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954
- 1375*/0x04DD, 1955, 8, 18, /* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955
- 1376*/0x0ADA, 1956, 8, 7, /* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956
- 1377*/0x05D4, 1957, 7, 28, /* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957
- 1378*/0x0DA9, 1958, 7, 17, /* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958
- 1379*/0x0D52, 1959, 7, 7, /* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959
- 1380*/0x0AAA, 1960, 6, 25, /* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960
- 1381*/0x04D6, 1961, 6, 14, /* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961
- 1382*/0x09B6, 1962, 6, 3, /* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962
- 1383*/0x0374, 1963, 5, 24, /* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963
- 1384*/0x0769, 1964, 5, 12, /* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964
- 1385*/0x0752, 1965, 5, 2, /* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965
- 1386*/0x06A5, 1966, 4, 21, /* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966
- 1387*/0x054B, 1967, 4, 10, /* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967
- 1388*/0x0AAB, 1968, 3, 29, /* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968
- 1389*/0x055A, 1969, 3, 19, /* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969
- 1390*/0x0AD5, 1970, 3, 8, /* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970
- 1391*/0x0DD2, 1971, 2, 26, /* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971
- 1392*/0x0DA4, 1972, 2, 16, /* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972
- 1393*/0x0D49, 1973, 2, 4, /* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973
- 1394*/0x0A95, 1974, 1, 24, /* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974
- 1395*/0x052D, 1975, 1, 13, /* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975
- 1396*/0x0A5D, 1976, 1, 2, /* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976
- 1397*/0x055A, 1976, 12, 22, /* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976
- 1398*/0x0AD5, 1977, 12, 11, /* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977
- 1399*/0x06AA, 1978, 12, 1, /* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978
- 1400*/0x0695, 1979, 11, 20, /* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979
- 1401*/0x052B, 1980, 11, 8, /* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980
- 1402*/0x0A57, 1981, 10, 28, /* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981
- 1403*/0x04AE, 1982, 10, 18, /* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982
- 1404*/0x0976, 1983, 10, 7, /* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983
- 1405*/0x056C, 1984, 9, 26, /* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984
- 1406*/0x0B55, 1985, 9, 15, /* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985
- 1407*/0x0AAA, 1986, 9, 5, /* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986
- 1408*/0x0A55, 1987, 8, 25, /* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987
- 1409*/0x04AD, 1988, 8, 13, /* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988
- 1410*/0x095D, 1989, 8, 2, /* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989
- 1411*/0x02DA, 1990, 7, 23, /* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990
- 1412*/0x05D9, 1991, 7, 12, /* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991
- 1413*/0x0DB2, 1992, 7, 1, /* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992
- 1414*/0x0BA4, 1993, 6, 21, /* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993
- 1415*/0x0B4A, 1994, 6, 10, /* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994
- 1416*/0x0A55, 1995, 5, 30, /* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995
- 1417*/0x02B5, 1996, 5, 18, /* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996
- 1418*/0x0575, 1997, 5, 7, /* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997
- 1419*/0x0B6A, 1998, 4, 27, /* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998
- 1420*/0x0BD2, 1999, 4, 17, /* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999
- 1421*/0x0BC4, 2000, 4, 6, /* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000
- 1422*/0x0B89, 2001, 3, 26, /* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001
- 1423*/0x0A95, 2002, 3, 15, /* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002
- 1424*/0x052D, 2003, 3, 4, /* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003
- 1425*/0x05AD, 2004, 2, 21, /* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004
- 1426*/0x0B6A, 2005, 2, 10, /* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005
- 1427*/0x06D4, 2006, 1, 31, /* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006
- 1428*/0x0DC9, 2007, 1, 20, /* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007
- 1429*/0x0D92, 2008, 1, 10, /* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008
- 1430*/0x0AA6, 2008, 12, 29, /* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008
- 1431*/0x0956, 2009, 12, 18, /* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009
- 1432*/0x02AE, 2010, 12, 7, /* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010
- 1433*/0x056D, 2011, 11, 26, /* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011
- 1434*/0x036A, 2012, 11, 15, /* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012
- 1435*/0x0B55, 2013, 11, 4, /* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013
- 1436*/0x0AAA, 2014, 10, 25, /* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014
- 1437*/0x094D, 2015, 10, 14, /* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015
- 1438*/0x049D, 2016, 10, 2, /* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016
- 1439*/0x095D, 2017, 9, 21, /* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017
- 1440*/0x02BA, 2018, 9, 11, /* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018
- 1441*/0x05B5, 2019, 8, 31, /* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019
- 1442*/0x05AA, 2020, 8, 20, /* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020
- 1443*/0x0D55, 2021, 8, 9, /* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021
- 1444*/0x0A9A, 2022, 7, 30, /* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022
- 1445*/0x092E, 2023, 7, 19, /* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023
- 1446*/0x026E, 2024, 7, 7, /* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024
- 1447*/0x055D, 2025, 6, 26, /* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025
- 1448*/0x0ADA, 2026, 6, 16, /* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026
- 1449*/0x06D4, 2027, 6, 6, /* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027
- 1450*/0x06A5, 2028, 5, 25, /* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028
- 1451*/0x054B, 2029, 5, 14, /* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029
- 1452*/0x0A97, 2030, 5, 3, /* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030
- 1453*/0x054E, 2031, 4, 23, /* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031
- 1454*/0x0AAE, 2032, 4, 11, /* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032
- 1455*/0x05AC, 2033, 4, 1, /* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033
- 1456*/0x0BA9, 2034, 3, 21, /* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034
- 1457*/0x0D92, 2035, 3, 11, /* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035
- 1458*/0x0B25, 2036, 2, 28, /* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036
- 1459*/0x064B, 2037, 2, 16, /* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037
- 1460*/0x0CAB, 2038, 2, 5, /* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038
- 1461*/0x055A, 2039, 1, 26, /* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039
- 1462*/0x0B55, 2040, 1, 15, /* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040
- 1463*/0x06D2, 2041, 1, 4, /* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041
- 1464*/0x0EA5, 2041, 12, 24, /* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041
- 1465*/0x0E4A, 2042, 12, 14, /* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042
- 1466*/0x0A95, 2043, 12, 3, /* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043
- 1467*/0x052D, 2044, 11, 21, /* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044
- 1468*/0x0AAD, 2045, 11, 10, /* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045
- 1469*/0x036C, 2046, 10, 31, /* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046
- 1470*/0x0759, 2047, 10, 20, /* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047
- 1471*/0x06D2, 2048, 10, 9, /* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048
- 1472*/0x0695, 2049, 9, 28, /* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049
- 1473*/0x052D, 2050, 9, 17, /* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050
- 1474*/0x0A5B, 2051, 9, 6, /* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051
- 1475*/0x04BA, 2052, 8, 26, /* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052
- 1476*/0x09BA, 2053, 8, 15, /* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053
- 1477*/0x03B4, 2054, 8, 5, /* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054
- 1478*/0x0B69, 2055, 7, 25, /* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055
- 1479*/0x0B52, 2056, 7, 14, /* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056
- 1480*/0x0AA6, 2057, 7, 3, /* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057
- 1481*/0x04B6, 2058, 6, 22, /* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058
- 1482*/0x096D, 2059, 6, 11, /* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059
- 1483*/0x02EC, 2060, 5, 31, /* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060
- 1484*/0x06D9, 2061, 5, 20, /* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061
- 1485*/0x0EB2, 2062, 5, 10, /* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062
- 1486*/0x0D54, 2063, 4, 30, /* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063
- 1487*/0x0D2A, 2064, 4, 18, /* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064
- 1488*/0x0A56, 2065, 4, 7, /* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065
- 1489*/0x04AE, 2066, 3, 27, /* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066
- 1490*/0x096D, 2067, 3, 16, /* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067
- 1491*/0x0D6A, 2068, 3, 5, /* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068
- 1492*/0x0B54, 2069, 2, 23, /* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069
- 1493*/0x0B29, 2070, 2, 12, /* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070
- 1494*/0x0A93, 2071, 2, 1, /* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071
- 1495*/0x052B, 2072, 1, 21, /* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072
- 1496*/0x0A57, 2073, 1, 9, /* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073
- 1497*/0x0536, 2073, 12, 30, /* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073
- 1498*/0x0AB5, 2074, 12, 19, /* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074
- 1499*/0x06AA, 2075, 12, 9, /* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075
- 1500*/0x0E93, 2076, 11, 27, /* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076
- 1501*/ 0, 2077, 11, 17, /* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077
- */ };
- // Direct inline initialization of DateMapping array would produce a lot of code bloat.
-
- // We take advantage of C# compiler compiles inline initialization of primitive type array into very compact code.
- // So we start with raw data stored in primitive type array, and initialize the DateMapping out of it
-
- DateMapping[] mapping = new DateMapping[rawData.Length / 4];
- for (int i = 0; i < mapping.Length; i++)
- mapping[i] = new DateMapping(rawData[i * 4], rawData[i * 4 + 1], rawData[i * 4 + 2], rawData[i * 4 + 3]);
- return mapping;
- }
-
- public const int UmAlQuraEra = 1;
-
- private const int DatePartYear = 0;
- private const int DatePartDayOfYear = 1;
- private const int DatePartMonth = 2;
- private const int DatePartDay = 3;
-
- private static readonly DateTime s_minDate = new DateTime(1900, 4, 30);
- private static readonly DateTime s_maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 9999);
-
- public override DateTime MinSupportedDateTime => s_minDate;
-
- public override DateTime MaxSupportedDateTime => s_maxDate;
-
- public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunarCalendar;
-
- public UmAlQuraCalendar()
- {
- }
-
- internal override CalendarId BaseCalendarID => CalendarId.HIJRI;
-
- internal override CalendarId ID => CalendarId.UMALQURA;
-
- protected override int DaysInYearBeforeMinSupportedYear =>
- // HijriCalendar has same number of days as UmAlQuraCalendar for any given year
- // HijriCalendar says year 1317 has 355 days.
- 355;
-
- private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, out int yg, out int mg, out int dg)
- {
- Debug.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range.");
- Debug.Assert(HijriMonth >= 1, "Hijri month is out of range.");
- Debug.Assert(HijriDay >= 1, "Hijri day is out of range.");
- int nDays = HijriDay - 1;
-
- int index = HijriYear - MinCalendarYear;
- DateTime dt = s_hijriYearInfo[index].GregorianDate;
- int b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
-
- for (int m = 1; m < HijriMonth; m++)
- {
- // Add the months lengths before mh
- nDays = nDays + 29 + (b & 1);
- b >>= 1;
- }
-
- dt = dt.AddDays(nDays);
- dt.GetDatePart(out yg, out mg, out dg);
- }
-
- private static long GetAbsoluteDateUmAlQura(int year, int month, int day)
- {
- ConvertHijriToGregorian(year, month, day, out int yg, out int mg, out int dg);
- return GregorianCalendar.GetAbsoluteDate(yg, mg, dg);
- }
-
- internal static void CheckTicksRange(long ticks)
- {
- if (ticks < s_minDate.Ticks || ticks > s_maxDate.Ticks)
- {
- throw new ArgumentOutOfRangeException(
- "time",
- ticks,
- SR.Format(
- CultureInfo.InvariantCulture,
- SR.ArgumentOutOfRange_CalendarRange,
- s_minDate,
- s_maxDate));
- }
- }
-
- internal static void CheckEraRange(int era)
- {
- if (era != CurrentEra && era != UmAlQuraEra)
- {
- throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
- }
- }
-
- internal static void CheckYearRange(int year, int era)
- {
- CheckEraRange(era);
- if (year < MinCalendarYear || year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
- }
- }
-
- internal static void CheckYearMonthRange(int year, int month, int era)
- {
- CheckYearRange(year, era);
- if (month < 1 || month > 12)
- {
- throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
- }
- }
-
- private static void ConvertGregorianToHijri(DateTime time, out int HijriYear, out int HijriMonth, out int HijriDay)
- {
- Debug.Assert((time.Ticks >= s_minDate.Ticks) && (time.Ticks <= s_maxDate.Ticks), "Gregorian date is out of range.");
-
- // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo.
- // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index.
-
- int index = (int)((time.Ticks - s_minDate.Ticks) / Calendar.TicksPerDay) / 355;
- do
- {
- } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); // while greater
-
- if (time.CompareTo(s_hijriYearInfo[index].GregorianDate) != 0)
- {
- index--;
- }
-
- TimeSpan ts = time.Subtract(s_hijriYearInfo[index].GregorianDate);
- int yh1 = index + MinCalendarYear;
- int mh1 = 1;
- int dh1 = 1;
- double nDays = ts.TotalDays;
- int b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
- int daysPerThisMonth = 29 + (b & 1);
-
- while (nDays >= daysPerThisMonth)
- {
- nDays -= daysPerThisMonth;
- b >>= 1;
- daysPerThisMonth = 29 + (b & 1);
- mh1++;
- }
- dh1 += (int)nDays;
-
- HijriDay = dh1;
- HijriMonth = mh1;
- HijriYear = yh1;
- }
-
- /// <summary>
- /// First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
- /// Use the formula (((AbsoluteDate - 226894) * 33) / (33 * 365 + 8)) + 1, we can a rough value for the UmAlQura year.
- /// In order to get the exact UmAlQura year, we compare the exact absolute date for UmAlQuraYear and (UmAlQuraYear + 1).
- /// From here, we can get the correct UmAlQura year.
- /// </summary>
- private int GetDatePart(DateTime time, int part)
- {
- long ticks = time.Ticks;
- CheckTicksRange(ticks);
-
- ConvertGregorianToHijri(time, out int UmAlQuraYear, out int UmAlQuraMonth, out int UmAlQuraDay);
-
- if (part == DatePartYear)
- {
- return UmAlQuraYear;
- }
- if (part == DatePartMonth)
- {
- return UmAlQuraMonth;
- }
- if (part == DatePartDay)
- {
- return UmAlQuraDay;
- }
- if (part == DatePartDayOfYear)
- {
- return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura(UmAlQuraYear, 1, 1) + 1);
- }
-
- // Incorrect part value.
- throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
- }
-
- public override DateTime AddMonths(DateTime time, int months)
- {
- if (months < -120000 || months > 120000)
- {
- throw new ArgumentOutOfRangeException(
- nameof(months),
- months,
- SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
- }
-
- // Get the date in UmAlQura calendar.
- int y = GetDatePart(time, DatePartYear);
- int m = GetDatePart(time, DatePartMonth);
- int d = GetDatePart(time, DatePartDay);
- int i = m - 1 + months;
-
- if (i >= 0)
- {
- m = i % 12 + 1;
- y += i / 12;
- }
- else
- {
- m = 12 + (i + 1) % 12;
- y += (i - 11) / 12;
- }
-
- if (d > 29)
- {
- int days = GetDaysInMonth(y, m);
- if (d > days)
- {
- d = days;
- }
- }
-
- CheckYearRange(y, UmAlQuraEra);
- DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay);
- Calendar.CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
- return dt;
- }
-
- public override DateTime AddYears(DateTime time, int years)
- {
- return AddMonths(time, years * 12);
- }
-
- public override int GetDayOfMonth(DateTime time)
- {
- return GetDatePart(time, DatePartDay);
- }
-
- public override DayOfWeek GetDayOfWeek(DateTime time)
- {
- return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
- }
-
- public override int GetDayOfYear(DateTime time)
- {
- return GetDatePart(time, DatePartDayOfYear);
- }
-
- public override int GetDaysInMonth(int year, int month, int era)
- {
- CheckYearMonthRange(year, month, era);
-
- if ((s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0)
- {
- return 29;
- }
- else
- {
- return 30;
- }
- }
-
- internal static int RealGetDaysInYear(int year)
- {
- int days = 0;
-
- Debug.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range.");
-
- int b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags;
-
- for (int m = 1; m <= 12; m++)
- {
- days = days + 29 + (b & 1); /* Add the months lengths before mh */
- b >>= 1;
- }
-
- Debug.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days.");
- return days;
- }
-
- public override int GetDaysInYear(int year, int era)
- {
- CheckYearRange(year, era);
- return RealGetDaysInYear(year);
- }
-
- public override int GetEra(DateTime time)
- {
- CheckTicksRange(time.Ticks);
- return UmAlQuraEra;
- }
-
- public override int[] Eras => new int[] { UmAlQuraEra };
-
- public override int GetMonth(DateTime time)
- {
- return GetDatePart(time, DatePartMonth);
- }
-
- public override int GetMonthsInYear(int year, int era)
- {
- CheckYearRange(year, era);
- return 12;
- }
-
- public override int GetYear(DateTime time)
- {
- return GetDatePart(time, DatePartYear);
- }
-
- public override bool IsLeapDay(int year, int month, int day, int era)
- {
- if (day >= 1 && day <= 29)
- {
- CheckYearMonthRange(year, month, era);
- return false;
- }
-
- // The year/month/era value checking is done in GetDaysInMonth().
- int daysInMonth = GetDaysInMonth(year, month, era);
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
- return false;
- }
-
- public override int GetLeapMonth(int year, int era)
- {
- CheckYearRange(year, era);
- return 0;
- }
-
- public override bool IsLeapMonth(int year, int month, int era)
- {
- CheckYearMonthRange(year, month, era);
- return false;
- }
-
- public override bool IsLeapYear(int year, int era)
- {
- CheckYearRange(year, era);
- return RealGetDaysInYear(year) == 355;
- }
-
- public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
- {
- if (day >= 1 && day <= 29)
- {
- CheckYearMonthRange(year, month, era);
- goto DayInRang;
- }
-
- // The year/month/era value checking is done in GetDaysInMonth().
- int daysInMonth = GetDaysInMonth(year, month, era);
-
- if (day < 1 || day > daysInMonth)
- {
- throw new ArgumentOutOfRangeException(
- nameof(day),
- day,
- SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
- }
- DayInRang:
- long lDate = GetAbsoluteDateUmAlQura(year, month, day);
- if (lDate < 0)
- {
- throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
- }
-
- return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond));
- }
-
- private const int DefaultTwoDigitYearMax = 1451;
-
- public override int TwoDigitYearMax
- {
- get
- {
- if (_twoDigitYearMax == -1)
- {
- _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
- }
-
- return _twoDigitYearMax;
- }
- set
- {
- if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear))
- {
- throw new ArgumentOutOfRangeException(
- nameof(value),
- value,
- SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
- }
-
- VerifyWritable();
- // We allow year 99 to be set so that one can make ToFourDigitYearMax a no-op by setting TwoDigitYearMax to 99.
- _twoDigitYearMax = value;
- }
- }
-
- public override int ToFourDigitYear(int year)
- {
- if (year < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
- }
-
- if (year < 100)
- {
- return base.ToFourDigitYear(year);
- }
-
- if (year < MinCalendarYear || year > MaxCalendarYear)
- {
- throw new ArgumentOutOfRangeException(
- nameof(year),
- year,
- SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
- }
-
- return year;
- }
- }
-}
diff --git a/netcore/System.Private.CoreLib/shared/System/Globalization/UnicodeCategory.cs b/netcore/System.Private.CoreLib/shared/System/Globalization/UnicodeCategory.cs
deleted file mode 100644
index f0ae1fdfd9d..00000000000
--- a/netcore/System.Private.CoreLib/shared/System/Globalization/UnicodeCategory.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-namespace System.Globalization
-{
- public enum UnicodeCategory
- {
- UppercaseLetter = 0,
- LowercaseLetter = 1,
- TitlecaseLetter = 2,
- ModifierLetter = 3,
- OtherLetter = 4,
- NonSpacingMark = 5,
- SpacingCombiningMark = 6,
- EnclosingMark = 7,
- DecimalDigitNumber = 8,
- LetterNumber = 9,
- OtherNumber = 10,
- SpaceSeparator = 11,
- LineSeparator = 12,
- ParagraphSeparator = 13,
- Control = 14,
- Format = 15,
- Surrogate = 16,
- PrivateUse = 17,
- ConnectorPunctuation = 18,
- DashPunctuation = 19,
- OpenPunctuation = 20,
- ClosePunctuation = 21,
- InitialQuotePunctuation = 22,
- FinalQuotePunctuation = 23,
- OtherPunctuation = 24,
- MathSymbol = 25,
- CurrencySymbol = 26,
- ModifierSymbol = 27,
- OtherSymbol = 28,
- OtherNotAssigned = 29,
- }
-}