Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Native Digit Reading #58598

Merged
merged 3 commits into from
Sep 4, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,43 @@ internal static bool IsCustomCultureId(int cultureId)
return cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED;
}

private string[] GetNativeDigits()
{
string[] result = NumberFormatInfo.s_asciiDigits;

// LOCALE_SNATIVEDIGITS (array of 10 single character strings).
string digits = GetLocaleInfoCoreUserOverride(LocaleStringData.Digits);

// if digits.Length < NumberFormatInfo.s_asciiDigits.Length means the native digits setting is messed up in the host machine.
// Instead of throwing IndexOutOfRangeException that will be hard to diagnose after the fact, we'll fall back to use the ASCII digits instead.
if (digits.Length >= NumberFormatInfo.s_asciiDigits.Length)
{
// Try to check if the digits are all ASCII so we can avoid the array allocation and use the static array NumberFormatInfo.s_asciiDigits instead.
// If we have non-ASCII digits, we should exit the loop very quickly.
int i = 0;
while (i < NumberFormatInfo.s_asciiDigits.Length)
{
if (digits[i] != NumberFormatInfo.s_asciiDigits[i][0])
{
break;
}
i++;
}

if (i < NumberFormatInfo.s_asciiDigits.Length)
{
// we have non-ASCII digits
result = new string[10];
for (i = 0; i < result.Length; i++)
{
result[i] = char.ToString(digits[i]);
}
}
}

return result;
}

internal void GetNFIValues(NumberFormatInfo nfi)
{
if (GlobalizationMode.Invariant || IsInvariantCulture)
Expand Down Expand Up @@ -2168,13 +2205,7 @@ internal void GetNFIValues(NumberFormatInfo nfi)
nfi._currencyNegativePattern = GetLocaleInfoCoreUserOverride(LocaleNumberData.NegativeMonetaryNumberFormat);
nfi._numberNegativePattern = GetLocaleInfoCoreUserOverride(LocaleNumberData.NegativeNumberFormat);

// LOCALE_SNATIVEDIGITS (array of 10 single character strings).
string digits = GetLocaleInfoCoreUserOverride(LocaleStringData.Digits);
nfi._nativeDigits = new string[10];
for (int i = 0; i < nfi._nativeDigits.Length; i++)
{
nfi._nativeDigits[i] = char.ToString(digits[i]);
}
nfi._nativeDigits = GetNativeDigits();

Debug.Assert(_sRealName != null);
nfi._digitSubstitution = ShouldUseUserOverrideNlsData ? NlsGetLocaleInfo(LocaleNumberData.DigitSubstitution) : IcuGetDigitSubstitution(_sRealName);
Expand Down Expand Up @@ -2308,7 +2339,7 @@ private enum LocaleStringData : uint
DecimalSeparator = 0x0000000E,
/// <summary>thousand separator (corresponds to LOCALE_STHOUSAND)</summary>
ThousandSeparator = 0x0000000F,
/// <summary>digit grouping (corresponds to LOCALE_SGROUPING)</summary>
/// <summary>native digits for 0-9, eg "0123456789" (corresponds to LOCALE_SNATIVEDIGITS)</summary>
Digits = 0x00000013,
/// <summary>local monetary symbol (corresponds to LOCALE_SCURRENCY)</summary>
MonetarySymbol = 0x00000014,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace System.Globalization
public sealed class NumberFormatInfo : IFormatProvider, ICloneable
{
private static volatile NumberFormatInfo? s_invariantInfo;
internal static readonly string[] s_asciiDigits = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };

internal int[] _numberGroupSizes = new int[] { 3 };
internal int[] _currencyGroupSizes = new int[] { 3 };
Expand Down