private static bool TrySkipIntegerDigits(string text, ref int pos, NumberStyles styles, NumberFormatInfo format) { if (pos == text.Length) { return(false); } var start = pos; if (format?.NumberDecimalSeparator != null && Skipper.TrySkip(text, ref pos, format.NumberDecimalSeparator)) { if (!IntReader.IsDigit(text, pos)) { pos = start; return(false); } pos = start; return(true); } if (!IntReader.IsDigit(text[pos])) { return(false); } while (pos < text.Length) { var i = text[pos] - '0'; if (i >= 0 && i <= 9) { pos++; continue; } if ((styles & NumberStyles.AllowThousands) != 0) { if (format?.NumberDecimalSeparator != null && Skipper.TrySkip(text, ref pos, format.NumberGroupSeparator)) { continue; } } break; } return(pos - start < 310); }
private static bool TrySkipExponent(string text, ref int pos) { if (Skipper.TrySkip(text, ref pos, 'E')) { return(true); } if (Skipper.TrySkip(text, ref pos, "e")) { return(true); } return(false); }
private static bool TryReadSign(string text, ref int pos, NumberFormatInfo format, out Sign sign) { if (Skipper.TrySkip(text, ref pos, format.PositiveSign)) { sign = Sign.Positive; return(true); } if (Skipper.TrySkip(text, ref pos, format.NegativeSign)) { sign = Sign.Negative; return(true); } sign = Sign.None; return(false); }
internal static bool TryRead( string text, ref int pos, NumberStyles style, IFormatProvider provider, out double result) { result = 0; var start = pos; if (string.IsNullOrEmpty(text)) { return(false); } if (!IsValidFloatingPointStyle(style)) { return(false); } if ((style & NumberStyles.AllowHexSpecifier) != 0) { return(false); } if ((style & NumberStyles.AllowLeadingWhite) != 0) { _ = WhiteSpaceReader.TryRead(text, ref pos); } if (char.IsWhiteSpace(text[pos])) { return(false); } if (TrySkipDoubleDigits(text, ref pos, style, provider)) { return(TryParseSubString(text, start, ref pos, style, provider, out result)); } if (provider is null) { provider = CultureInfo.CurrentCulture; } var format = NumberFormatInfo.GetInstance(provider); if (Skipper.TrySkip(text, ref pos, format.NaNSymbol)) { result = double.NaN; return(true); } if (Skipper.TrySkip(text, ref pos, format.PositiveInfinitySymbol)) { result = double.PositiveInfinity; return(true); } if (Skipper.TrySkip(text, ref pos, format.NegativeInfinitySymbol)) { result = double.NegativeInfinity; return(true); } pos = start; return(false); }
// Try parse a double from digits ignoring +-Inf and NaN private static bool TrySkipDoubleDigits( string text, ref int pos, NumberStyles style, IFormatProvider provider) { var start = pos; var format = NumberFormatInfo.GetInstance(provider); if (TryReadSign(text, ref pos, format, out _)) { if ((style & NumberStyles.AllowLeadingSign) == 0) { pos = start; return(false); } } if (!TrySkipIntegerDigits(text, ref pos, style, format)) { pos = start; return(false); } if (Skipper.TrySkip(text, ref pos, format.NumberDecimalSeparator)) { if ((style & NumberStyles.AllowDecimalPoint) == 0) { pos = start; return(false); } _ = TrySkipFractionDigits(text, ref pos); } if (TrySkipExponent(text, ref pos)) { if ((style & NumberStyles.AllowExponent) == 0) { pos = start; return(false); } _ = TryReadSign(text, ref pos, format, out var exponentSign); if (TrySkipExponentDigits(text, ref pos)) { return(true); } // This is a tricky spot we read digits followed by (sign) exponent // then no digits were thrown. I choose to return the double here. // Both alternatives will be wrong in some situations. // returning false here would make it impossible to parse 1.2eV var backStep = exponentSign == Sign.None ? 1 : 2; pos -= backStep; return(true); } return(true); }