{
char fmt = ParseFormatSpecifier(format, out int digits);
- char* pDigits = stackalloc char[DecimalNumberBufferLength];
+ byte* pDigits = stackalloc byte[DecimalNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, pDigits, DecimalNumberBufferLength);
DecimalToNumber(ref value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
if (fmt != 0)
{
{
char fmt = ParseFormatSpecifier(format, out int digits);
- char* pDigits = stackalloc char[DecimalNumberBufferLength];
+ byte* pDigits = stackalloc byte[DecimalNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, pDigits, DecimalNumberBufferLength);
DecimalToNumber(ref value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
if (fmt != 0)
{
private static unsafe void DecimalToNumber(ref decimal d, ref NumberBuffer number)
{
- char* buffer = number.GetDigitsPointer();
- number.Precision = DecimalPrecision;
- number.Sign = d.IsNegative;
+ byte* buffer = number.GetDigitsPointer();
+ number.DigitsCount = DecimalPrecision;
+ number.IsNegative = d.IsNegative;
- char* p = buffer + DecimalPrecision;
+ byte* p = buffer + DecimalPrecision;
while ((d.Mid | d.High) != 0)
{
p = UInt32ToDecChars(p, decimal.DecDivMod1E9(ref d), 9);
}
p = UInt32ToDecChars(p, d.Low, 0);
- int i = (int)((byte*)(buffer + DecimalPrecision) - (byte*)p) >> 1;
+ int i = (int)((buffer + DecimalPrecision) - p);
+
+ number.DigitsCount = i;
number.Scale = i - d.Scale;
- char* dst = number.GetDigitsPointer();
+ byte* dst = number.GetDigitsPointer();
while (--i >= 0)
{
*dst++ = *p++;
}
- *dst = '\0';
+ *dst = (byte)('\0');
+
+ number.CheckConsistency();
}
public static string FormatDouble(double value, string format, NumberFormatInfo info)
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = DoublePrecision;
- char* pDigits = stackalloc char[DoubleNumberBufferLength];
+ byte* pDigits = stackalloc byte[DoubleNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, pDigits, DoubleNumberBufferLength);
switch (fmt)
// number using 15 digits and then determine if it round trips to the same value. If it does, we
// convert that NUMBER to a string, otherwise we reparse using 17 digits and display that.
DoubleToNumber(value, DoublePrecision, ref number);
+
if (number.Scale == ScaleNAN)
{
return info.NaNSymbol;
}
else if (number.Scale == ScaleINF)
{
- return number.Sign ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
+ return number.IsNegative ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
}
double roundTrip = NumberToDouble(ref number);
}
DoubleToNumber(value, precision, ref number);
+
if (number.Scale == ScaleNAN)
{
return info.NaNSymbol;
}
else if (number.Scale == ScaleINF)
{
- return number.Sign ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
+ return number.IsNegative ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
}
if (fmt != 0)
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = SinglePrecision;
- char* pDigits = stackalloc char[SingleNumberBufferLength];
+ byte* pDigits = stackalloc byte[SingleNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, pDigits, SingleNumberBufferLength);
switch (fmt)
// number using 7 digits and then determine if it round trips to the same value. If it does, we
// convert that NUMBER to a string, otherwise we reparse using 9 digits and display that.
DoubleToNumber(value, SinglePrecision, ref number);
+
if (number.Scale == ScaleNAN)
{
return info.NaNSymbol;
}
else if (number.Scale == ScaleINF)
{
- return number.Sign ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
+ return number.IsNegative ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
}
float roundTrip = NumberToSingle(ref number);
}
DoubleToNumber(value, precision, ref number);
+
if (number.Scale == ScaleNAN)
{
return info.NaNSymbol;
}
else if (number.Scale == ScaleINF)
{
- return number.Sign ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
+ return number.IsNegative ? info.NegativeInfinitySymbol : info.PositiveInfinitySymbol;
}
if (fmt != 0)
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[Int32NumberBufferLength];
+ byte* pDigits = stackalloc byte[Int32NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, Int32NumberBufferLength);
Int32ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[Int32NumberBufferLength];
+ byte* pDigits = stackalloc byte[Int32NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, Int32NumberBufferLength);
Int32ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[UInt32NumberBufferLength];
+ byte* pDigits = stackalloc byte[UInt32NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, UInt32NumberBufferLength);
UInt32ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[UInt32NumberBufferLength];
+ byte* pDigits = stackalloc byte[UInt32NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, UInt32NumberBufferLength);
UInt32ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[Int64NumberBufferLength];
+ byte* pDigits = stackalloc byte[Int64NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, Int64NumberBufferLength);
Int64ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[Int64NumberBufferLength];
+ byte* pDigits = stackalloc byte[Int64NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, Int64NumberBufferLength);
Int64ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[UInt64NumberBufferLength];
+ byte* pDigits = stackalloc byte[UInt64NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, UInt64NumberBufferLength);
UInt64ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
{
NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
- char* pDigits = stackalloc char[UInt64NumberBufferLength];
+ byte* pDigits = stackalloc byte[UInt64NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, UInt64NumberBufferLength);
UInt64ToNumber(value, ref number);
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ ValueStringBuilder sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
+
if (fmt != 0)
{
NumberToString(ref sb, ref number, fmt, digits, info);
[MethodImpl(MethodImplOptions.AggressiveInlining)] // called from only one location
private static unsafe void Int32ToNumber(int value, ref NumberBuffer number)
{
- number.Precision = Int32Precision;
+ number.DigitsCount = Int32Precision;
if (value >= 0)
{
- number.Sign = false;
+ number.IsNegative = false;
}
else
{
- number.Sign = true;
+ number.IsNegative = true;
value = -value;
}
- char* buffer = number.GetDigitsPointer();
- char* p = UInt32ToDecChars(buffer + Int32Precision, (uint)value, 0);
+ byte* buffer = number.GetDigitsPointer();
+ byte* p = UInt32ToDecChars(buffer + Int32Precision, (uint)value, 0);
+
int i = (int)(buffer + Int32Precision - p);
+ number.DigitsCount = i;
number.Scale = i;
- char* dst = number.GetDigitsPointer();
+ byte* dst = number.GetDigitsPointer();
while (--i >= 0)
*dst++ = *p++;
- *dst = '\0';
+ *dst = (byte)('\0');
+
+ number.CheckConsistency();
}
private static unsafe string NegativeInt32ToDecStr(int value, int digits, string sNegative)
[MethodImpl(MethodImplOptions.AggressiveInlining)] // called from only one location
private static unsafe void UInt32ToNumber(uint value, ref NumberBuffer number)
{
- number.Precision = UInt32Precision;
- number.Sign = false;
+ number.DigitsCount = UInt32Precision;
+ number.IsNegative = false;
+
+ byte* buffer = number.GetDigitsPointer();
+ byte* p = UInt32ToDecChars(buffer + UInt32Precision, value, 0);
- char* buffer = number.GetDigitsPointer();
- char* p = UInt32ToDecChars(buffer + UInt32Precision, value, 0);
int i = (int)(buffer + UInt32Precision - p);
+
+ number.DigitsCount = i;
number.Scale = i;
- char* dst = number.GetDigitsPointer();
+ byte* dst = number.GetDigitsPointer();
while (--i >= 0)
*dst++ = *p++;
- *dst = '\0';
+ *dst = (byte)('\0');
+
+ number.CheckConsistency();
+ }
+
+ internal static unsafe byte* UInt32ToDecChars(byte* bufferEnd, uint value, int digits)
+ {
+ while (--digits >= 0 || value != 0)
+ {
+ // TODO https://github.com/dotnet/coreclr/issues/3439
+ uint newValue = value / 10;
+ *(--bufferEnd) = (byte)(value - (newValue * 10) + '0');
+ value = newValue;
+ }
+ return bufferEnd;
}
internal static unsafe char* UInt32ToDecChars(char* bufferEnd, uint value, int digits)
private static unsafe void Int64ToNumber(long input, ref NumberBuffer number)
{
ulong value = (ulong)input;
- number.Sign = input < 0;
- number.Precision = Int64Precision;
- if (number.Sign)
+ number.IsNegative = input < 0;
+ number.DigitsCount = Int64Precision;
+ if (number.IsNegative)
{
value = (ulong)(-input);
}
- char* buffer = number.GetDigitsPointer();
- char* p = buffer + Int64Precision;
+ byte* buffer = number.GetDigitsPointer();
+ byte* p = buffer + Int64Precision;
while (High32(value) != 0)
p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
p = UInt32ToDecChars(p, Low32(value), 0);
+
int i = (int)(buffer + Int64Precision - p);
+ number.DigitsCount = i;
number.Scale = i;
- char* dst = number.GetDigitsPointer();
+ byte* dst = number.GetDigitsPointer();
while (--i >= 0)
*dst++ = *p++;
- *dst = '\0';
+ *dst = (byte)('\0');
+
+ number.CheckConsistency();
}
private static unsafe string NegativeInt64ToDecStr(long input, int digits, string sNegative)
private static unsafe void UInt64ToNumber(ulong value, ref NumberBuffer number)
{
- number.Precision = UInt64Precision;
- number.Sign = false;
+ number.DigitsCount = UInt64Precision;
+ number.IsNegative = false;
- char* buffer = number.GetDigitsPointer();
- char* p = buffer + UInt64Precision;
+ byte* buffer = number.GetDigitsPointer();
+ byte* p = buffer + UInt64Precision;
while (High32(value) != 0)
p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
p = UInt32ToDecChars(p, Low32(value), 0);
+
int i = (int)(buffer + UInt64Precision - p);
+ number.DigitsCount = i;
number.Scale = i;
- char* dst = number.GetDigitsPointer();
+ byte* dst = number.GetDigitsPointer();
while (--i >= 0)
*dst++ = *p++;
- *dst = '\0';
+ *dst = (byte)('\0');
+
+ number.CheckConsistency();
}
private static unsafe string UInt64ToDecStr(ulong value, int digits)
internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info)
{
- Debug.Assert(number.Kind != NumberBufferKind.Unknown);
+ number.CheckConsistency();
switch (format)
{
RoundNumber(ref number, number.Scale + nMaxDigits);
- if (number.Sign)
+ if (number.IsNegative)
sb.Append(info.NegativeSign);
FormatFixed(ref sb, ref number, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
RoundNumber(ref number, nMaxDigits);
- if (number.Sign)
+ if (number.IsNegative)
sb.Append(info.NegativeSign);
FormatScientific(ref sb, ref number, nMaxDigits, info, format);
else
{
// This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = number.Precision;
+ nMaxDigits = number.DigitsCount;
}
}
RoundNumber(ref number, nMaxDigits);
SkipRounding:
- if (number.Sign)
+ if (number.IsNegative)
sb.Append(info.NegativeSign);
FormatGeneral(ref sb, ref number, nMaxDigits, info, (char)(format - ('G' - 'E')), noRounding);
internal static unsafe void NumberToStringFormat(ref ValueStringBuilder sb, ref NumberBuffer number, ReadOnlySpan<char> format, NumberFormatInfo info)
{
- Debug.Assert(number.Kind != NumberBufferKind.Unknown);
+ number.CheckConsistency();
int digitCount;
int decimalPos;
int section;
int src;
- char* dig = number.GetDigitsPointer();
+ byte* dig = number.GetDigitsPointer();
char ch;
- section = FindSection(format, dig[0] == 0 ? 2 : number.Sign ? 1 : 0);
+ section = FindSection(format, dig[0] == 0 ? 2 : number.IsNegative ? 1 : 0);
while (true)
{
}
}
- if (number.Sign && (section == 0) && (number.Scale != 0))
+ if (number.IsNegative && (section == 0) && (number.Scale != 0))
sb.Append(info.NegativeSign);
bool decimalWritten = false;
fixed (char* pFormat = &MemoryMarshal.GetReference(format))
{
- char* cur = dig;
+ byte* cur = dig;
while (src < format.Length && (ch = pFormat[src++]) != 0 && ch != ';')
{
{
// digPos will be one greater than thousandsSepPos[thousandsSepCtr] since we are at
// the character after which the groupSeparator needs to be appended.
- sb.Append(*cur != 0 ? *cur++ : '0');
+ sb.Append(*cur != 0 ? (char)(*cur++) : '0');
if (thousandSeps && digPos > 1 && thousandsSepCtr >= 0)
{
if (digPos == thousandsSepPos[thousandsSepCtr] + 1)
}
else
{
- ch = *cur != 0 ? *cur++ : digPos > lastDigit ? '0' : '\0';
+ ch = *cur != 0 ? (char)(*cur++) : digPos > lastDigit ? '0' : '\0';
}
if (ch != 0)
{
}
}
- if (number.Sign && (section == 0) && (number.Scale == 0) && (sb.Length > 0))
+ if (number.IsNegative && (section == 0) && (number.Scale == 0) && (sb.Length > 0))
sb.Insert(0, info.NegativeSign);
}
private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
- string fmt = number.Sign ?
+ string fmt = number.IsNegative ?
s_negCurrencyFormats[info.CurrencyNegativePattern] :
s_posCurrencyFormats[info.CurrencyPositivePattern];
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.GetDigitsPointer();
+ byte* dig = number.GetDigitsPointer();
if (digPos > 0)
{
groupSizeIndex = 0;
int digitCount = 0;
- int digLength = string.wcslen(dig);
+ int digLength = number.DigitsCount;
int digStart = (digPos < digLength) ? digPos : digLength;
fixed (char* spanPtr = &MemoryMarshal.GetReference(sb.AppendSpan(bufferSize)))
{
char* p = spanPtr + bufferSize - 1;
for (int i = digPos - 1; i >= 0; i--)
{
- *(p--) = (i < digStart) ? dig[i] : '0';
+ *(p--) = (i < digStart) ? (char)(dig[i]) : '0';
if (groupSize > 0)
{
{
do
{
- sb.Append(*dig != 0 ? *dig++ : '0');
+ sb.Append(*dig != 0 ? (char)(*dig++) : '0');
}
while (--digPos > 0);
}
while (nMaxDigits > 0)
{
- sb.Append((*dig != 0) ? *dig++ : '0');
+ sb.Append((*dig != 0) ? (char)(*dig++) : '0');
nMaxDigits--;
}
}
private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
- string fmt = number.Sign ?
+ string fmt = number.IsNegative ?
s_negNumberFormats[info.NumberNegativePattern] :
PosNumberFormat;
private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar)
{
- char* dig = number.GetDigitsPointer();
+ byte* dig = number.GetDigitsPointer();
- sb.Append((*dig != 0) ? *dig++ : '0');
+ sb.Append((*dig != 0) ? (char)(*dig++) : '0');
if (nMaxDigits != 1) // For E0 we would like to suppress the decimal point
sb.Append(info.NumberDecimalSeparator);
while (--nMaxDigits > 0)
- sb.Append((*dig != 0) ? *dig++ : '0');
+ sb.Append((*dig != 0) ? (char)(*dig++) : '0');
int e = number.Digits[0] == 0 ? 0 : number.Scale - 1;
FormatExponent(ref sb, info, e, expChar, 3, true);
}
}
- char* dig = number.GetDigitsPointer();
+ byte* dig = number.GetDigitsPointer();
if (digPos > 0)
{
do
{
- sb.Append((*dig != 0) ? *dig++ : '0');
+ sb.Append((*dig != 0) ? (char)(*dig++) : '0');
} while (--digPos > 0);
}
else
}
while (*dig != 0)
- sb.Append(*dig++);
+ sb.Append((char)(*dig++));
}
if (scientific)
private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
- string fmt = number.Sign ?
+ string fmt = number.IsNegative ?
s_negPercentFormats[info.PercentNegativePattern] :
s_posPercentFormats[info.PercentPositivePattern];
private static unsafe void RoundNumber(ref NumberBuffer number, int pos)
{
- char* dig = number.GetDigitsPointer();
+ byte* dig = number.GetDigitsPointer();
int i = 0;
while (i < pos && dig[i] != 0)
else
{
number.Scale++;
- dig[0] = '1';
+ dig[0] = (byte)('1');
i = 1;
}
}
if (number.Kind == NumberBufferKind.Integer)
{
- number.Sign = false;
+ number.IsNegative = false;
}
}
- dig[i] = '\0';
+
+ dig[i] = (byte)('\0');
+ number.DigitsCount = i;
+ number.CheckConsistency();
}
private static unsafe int FindSection(ReadOnlySpan<char> format, int section)
private static unsafe void DoubleToNumber(double value, int precision, ref NumberBuffer number)
{
- number.Precision = precision;
-
if (!double.IsFinite(value))
{
number.Scale = double.IsNaN(value) ? ScaleNAN : ScaleINF;
- number.Sign = double.IsNegative(value);
- number.Digits[0] = '\0';
+ number.IsNegative = double.IsNegative(value);
+ number.Digits[0] = (byte)('\0');
}
else if (value == 0.0)
{
number.Scale = 0;
- number.Sign = double.IsNegative(value);
- number.Digits[0] = '\0';
+ number.IsNegative = double.IsNegative(value);
+ number.Digits[0] = (byte)('\0');
}
- else if (!Grisu3.Run(value, precision, ref number))
+ else
{
- Dragon4(value, precision, ref number);
+ number.DigitsCount = precision;
+
+ if (!Grisu3.Run(value, precision, ref number))
+ {
+ Dragon4(value, precision, ref number);
+ }
}
+
+ number.CheckConsistency();
}
private static long ExtractFractionAndBiasedExponent(double value, out int exponent)
private static unsafe bool TryNumberToInt32(ref NumberBuffer number, ref int value)
{
+ number.CheckConsistency();
+
int i = number.Scale;
- if (i > Int32Precision || i < number.Precision)
+ if (i > Int32Precision || i < number.DigitsCount)
{
return false;
}
- char* p = number.GetDigitsPointer();
+ byte* p = number.GetDigitsPointer();
Debug.Assert(p != null);
int n = 0;
while (--i >= 0)
n += (*p++ - '0');
}
}
- if (number.Sign)
+ if (number.IsNegative)
{
n = -n;
if (n > 0)
private static unsafe bool TryNumberToInt64(ref NumberBuffer number, ref long value)
{
+ number.CheckConsistency();
+
int i = number.Scale;
- if (i > Int64Precision || i < number.Precision)
+ if (i > Int64Precision || i < number.DigitsCount)
{
return false;
}
- char* p = number.GetDigitsPointer();
+ byte* p = number.GetDigitsPointer();
Debug.Assert(p != null);
long n = 0;
while (--i >= 0)
n += (*p++ - '0');
}
}
- if (number.Sign)
+ if (number.IsNegative)
{
n = -n;
if (n > 0)
private static unsafe bool TryNumberToUInt32(ref NumberBuffer number, ref uint value)
{
+ number.CheckConsistency();
+
int i = number.Scale;
- if (i > UInt32Precision || i < number.Precision || number.Sign)
+ if (i > UInt32Precision || i < number.DigitsCount || number.IsNegative)
{
return false;
}
- char* p = number.GetDigitsPointer();
+ byte* p = number.GetDigitsPointer();
Debug.Assert(p != null);
uint n = 0;
while (--i >= 0)
private static unsafe bool TryNumberToUInt64(ref NumberBuffer number, ref ulong value)
{
+ number.CheckConsistency();
+
int i = number.Scale;
- if (i > UInt64Precision || i < number.Precision || number.Sign)
+ if (i > UInt64Precision || i < number.DigitsCount || number.IsNegative)
{
return false;
}
- char* p = number.GetDigitsPointer();
+ byte* p = number.GetDigitsPointer();
Debug.Assert(p != null);
ulong n = 0;
while (--i >= 0)
const int StateDecimal = 0x0010;
const int StateCurrency = 0x0020;
- Debug.Assert(number.Precision == 0);
+ Debug.Assert(number.DigitsCount == 0);
Debug.Assert(number.Scale == 0);
- Debug.Assert(number.Sign == false);
+ Debug.Assert(number.IsNegative == false);
Debug.Assert(number.HasNonZeroTail == false);
- Debug.Assert(number.Kind != NumberBufferKind.Unknown);
+
+ number.CheckConsistency();
string decSep; // decimal separator from NumberFormatInfo.
string groupSep; // group separator from NumberFormatInfo.
// "-Kr 1231.47" is legal but "- 1231.47" is not.
if (!IsWhite(ch) || (styles & NumberStyles.AllowLeadingWhite) == 0 || ((state & StateSign) != 0 && ((state & StateCurrency) == 0 && info.NumberNegativePattern != 2)))
{
- if ((((styles & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || ((next = MatchChars(p, strEnd, info.NegativeSign)) != null && (number.Sign = true))))
+ if ((((styles & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || ((next = MatchChars(p, strEnd, info.NegativeSign)) != null && (number.IsNegative = true))))
{
state |= StateSign;
p = next - 1;
else if (ch == '(' && ((styles & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0))
{
state |= StateSign | StateParens;
- number.Sign = true;
+ number.IsNegative = true;
}
else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null)
{
{
if (digCount < maxDigCount)
{
- number.Digits[digCount++] = ch;
+ number.Digits[digCount++] = (byte)(ch);
if ((ch != '0') || (number.Kind != NumberBufferKind.Integer))
{
digEnd = digCount;
}
bool negExp = false;
- number.Precision = digEnd;
- number.Digits[digEnd] = '\0';
+ number.DigitsCount = digEnd;
+ number.Digits[digEnd] = (byte)('\0');
if ((state & StateDigits) != 0)
{
if ((ch == 'E' || ch == 'e') && ((styles & NumberStyles.AllowExponent) != 0))
{
if (!IsWhite(ch) || (styles & NumberStyles.AllowTrailingWhite) == 0)
{
- if (((styles & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || (((next = MatchChars(p, strEnd, info.NegativeSign)) != null) && (number.Sign = true))))
+ if (((styles & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || (((next = MatchChars(p, strEnd, info.NegativeSign)) != null) && (number.IsNegative = true))))
{
state |= StateSign;
p = next - 1;
}
if ((state & StateDecimal) == 0)
{
- number.Sign = false;
+ number.IsNegative = false;
}
}
str = p;
return TryParseUInt32HexNumberStyle(value, styles, out Unsafe.As<int, uint>(ref result), ref failureIsOverflow);
}
- char* pDigits = stackalloc char[Int32NumberBufferLength];
+ byte* pDigits = stackalloc byte[Int32NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, Int32NumberBufferLength);
if (!TryStringToNumber(value, styles, ref number, info))
return TryParseUInt64HexNumberStyle(value, styles, out Unsafe.As<long, ulong>(ref result), ref failureIsOverflow);
}
- char* pDigits = stackalloc char[Int64NumberBufferLength];
+ byte* pDigits = stackalloc byte[Int64NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, Int64NumberBufferLength);
if (!TryStringToNumber(value, styles, ref number, info))
return TryParseUInt32HexNumberStyle(value, styles, out result, ref failureIsOverflow);
}
- char* pDigits = stackalloc char[UInt32NumberBufferLength];
+ byte* pDigits = stackalloc byte[UInt32NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, UInt32NumberBufferLength);
if (!TryStringToNumber(value, styles, ref number, info))
return false;
}
-
if (!TryNumberToUInt32(ref number, ref result))
{
failureIsOverflow = true;
return TryParseUInt64HexNumberStyle(value, styles, out result, ref failureIsOverflow);
}
- char* pDigits = stackalloc char[UInt64NumberBufferLength];
+ byte* pDigits = stackalloc byte[UInt64NumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, UInt64NumberBufferLength);
if (!TryStringToNumber(value, styles, ref number, info))
return false;
}
-
if (!TryNumberToUInt64(ref number, ref result))
{
failureIsOverflow = true;
private static unsafe bool TryNumberToDecimal(ref NumberBuffer number, ref decimal value)
{
- char* p = number.GetDigitsPointer();
+ number.CheckConsistency();
+
+ byte* p = number.GetDigitsPointer();
int e = number.Scale;
- bool sign = number.Sign;
+ bool sign = number.IsNegative;
uint c = *p;
if (c == 0)
{
internal static unsafe bool TryParseDecimal(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out decimal result, out bool failureIsOverflow)
{
- char* pDigits = stackalloc char[DecimalNumberBufferLength];
+ byte* pDigits = stackalloc byte[DecimalNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, pDigits, DecimalNumberBufferLength);
result = 0;
internal static unsafe bool TryParseDouble(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out double result)
{
- char* pDigits = stackalloc char[DoubleNumberBufferLength];
+ byte* pDigits = stackalloc byte[DoubleNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, pDigits, DoubleNumberBufferLength);
if (!TryStringToNumber(value, styles, ref number, info))
internal static unsafe bool TryParseSingle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out float result)
{
- char* pDigits = stackalloc char[SingleNumberBufferLength];
+ byte* pDigits = stackalloc byte[SingleNumberBufferLength];
NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, pDigits, SingleNumberBufferLength);
if (!TryStringToNumber(value, styles, ref number, info))
if (!TryParseNumber(ref p, p + value.Length, styles, ref number, info)
|| (p - stringPointer < value.Length && !TrailingZeros(value, (int)(p - stringPointer))))
{
+ number.CheckConsistency();
return false;
}
}
+ number.CheckConsistency();
return true;
}
private static double NumberToDouble(ref NumberBuffer number)
{
+ number.CheckConsistency();
+
ulong bits = NumberToFloatingPointBits(ref number, in FloatingPointInfo.Double);
double result = BitConverter.Int64BitsToDouble((long)(bits));
- return number.Sign ? -result : result;
+ return number.IsNegative ? -result : result;
}
private static float NumberToSingle(ref NumberBuffer number)
{
+ number.CheckConsistency();
+
uint bits = (uint)(NumberToFloatingPointBits(ref number, in FloatingPointInfo.Single));
float result = BitConverter.Int32BitsToSingle((int)(bits));
- return number.Sign ? -result : result;
+ return number.IsNegative ? -result : result;
}
}
}