Esempio n. 1
0
        internal static bool Parse(string s, bool tryParse, out uint result, out Exception exc)
        {
            uint val = 0;
            int  len;
            int  i;
            bool digits_seen       = false;
            bool has_negative_sign = false;

            result = 0;
            exc    = null;

            if (s == null)
            {
                if (!tryParse)
                {
                    exc = new ArgumentNullException("s");
                }
                return(false);
            }

            len = s.Length;

            char c;

            for (i = 0; i < len; i++)
            {
                c = s[i];
                if (!Char.IsWhiteSpace(c))
                {
                    break;
                }
            }

            if (i == len)
            {
                if (!tryParse)
                {
                    exc = ParseHelper.GetFormatException();
                }
                return(false);
            }

            if (s[i] == '+')
            {
                i++;
            }
            else
            if (s[i] == '-')
            {
                i++;
                has_negative_sign = true;
            }

            for (; i < len; i++)
            {
                c = s[i];

                if (c >= '0' && c <= '9')
                {
                    uint d = (uint)(c - '0');

                    if ((val > MaxValue / 10) || (val == (MaxValue / 10) && d > (MaxValue % 10)))
                    {
                        if (!tryParse)
                        {
                            exc = new OverflowException(String.Format("Value is too large"));
                        }
                        return(false);
                    }
                    val         = (val * 10) + d;
                    digits_seen = true;
                }
                else if (!ParseHelper.ProcessTrailingWhitespace(tryParse, s, i, ref exc))
                {
                    return(false);
                }
            }
            if (!digits_seen)
            {
                if (!tryParse)
                {
                    exc = ParseHelper.GetFormatException();
                }
                return(false);
            }

            // -0 is legal but other negative values are not
            if (has_negative_sign && (val > 0))
            {
                if (!tryParse)
                {
                    exc = new OverflowException(
                        String.Format("Negative number"));
                }
                return(false);
            }

            result = val;
            return(true);
        }
Esempio n. 2
0
        internal static bool Parse(string s, NumberStyles style, IFormatProvider provider, bool tryParse, out uint result, out Exception exc)
        {
            result = 0;
            exc    = null;

            if (s == null)
            {
                if (!tryParse)
                {
                    exc = new ArgumentNullException("s");
                }
                return(false);
            }

            if (s.Length == 0)
            {
                if (!tryParse)
                {
                    exc = ParseHelper.GetFormatException();
                }
                return(false);
            }

            NumberFormatInfo nfi = null;

            if (provider != null)
            {
                Type typeNFI = typeof(NumberFormatInfo);
                nfi = (NumberFormatInfo)provider.GetFormat(typeNFI);
            }
            if (nfi == null)
            {
                nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
            }

            if (!ParseHelper.CheckStyle(style, tryParse, ref exc))
            {
                return(false);
            }

            bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
            bool AllowHexSpecifier   = (style & NumberStyles.AllowHexSpecifier) != 0;
            bool AllowThousands      = (style & NumberStyles.AllowThousands) != 0;
            bool AllowDecimalPoint   = (style & NumberStyles.AllowDecimalPoint) != 0;
            bool AllowParentheses    = (style & NumberStyles.AllowParentheses) != 0;
            bool AllowTrailingSign   = (style & NumberStyles.AllowTrailingSign) != 0;
            bool AllowLeadingSign    = (style & NumberStyles.AllowLeadingSign) != 0;
            bool AllowTrailingWhite  = (style & NumberStyles.AllowTrailingWhite) != 0;
            bool AllowLeadingWhite   = (style & NumberStyles.AllowLeadingWhite) != 0;

            int pos = 0;

            if (AllowLeadingWhite && !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
            {
                return(false);
            }

            bool foundOpenParentheses = false;
            bool negative             = false;
            bool foundSign            = false;
            bool foundCurrency        = false;

            // Pre-number stuff
            if (AllowParentheses && s[pos] == '(')
            {
                foundOpenParentheses = true;
                foundSign            = true;
                negative             = true; // MS always make the number negative when there parentheses
                // even when NumberFormatInfo.NumberNegativePattern != 0!!!
                pos++;
                if (AllowLeadingWhite && !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                {
                    return(false);
                }

                if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
                {
                    if (!tryParse)
                    {
                        exc = ParseHelper.GetFormatException();
                    }
                    return(false);
                }
                if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
                {
                    if (!tryParse)
                    {
                        exc = ParseHelper.GetFormatException();
                    }
                    return(false);
                }
            }

            if (AllowLeadingSign && !foundSign)
            {
                // Sign + Currency
                ParseHelper.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                if (foundSign)
                {
                    if (AllowLeadingWhite && !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (AllowCurrencySymbol)
                    {
                        ParseHelper.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                        if (foundCurrency && AllowLeadingWhite &&
                            !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                        {
                            return(false);
                        }
                    }
                }
            }

            if (AllowCurrencySymbol && !foundCurrency)
            {
                // Currency + sign
                ParseHelper.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                if (foundCurrency)
                {
                    if (AllowLeadingWhite && !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (foundCurrency)
                    {
                        if (!foundSign && AllowLeadingSign)
                        {
                            ParseHelper.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                            if (foundSign && AllowLeadingWhite &&
                                !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                            {
                                return(false);
                            }
                        }
                    }
                }
            }

            uint number            = 0;
            int  nDigits           = 0;
            bool decimalPointFound = false;
            uint digitValue;
            char hexDigit;

            // Number stuff
            // Just the same as Int32, but this one adds instead of substract
            do
            {
                if (!ParseHelper.ValidDigit(s[pos], AllowHexSpecifier))
                {
                    if (AllowThousands && ParseHelper.FindOther(ref pos, s, nfi.NumberGroupSeparator))
                    {
                        continue;
                    }
                    else
                    if (!decimalPointFound && AllowDecimalPoint &&
                        ParseHelper.FindOther(ref pos, s, nfi.NumberDecimalSeparator))
                    {
                        decimalPointFound = true;
                        continue;
                    }
                    break;
                }
                else if (AllowHexSpecifier)
                {
                    nDigits++;
                    hexDigit = s[pos++];
                    if (Char.IsDigit(hexDigit))
                    {
                        digitValue = (uint)(hexDigit - '0');
                    }
                    else if (Char.IsLower(hexDigit))
                    {
                        digitValue = (uint)(hexDigit - 'a' + 10);
                    }
                    else
                    {
                        digitValue = (uint)(hexDigit - 'A' + 10);
                    }

                    if (tryParse)
                    {
                        ulong l = number * 16 + digitValue;

                        if (l > MaxValue)
                        {
                            return(false);
                        }
                        number = (uint)l;
                    }
                    else
                    {
                        number = checked (number * 16 + digitValue);
                    }
                }
                else if (decimalPointFound)
                {
                    nDigits++;
                    // Allows decimal point as long as it's only
                    // followed by zeroes.
                    if (s[pos++] != '0')
                    {
                        if (!tryParse)
                        {
                            exc = new OverflowException(String.Format("Value too large or too small."));
                        }
                        return(false);
                    }
                }
                else
                {
                    nDigits++;

                    try
                    {
                        number = checked (number * 10 + (uint)(s[pos++] - '0'));
                    }
                    catch (OverflowException)
                    {
                        if (!tryParse)
                        {
                            exc = new OverflowException(String.Format("Value too large or too small."));
                        }
                        return(false);
                    }
                }
            } while (pos < s.Length);

            // Post number stuff
            if (nDigits == 0)
            {
                if (!tryParse)
                {
                    exc = ParseHelper.GetFormatException();
                }
                return(false);
            }

            if (AllowTrailingSign && !foundSign)
            {
                // Sign + Currency
                ParseHelper.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                if (foundSign)
                {
                    if (AllowTrailingWhite && !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (AllowCurrencySymbol)
                    {
                        ParseHelper.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                    }
                }
            }

            if (AllowCurrencySymbol && !foundCurrency)
            {
                // Currency + sign
                ParseHelper.FindCurrency(ref pos, s, nfi, ref foundCurrency);
                if (foundCurrency)
                {
                    if (AllowTrailingWhite && !ParseHelper.JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                    {
                        return(false);
                    }
                    if (!foundSign && AllowTrailingSign)
                    {
                        ParseHelper.FindSign(ref pos, s, nfi, ref foundSign, ref negative);
                    }
                }
            }

            if (AllowTrailingWhite && pos < s.Length && !ParseHelper.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
            {
                return(false);
            }

            if (foundOpenParentheses)
            {
                if (pos >= s.Length || s[pos++] != ')')
                {
                    if (!tryParse)
                    {
                        exc = ParseHelper.GetFormatException();
                    }
                    return(false);
                }
                if (AllowTrailingWhite && pos < s.Length && !ParseHelper.JumpOverWhite(ref pos, s, false, tryParse, ref exc))
                {
                    return(false);
                }
            }

            if (pos < s.Length && s[pos] != '\u0000')
            {
                if (!tryParse)
                {
                    exc = ParseHelper.GetFormatException();
                }
                return(false);
            }

            // -0 is legal but other negative values are not
            if (negative && (number > 0))
            {
                if (!tryParse)
                {
                    exc = new OverflowException(
                        String.Format("Negative number"));
                }
                return(false);
            }

            result = number;

            return(true);
        }