char fmt = ParseFormatSpecifier(format, out int digits);
NumberBuffer number = default;
- DecimalToNumber(value, ref number);
+ DecimalToNumber(ref value, ref number);
ValueStringBuilder sb;
unsafe
char fmt = ParseFormatSpecifier(format, out int digits);
NumberBuffer number = default;
- DecimalToNumber(value, ref number);
+ DecimalToNumber(ref value, ref number);
ValueStringBuilder sb;
unsafe
return sb.TryCopyTo(destination, out charsWritten);
}
- private static unsafe void DecimalToNumber(decimal value, ref NumberBuffer number)
+ private static unsafe void DecimalToNumber(ref decimal d, ref NumberBuffer number)
{
- decimal d = value;
-
char* buffer = number.digits;
number.precision = DecimalPrecision;
number.sign = d.IsNegative;
}
p = UInt32ToDecChars(p, d.Low, 0);
- int i = (int)(buffer + DecimalPrecision - p);
+ int i = (int)((byte*)(buffer + DecimalPrecision) - (byte*)p) >> 1;
number.scale = i - d.Scale;
char* dst = number.digits;
internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info, bool isDecimal)
{
- int nMinDigits = -1;
-
switch (format)
{
case 'C':
case 'c':
{
- nMinDigits = nMaxDigits >= 0 ? nMaxDigits : info.CurrencyDecimalDigits;
if (nMaxDigits < 0)
nMaxDigits = info.CurrencyDecimalDigits;
RoundNumber(ref number, number.scale + nMaxDigits); // Don't change this line to use digPos since digCount could have its sign changed.
- FormatCurrency(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatCurrency(ref sb, ref number, nMaxDigits, info);
break;
}
case 'f':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.NumberDecimalDigits;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.NumberDecimalDigits;
RoundNumber(ref number, number.scale + nMaxDigits);
if (number.sign)
sb.Append(info.NegativeSign);
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
break;
}
case 'n':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.NumberDecimalDigits; // Since we are using digits in our calculation
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.NumberDecimalDigits; // Since we are using digits in our calculation
RoundNumber(ref number, number.scale + nMaxDigits);
- FormatNumber(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatNumber(ref sb, ref number, nMaxDigits, info);
break;
}
case 'e':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = 6;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = 6;
nMaxDigits++;
RoundNumber(ref number, nMaxDigits);
if (number.sign)
sb.Append(info.NegativeSign);
- FormatScientific(ref sb, ref number, nMinDigits, nMaxDigits, info, format);
+ FormatScientific(ref sb, ref number, nMaxDigits, info, format);
break;
}
case 'G':
case 'g':
{
- bool enableRounding = true;
+ bool noRounding = false;
if (nMaxDigits < 1)
{
if (isDecimal && (nMaxDigits == -1))
{
- // Default to 29 digits precision only for G formatting without a precision specifier
- // This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = nMinDigits = DecimalPrecision;
- enableRounding = false; // Turn off rounding for ECMA compliance to output trailing 0's after decimal as significant
+ 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
{
// This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = nMinDigits = number.precision;
+ nMaxDigits = number.precision;
}
}
- else
- nMinDigits = nMaxDigits;
- if (enableRounding) // Don't round for G formatting without precision
- RoundNumber(ref number, nMaxDigits); // This also fixes up the minus zero case
- else
- {
- if (isDecimal && (number.digits[0] == 0))
- {
- // Minus zero should be formatted as 0
- number.sign = false;
- }
- }
+ RoundNumber(ref number, nMaxDigits); // This also fixes up the minus zero case
+SkipRounding:
if (number.sign)
sb.Append(info.NegativeSign);
- FormatGeneral(ref sb, ref number, nMinDigits, nMaxDigits, info, (char)(format - ('G' - 'E')), !enableRounding);
+SkipSign:
+ FormatGeneral(ref sb, ref number, nMaxDigits, info, (char)(format - ('G' - 'E')), noRounding);
break;
}
case 'p':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.PercentDecimalDigits;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.PercentDecimalDigits;
number.scale += 2;
RoundNumber(ref number, number.scale + nMaxDigits);
- FormatPercent(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatPercent(ref sb, ref number, nMaxDigits, info);
break;
}
}
}
- private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negCurrencyFormats[info.CurrencyNegativePattern] :
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
}
}
- private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, int[] groupDigits, string sDecimal, string sGroup)
+ private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, int[] groupDigits, string sDecimal, string sGroup)
{
int digPos = number.scale;
char* dig = number.digits;
}
}
- private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negNumberFormats[info.NumberNegativePattern] :
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
}
}
- private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, char expChar)
+ private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar)
{
char* dig = number.digits;
sb.Append(p, (int)(digits + MaxUInt32DecDigits - p));
}
- private static unsafe void FormatGeneral(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, char expChar, bool bSuppressScientific)
+ private static unsafe void FormatGeneral(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar, bool bSuppressScientific)
{
int digPos = number.scale;
bool scientific = false;
FormatExponent(ref sb, info, number.scale - 1, expChar, 2, true);
}
- private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negPercentFormats[info.PercentNegativePattern] :
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);