示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        // 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);
        }