diff options
author | Tanner Gooding <tagoo@outlook.com> | 2018-08-30 20:09:59 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2018-09-07 06:33:14 +0300 |
commit | aac68859756fb4eb8da80474eeed6d772fe6c0d7 (patch) | |
tree | 46d65d38721bdc542a83439965a7f513ec65d615 | |
parent | 86f5fbcb12bc5f9e063ab820b412df6c512062b8 (diff) |
Updating Number.Formatting to properly print -0
Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
-rw-r--r-- | src/System.Private.CoreLib/shared/System/Number.Formatting.cs | 62 | ||||
-rw-r--r-- | src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs | 20 |
2 files changed, 50 insertions, 32 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs index 106fd153e..3d3c15bf7 100644 --- a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs +++ b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs @@ -301,7 +301,7 @@ namespace System if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, isDecimal:true); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -327,7 +327,7 @@ namespace System if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, isDecimal: true); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -342,6 +342,7 @@ namespace System char* buffer = number.digits; number.precision = DecimalPrecision; number.sign = d.IsNegative; + number.kind = NumberBufferKind.Decimal; char* p = buffer + DecimalPrecision; while ((d.Mid | d.High) != 0) @@ -388,6 +389,7 @@ namespace System char fmt = ParseFormatSpecifier(format, out int digits); int precision = DoublePrecision; NumberBuffer number = default; + number.kind = NumberBufferKind.Double; switch (fmt) { @@ -409,12 +411,12 @@ namespace System if (NumberToDouble(ref number) == value) { - NumberToString(ref sb, ref number, 'G', DoublePrecision, info, isDecimal: false); + NumberToString(ref sb, ref number, 'G', DoublePrecision, info); } else { DoubleToNumber(value, 17, ref number); - NumberToString(ref sb, ref number, 'G', 17, info, isDecimal: false); + NumberToString(ref sb, ref number, 'G', 17, info); } return null; @@ -451,7 +453,7 @@ namespace System if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, isDecimal: false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -488,6 +490,7 @@ namespace System char fmt = ParseFormatSpecifier(format, out int digits); int precision = FloatPrecision; NumberBuffer number = default; + number.kind = NumberBufferKind.Double; switch (fmt) { @@ -509,12 +512,12 @@ namespace System if ((float)NumberToDouble(ref number) == value) { - NumberToString(ref sb, ref number, 'G', FloatPrecision, info, isDecimal: false); + NumberToString(ref sb, ref number, 'G', FloatPrecision, info); } else { DoubleToNumber(value, 9, ref number); - NumberToString(ref sb, ref number, 'G', 9, info, isDecimal: false); + NumberToString(ref sb, ref number, 'G', 9, info); } return null; } @@ -550,7 +553,7 @@ namespace System if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -608,7 +611,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -653,7 +656,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -696,7 +699,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -739,7 +742,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -785,7 +788,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -831,7 +834,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -875,7 +878,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -919,7 +922,7 @@ namespace System } if (fmt != 0) { - NumberToString(ref sb, ref number, fmt, digits, info, false); + NumberToString(ref sb, ref number, fmt, digits, info); } else { @@ -949,6 +952,7 @@ namespace System int i = (int)(buffer + Int32Precision - p); number.scale = i; + number.kind = NumberBufferKind.Integer; char* dst = number.digits; while (--i >= 0) @@ -1065,6 +1069,7 @@ namespace System char* p = UInt32ToDecChars(buffer + UInt32Precision, value, 0); int i = (int)(buffer + UInt32Precision - p); number.scale = i; + number.kind = NumberBufferKind.Integer; char* dst = number.digits; while (--i >= 0) @@ -1184,6 +1189,7 @@ namespace System int i = (int)(buffer + Int64Precision - p); number.scale = i; + number.kind = NumberBufferKind.Integer; char* dst = number.digits; while (--i >= 0) @@ -1325,6 +1331,7 @@ namespace System int i = (int)(buffer + UInt64Precision - p); number.scale = i; + number.kind = NumberBufferKind.Integer; char* dst = number.digits; while (--i >= 0) @@ -1453,8 +1460,10 @@ namespace System '\0'; } - internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info, bool isDecimal) + internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info) { + Debug.Assert(number.kind != NumberBufferKind.Unknown); + switch (format) { case 'C': @@ -1522,14 +1531,9 @@ namespace System bool noRounding = false; if (nMaxDigits < 1) { - if (isDecimal && (nMaxDigits == -1)) + if ((number.kind == NumberBufferKind.Decimal) && (nMaxDigits == -1)) { noRounding = true; // Turn off rounding for ECMA compliance to output trailing 0's after decimal as significant - if (number.digits[0] == 0) - { - // Minus zero should be formatted as 0 - goto SkipSign; - } goto SkipRounding; } else @@ -1539,13 +1543,12 @@ namespace System } } - RoundNumber(ref number, nMaxDigits); // This also fixes up the minus zero case + RoundNumber(ref number, nMaxDigits); SkipRounding: if (number.sign) sb.Append(info.NegativeSign); -SkipSign: FormatGeneral(ref sb, ref number, nMaxDigits, info, (char)(format - ('G' - 'E')), noRounding); break; @@ -1572,6 +1575,8 @@ SkipSign: internal static unsafe void NumberToStringFormat(ref ValueStringBuilder sb, ref NumberBuffer number, ReadOnlySpan<char> format, NumberFormatInfo info) { + Debug.Assert(number.kind != NumberBufferKind.Unknown); + int digitCount; int decimalPos; int firstDigit; @@ -1694,7 +1699,6 @@ SkipSign: } else { - number.sign = false; // We need to format -0 without the sign set. number.scale = 0; // Decimals with scale ('0.00') should be rounded. } @@ -2220,7 +2224,11 @@ SkipSign: if (i == 0) { number.scale = 0; - number.sign = false; + + if (number.kind == NumberBufferKind.Integer) + { + number.sign = false; + } } dig[i] = '\0'; } diff --git a/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs b/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs index 2316f99bd..1730cf18f 100644 --- a/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs +++ b/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs @@ -15,17 +15,27 @@ namespace System [StructLayout(LayoutKind.Sequential, Pack = 1)] internal unsafe ref struct NumberBuffer // needs to match layout of NUMBER in coreclr's src/classlibnative/bcltype/number.h { - public int precision; - public int scale; - private int _sign; - private DigitsAndNullTerminator _digits; - private char* _allDigits; + public int precision; // 0 + public int scale; // 4 + private int _sign; // 8 + private NumberBufferKind _kind; // 12 + private char* _allDigits; // 16 + private DigitsAndNullTerminator _digits; // 20 or 24 public bool sign { get => _sign != 0; set => _sign = value ? 1 : 0; } public char* digits => (char*)Unsafe.AsPointer(ref _digits); + public NumberBufferKind kind { get => _kind; set => _kind = value; } [StructLayout(LayoutKind.Sequential, Size = (NumberMaxDigits + 1) * sizeof(char))] private struct DigitsAndNullTerminator { } } + + internal enum NumberBufferKind // needs to match NUMBER_KIND in coreclr's src/classlibnative/bcltype/number.h + { + Unknown = 0, + Integer = 1, + Decimal = 2, + Double = 3 + } } } |