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 = Int32.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 (!Int32.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; bool AllowExponent = (style & NumberStyles.AllowExponent) != 0; int pos = 0; if (AllowLeadingWhite && !Int32.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 && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } if (AllowLeadingSign && !foundSign) { // Sign + Currency Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign) { if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (AllowCurrencySymbol) { Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency && AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } } if (AllowCurrencySymbol && !foundCurrency) { // Currency + sign Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency) { if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (foundCurrency) { if (!foundSign && AllowLeadingSign) { Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign && AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } } } uint number = 0; int nDigits = 0; int decimalPointPos = -1; uint digitValue; char hexDigit; // Number stuff // Just the same as Int32, but this one adds instead of substract while (pos < s.Length) { if (!Int32.ValidDigit(s [pos], AllowHexSpecifier)) { if (AllowThousands && (Int32.FindOther(ref pos, s, nfi.NumberGroupSeparator) || Int32.FindOther(ref pos, s, nfi.CurrencyGroupSeparator))) { continue; } if (AllowDecimalPoint && decimalPointPos < 0 && (Int32.FindOther(ref pos, s, nfi.NumberDecimalSeparator) || Int32.FindOther(ref pos, s, nfi.CurrencyDecimalSeparator))) { decimalPointPos = nDigits; continue; } break; } nDigits++; if (AllowHexSpecifier) { 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); } continue; } try { number = checked (number * 10 + (uint)(s [pos++] - '0')); } catch (OverflowException) { if (!tryParse) { exc = new OverflowException(Locale.GetText("Value too large or too small.")); } return(false); } } // Post number stuff if (nDigits == 0) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } int exponent = 0; if (AllowExponent) { if (Int32.FindExponent(ref pos, s, ref exponent, tryParse, ref exc) && exc != null) { return(false); } } if (AllowTrailingSign && !foundSign) { // Sign + Currency Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign && pos < s.Length) { if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } if (AllowCurrencySymbol && !foundCurrency) { if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } // Currency + sign Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency && pos < s.Length) { if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (!foundSign && AllowTrailingSign) { Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); } } } if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } if (foundOpenParentheses) { if (pos >= s.Length || s [pos++] != ')') { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } } if (pos < s.Length && s [pos] != '\u0000') { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } // -0 is legal but other negative values are not if (negative && (number > 0)) { if (!tryParse) { exc = new OverflowException( Locale.GetText("Negative number")); } return(false); } if (decimalPointPos >= 0) { exponent = exponent - nDigits + decimalPointPos; } if (exponent < 0) { // // Any non-zero values after decimal point are not allowed // long remainder; number = (uint)Math.DivRem(number, (int)Math.Pow(10, -exponent), out remainder); if (remainder != 0) { if (!tryParse) { exc = new OverflowException("Value too large or too small."); } return(false); } } else if (exponent > 0) { // // result *= 10^exponent // // Reduce the risk of throwing an overflow exc // double res = checked (Math.Pow(10, exponent) * number); if (res < MinValue || res > MaxValue) { if (!tryParse) { exc = new OverflowException("Value too large or too small."); } return(false); } number = (uint)res; } result = number; return(true); }
internal static bool Parse(string s, NumberStyles style, IFormatProvider fp, bool tryParse, out long 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 = Int32.GetFormatException(); } return(false); } NumberFormatInfo nfi = null; if (fp != null) { Type typeNFI = typeof(System.Globalization.NumberFormatInfo); nfi = (NumberFormatInfo)fp.GetFormat(typeNFI); } if (nfi == null) { nfi = Thread.CurrentThread.CurrentCulture.NumberFormat; } if (!Int32.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; bool AllowExponent = (style & NumberStyles.AllowExponent) != 0; int pos = 0; if (AllowLeadingWhite && !Int32.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 && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } if (AllowLeadingSign && !foundSign) { // Sign + Currency Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign) { if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (AllowCurrencySymbol) { Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency && AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } } if (AllowCurrencySymbol && !foundCurrency) { // Currency + sign Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency) { if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (foundCurrency) { if (!foundSign && AllowLeadingSign) { Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign && AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } } } long number = 0; int nDigits = 0; bool decimalPointFound = false; int digitValue; char hexDigit; int exponent = 0; // Number stuff do { if (!Int32.ValidDigit(s [pos], AllowHexSpecifier)) { if (AllowThousands && (Int32.FindOther(ref pos, s, nfi.NumberGroupSeparator) || Int32.FindOther(ref pos, s, nfi.CurrencyGroupSeparator))) { continue; } else if (!decimalPointFound && AllowDecimalPoint && (Int32.FindOther(ref pos, s, nfi.NumberDecimalSeparator) || Int32.FindOther(ref pos, s, nfi.CurrencyDecimalSeparator))) { decimalPointFound = true; continue; } break; } if (AllowHexSpecifier) { nDigits++; hexDigit = s [pos++]; if (Char.IsDigit(hexDigit)) { digitValue = (int)(hexDigit - '0'); } else if (Char.IsLower(hexDigit)) { digitValue = (int)(hexDigit - 'a' + 10); } else { digitValue = (int)(hexDigit - 'A' + 10); } ulong unumber = (ulong)number; // IMPROVME: We could avoid catching OverflowException try { number = (long)checked (unumber * 16ul + (ulong)digitValue); } catch (OverflowException e) { if (!tryParse) { exc = e; } return(false); } } 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("Value too large or too " + "small."); } return(false); } } else { nDigits++; try { // Calculations done as negative // (abs (MinValue) > abs (MaxValue)) number = checked ( number * 10 - (long)(s [pos++] - '0') ); } catch (OverflowException) { if (!tryParse) { exc = new OverflowException("Value too large or too " + "small."); } return(false); } } } while (pos < s.Length); // Post number stuff if (nDigits == 0) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (AllowExponent) { if (Int32.FindExponent(ref pos, s, ref exponent, tryParse, ref exc) && exc != null) { return(false); } } if (AllowTrailingSign && !foundSign) { // Sign + Currency Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign && pos < s.Length) { if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } if (AllowCurrencySymbol && !foundCurrency) { if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } // Currency + sign Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency && pos < s.Length) { if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (!foundSign && AllowTrailingSign) { Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); } } } if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } if (foundOpenParentheses) { if (pos >= s.Length || s [pos++] != ')') { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } } if (pos < s.Length && s [pos] != '\u0000') { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (!negative && !AllowHexSpecifier) { try { number = checked (-number); } catch (OverflowException e) { if (!tryParse) { exc = e; } return(false); } } // result *= 10^exponent if (exponent > 0) { // Reduce the risk of throwing an overflow exc double res = checked (Math.Pow(10, exponent) * number); if (res < Int32.MinValue || res > Int32.MaxValue) { if (!tryParse) { exc = new OverflowException("Value too large or too small."); } return(false); } number = (long)res; } result = number; return(true); }
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 = Int32.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(Locale.GetText("Value is too large")); } return(false); } val = (val * 10) + d; digits_seen = true; } else if (!Int32.ProcessTrailingWhitespace(tryParse, s, i, ref exc)) { return(false); } } if (!digits_seen) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } // -0 is legal but other negative values are not if (has_negative_sign && (val > 0)) { if (!tryParse) { exc = new OverflowException( Locale.GetText("Negative number")); } return(false); } result = val; return(true); }
// FIXME: check if digits are group in correct numbers between the group separators internal static bool Parse(string s, NumberStyles style, IFormatProvider provider, bool tryParse, out double 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 = new FormatException(); } return(false); } // yes it's counter intuitive (buggy?) but even TryParse actually throws in this case if ((style & NumberStyles.AllowHexSpecifier) != 0) { string msg = Locale.GetText("Double doesn't support parsing with '{0}'.", "AllowHexSpecifier"); throw new ArgumentException(msg); } if (style > NumberStyles.Any) { if (!tryParse) { exc = new ArgumentException(); } return(false); } NumberFormatInfo format = NumberFormatInfo.GetInstance(provider); if (format == null) { throw new Exception("How did this happen?"); } // // validate and prepare string for C // int len = s.Length; int didx = 0; int sidx = 0; char c; bool allow_leading_white = (style & NumberStyles.AllowLeadingWhite) != 0; bool allow_trailing_white = ((style & NumberStyles.AllowTrailingWhite) != 0); if (allow_leading_white) { while (sidx < len && Char.IsWhiteSpace(s [sidx])) { sidx++; } if (sidx == len) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } int sEndPos = s.Length - 1; if (allow_trailing_white) { while (Char.IsWhiteSpace(s [sEndPos])) { sEndPos--; } } if (TryParseStringConstant(format.NaNSymbol, s, sidx, sEndPos)) { result = double.NaN; return(true); } if (TryParseStringConstant(format.PositiveInfinitySymbol, s, sidx, sEndPos)) { result = double.PositiveInfinity; return(true); } if (TryParseStringConstant(format.NegativeInfinitySymbol, s, sidx, sEndPos)) { result = double.NegativeInfinity; return(true); } byte [] b = new byte [len + 1]; // // Machine state // var state = ParseState.AllowSign; // // Setup // string decimal_separator = null; string group_separator = null; string currency_symbol = null; int decimal_separator_len = 0; int group_separator_len = 0; int currency_symbol_len = 0; if ((style & NumberStyles.AllowDecimalPoint) != 0) { decimal_separator = format.NumberDecimalSeparator; decimal_separator_len = decimal_separator.Length; } if ((style & NumberStyles.AllowThousands) != 0) { group_separator = format.NumberGroupSeparator; group_separator_len = group_separator.Length; } if ((style & NumberStyles.AllowCurrencySymbol) != 0) { currency_symbol = format.CurrencySymbol; currency_symbol_len = currency_symbol.Length; } string positive = format.PositiveSign; string negative = format.NegativeSign; bool allow_trailing_parenthes = false; for (; sidx < len; sidx++) { c = s [sidx]; if (c == '\0') { sidx = len; continue; } switch (state) { case ParseState.AllowSign: if ((style & NumberStyles.AllowLeadingSign) != 0) { if (c == positive [0] && s.Substring(sidx, positive.Length) == positive) { state = ParseState.Digits; sidx += positive.Length - 1; continue; } if (c == negative [0] && s.Substring(sidx, negative.Length) == negative) { state = ParseState.Digits; b [didx++] = (byte)'-'; sidx += negative.Length - 1; continue; } } if ((style & NumberStyles.AllowParentheses) != 0 && c == '(') { b [didx++] = (byte)'-'; state = ParseState.Digits; allow_trailing_parenthes = true; continue; } state = ParseState.Digits; goto case ParseState.Digits; case ParseState.Digits: if (Char.IsDigit(c)) { b [didx++] = (byte)c; break; } if (c == 'e' || c == 'E') { goto case ParseState.Decimal; } if (allow_trailing_parenthes && c == ')') { allow_trailing_parenthes = false; state = ParseState.ConsumeWhiteSpace; continue; } if (decimal_separator_len > 0 && decimal_separator [0] == c) { if (String.CompareOrdinal(s, sidx, decimal_separator, 0, decimal_separator_len) == 0) { b [didx++] = (byte)'.'; sidx += decimal_separator_len - 1; state = ParseState.Decimal; break; } } if (group_separator_len > 0 && group_separator [0] == c) { if (s.Substring(sidx, group_separator_len) == group_separator) { sidx += group_separator_len - 1; break; } } if (currency_symbol_len > 0 && currency_symbol [0] == c) { if (s.Substring(sidx, currency_symbol_len) == currency_symbol) { sidx += currency_symbol_len - 1; currency_symbol_len = 0; break; } } state = ParseState.TrailingSymbols; goto case ParseState.TrailingSymbols; case ParseState.Decimal: if (Char.IsDigit(c)) { b [didx++] = (byte)c; break; } if (c == 'e' || c == 'E') { if ((style & NumberStyles.AllowExponent) == 0) { if (!tryParse) { exc = new FormatException("Unknown char: " + c); } return(false); } b [didx++] = (byte)c; state = ParseState.ExponentSign; break; } state = ParseState.TrailingSymbols; goto case ParseState.TrailingSymbols; case ParseState.ExponentSign: if (Char.IsDigit(c)) { state = ParseState.Exponent; goto case ParseState.Exponent; } if (c == positive [0] && s.Substring(sidx, positive.Length) == positive) { state = ParseState.Digits; sidx += positive.Length - 1; continue; } if (c == negative [0] && s.Substring(sidx, negative.Length) == negative) { state = ParseState.Digits; b [didx++] = (byte)'-'; sidx += negative.Length - 1; continue; } goto case ParseState.ConsumeWhiteSpace; case ParseState.Exponent: if (Char.IsDigit(c)) { b [didx++] = (byte)c; break; } state = ParseState.TrailingSymbols; goto case ParseState.TrailingSymbols; case ParseState.TrailingSymbols: if ((style & NumberStyles.AllowTrailingSign) != 0) { if (positive != null && c == positive [0] && s.Substring(sidx, positive.Length) == positive) { state = ParseState.ConsumeWhiteSpace; sidx += positive.Length - 1; allow_trailing_parenthes = false; positive = null; continue; } if (negative != null && c == negative [0] && s.Substring(sidx, negative.Length) == negative) { state = ParseState.ConsumeWhiteSpace; Array.Copy(b, 0, b, 1, didx); b [0] = (byte)'-'; ++didx; sidx += negative.Length - 1; allow_trailing_parenthes = false; negative = null; continue; } } if (currency_symbol_len > 0 && currency_symbol [0] == c) { if (s.Substring(sidx, currency_symbol_len) == currency_symbol) { sidx += currency_symbol_len - 1; currency_symbol_len = 0; break; } } if (allow_trailing_white && Char.IsWhiteSpace(c)) { break; } goto case ParseState.ConsumeWhiteSpace; case ParseState.ConsumeWhiteSpace: if (allow_trailing_parenthes && c == ')') { allow_trailing_parenthes = false; state = ParseState.ConsumeWhiteSpace; break; } if (allow_trailing_white && Char.IsWhiteSpace(c)) { state = ParseState.ConsumeWhiteSpace; break; } if (!tryParse) { exc = new FormatException("Unknown char"); } return(false); } if (state == ParseState.Exit) { break; } } b [didx] = 0; unsafe { fixed(byte *p = &b[0]) { double retVal; if (!ParseImpl(p, out retVal)) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (IsPositiveInfinity(retVal) || IsNegativeInfinity(retVal)) { if (!tryParse) { exc = new OverflowException(); } return(false); } result = retVal; return(true); } } }
internal static bool Parse(string s, bool tryParse, out long result, out Exception exc) { long val = 0; int len; int i, sign = 1; bool digits_seen = false; result = 0; exc = null; NumberFormatInfo nfi = Thread.CurrentThread.CurrentCulture.NumberFormat; 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 = Int32.GetFormatException(); } return(false); } if (String.Compare(s, i, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) { i += nfi.PositiveSign.Length; } else if (String.Compare(s, i, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) { sign = -1; i += nfi.NegativeSign.Length; } for (; i < len; i++) { c = s [i]; if (c >= '0' && c <= '9') { byte d = (byte)(c - '0'); if (val > (MaxValue / 10)) { goto overflow; } if (val == (MaxValue / 10)) { if ((d > (MaxValue % 10)) && (sign == 1 || (d > ((MaxValue % 10) + 1)))) { goto overflow; } if (sign == -1) { val = (val * sign * 10) - d; } else { val = (val * 10) + d; } if (Int32.ProcessTrailingWhitespace(tryParse, s, i + 1, ref exc)) { result = val; return(true); } goto overflow; } else { val = val * 10 + d; } digits_seen = true; } else if (!Int32.ProcessTrailingWhitespace(tryParse, s, i, ref exc)) { return(false); } } if (!digits_seen) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (sign == -1) { result = val * sign; } else { result = val; } return(true); overflow: if (!tryParse) { exc = new OverflowException("Value is too large"); } return(false); }
internal static bool Parse(string s, bool tryParse, out short result, out Exception exc) { short val = 0; int len; int i, sign = 1; bool digits_seen = 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 = Int32.GetFormatException(); } return(false); } c = s [i]; if (c == '+') { i++; } else if (c == '-') { sign = -1; i++; } for (; i < len; i++) { c = s [i]; if (c >= '0' && c <= '9') { byte d = (byte)(c - '0'); if (val > (MaxValue / 10)) { goto overflow; } if (val == (MaxValue / 10)) { if ((d > (MaxValue % 10)) && (sign == 1 || (d > ((MaxValue % 10) + 1)))) { goto overflow; } if (sign == -1) { val = (short)((val * sign * 10) - d); } else { val = (short)((val * 10) + d); } if (Int32.ProcessTrailingWhitespace(tryParse, s, i + 1, ref exc)) { result = val; return(true); } goto overflow; } else { val = (short)(val * 10 + d); } digits_seen = true; } else if (!Int32.ProcessTrailingWhitespace(tryParse, s, i, ref exc)) { return(false); } } if (!digits_seen) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (sign == -1) { result = (short)(val * sign); } else { result = val; } return(true); overflow: if (!tryParse) { exc = new OverflowException("Value is too large"); } return(false); }
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 = Int32.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 (!Int32.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 && !Int32.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 && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (s.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } if (AllowLeadingSign && !foundSign) { // Sign + Currency Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign) { if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (AllowCurrencySymbol) { Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency && AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } } } } if (AllowCurrencySymbol && !foundCurrency) { // Currency + sign Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency) { if (AllowLeadingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (foundCurrency) { if (!foundSign && AllowLeadingSign) { Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign && AllowLeadingWhite && !Int32.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 (!Int32.ValidDigit(s [pos], AllowHexSpecifier)) { if (AllowThousands && Int32.FindOther(ref pos, s, nfi.NumberGroupSeparator)) { continue; } else if (!decimalPointFound && AllowDecimalPoint && Int32.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(Locale.GetText("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(Locale.GetText("Value too large or too small.")); } return(false); } } } while (pos < s.Length); // Post number stuff if (nDigits == 0) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (AllowTrailingSign && !foundSign) { // Sign + Currency Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); if (foundSign) { if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (AllowCurrencySymbol) { Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); } } } if (AllowCurrencySymbol && !foundCurrency) { // Currency + sign Int32.FindCurrency(ref pos, s, nfi, ref foundCurrency); if (foundCurrency) { if (AllowTrailingWhite && !Int32.JumpOverWhite(ref pos, s, true, tryParse, ref exc)) { return(false); } if (!foundSign && AllowTrailingSign) { Int32.FindSign(ref pos, s, nfi, ref foundSign, ref negative); } } } if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } if (foundOpenParentheses) { if (pos >= s.Length || s [pos++] != ')') { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite(ref pos, s, false, tryParse, ref exc)) { return(false); } } if (pos < s.Length && s [pos] != '\u0000') { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } // -0 is legal but other negative values are not if (negative && (number > 0)) { if (!tryParse) { exc = new OverflowException( Locale.GetText("Negative number")); } return(false); } result = number; return(true); }
internal static bool Parse(string s, bool tryParse, out ulong result, out Exception exc) { ulong val = 0; int len; int i; bool digits_seen = false; bool has_negative_sign = false; exc = null; result = 0; 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 = Int32.GetFormatException(); } return(false); } if (s [i] == '+') { i++; } else if (s [i] == '-') { i++; has_negative_sign = true; } // Actual number stuff 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("Value is too large."); } return(false); } val = (val * 10) + d; digits_seen = true; } else if (!Int32.ProcessTrailingWhitespace(tryParse, s, i, ref exc)) { return(false); } } if (!digits_seen) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } if (has_negative_sign && val > 0) { if (!tryParse) { exc = new OverflowException("Negative number."); } return(false); } result = val; return(true); }
internal static bool Parse(string s, bool tryParse, out sbyte result, out Exception exc) { int ival = 0; int len; int i; bool neg = false; bool digits_seen = 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 = Int32.GetFormatException(); } return(false); } c = s [i]; if (c == '+') { i++; } else if (c == '-') { neg = true; i++; } for (; i < len; i++) { c = s [i]; if (c >= '0' && c <= '9') { if (tryParse) { int intval = ival * 10 - (int)(c - '0'); if (intval < MinValue) { return(false); } ival = (sbyte)intval; } else { ival = checked (ival * 10 - (int)(c - '0')); } digits_seen = true; } else { if (Char.IsWhiteSpace(c)) { for (i++; i < len; i++) { if (!Char.IsWhiteSpace(s [i])) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } break; } else { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } } if (!digits_seen) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } ival = neg ? ival : -ival; if (ival < SByte.MinValue || ival > SByte.MaxValue) { if (!tryParse) { exc = new OverflowException(); } return(false); } result = (sbyte)ival; return(true); }
internal static bool Parse(string s, bool tryParse, out long result, out Exception exc) { long val = 0; int len; int i; int sign = 1; bool digits_seen = 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 = Int32.GetFormatException(); } return(false); } c = s[i]; if (c == '+') { i++; } else if (c == '-') { sign = -1; i++; } for (; i < len; i++) { c = s[i]; if (c >= '0' && c <= '9') { if (tryParse) { val = val * 10 + (c - '0') * sign; if (sign == 1) { if (val < 0) { return(false); } } else if (val > 0) { return(false); } } else { val = checked (val * 10 + (c - '0') * sign); } digits_seen = true; } else { if (Char.IsWhiteSpace(c)) { for (i++; i < len; i++) { if (!Char.IsWhiteSpace(s[i])) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } break; } else { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } } } if (!digits_seen) { if (!tryParse) { exc = Int32.GetFormatException(); } return(false); } result = val; return(true); }