Exemple #1
0
        public void Indent1SuccessTest()
        {
            var toks    = Seq(new Tok(1, 1, 'a'), new Tok(2, 1, 'b'), new Tok(2, 2, 'c'), new Tok(1, 3, 'd'), new Tok(1, 4, '1'));
            var letter  = satisfy <Tok>(t => Char.IsLetter(t.Val));
            var digit   = satisfy <Tok>(t => Char.IsDigit(t.Val));
            var letters = many1(attempt(letter));
            var digits  = many1(attempt(digit));

            var block = from ls1 in indented1 <Tok, Seq <Tok> >(letters)
                        from ls2 in indented1 <Tok, Seq <Tok> >(letters)
                        from dg1 in indented1 <Tok, Seq <Tok> >(digits)
                        from ___ in eof <Tok>()
                        select(ls1, ls2, dg1);

            var res = block.Parse(toks, t => new Pos(t.Ln - 1, t.Col - 1)).ToEither().IfLeft(() => default);
        /// <summary>
        /// Gets the version specified in the text declaration.
        /// </summary>
        /// <param name="c">The character.</param>
        /// <param name="decl">The current declaration.</param>
        /// <returns>The token.</returns>
        DtdToken TextDeclVersion(Char c, DtdDeclToken decl)
        {
            if (c == Specification.EQ)
            {
                var q = _stream.Next;

                if (q == Specification.DQ || q == Specification.SQ)
                {
                    _stringBuffer.Clear();
                    c = _stream.Next;

                    while (c.IsDigit() || c == Specification.DOT)
                    {
                        _stringBuffer.Append(c);
                        c = _stream.Next;
                    }

                    if (c == q)
                    {
                        decl.Version = _stringBuffer.ToString();
                        return TextDeclBetween(_stream.Next, decl);
                    }
                }
            }

            throw Errors.Xml(ErrorCode.DtdTextDeclInvalid);
        }
Exemple #3
0
        /// <summary>
        /// See 8.2.4.69 Tokenizing character references
        /// </summary>
        /// <param name="c">The next input character.</param>
        /// <param name="allowedCharacter">The additionally allowed character if there is one.</param>
        String CharacterReference(Char c, Char allowedCharacter = Specification.NULL)
        {
            if (c.IsSpaceCharacter() || c == Specification.LT || c == Specification.EOF || c == Specification.AMPERSAND || c == allowedCharacter)
            {
                _src.Back();
                return null;
            }

            if (c == Specification.NUM)
            {
                var exp = 10;
                var basis = 1;
                var num = 0;
                var nums = new List<Int32>();
                c = _src.Next;
                var isHex = c == 'x' || c == 'X';

                if (isHex)
                {
                    exp = 16;

                    while ((c = _src.Next).IsHex())
                        nums.Add(c.FromHex());
                }
                else
                {
                    while (c.IsDigit())
                    {
                        nums.Add(c.FromHex());
                        c = _src.Next;
                    }
                }

                for (var i = nums.Count - 1; i >= 0; i--)
                {
                    num += nums[i] * basis;
                    basis *= exp;
                }

                if (nums.Count == 0)
                {
                    _src.Back(2);

                    if (isHex)
                        _src.Back();

                    RaiseErrorOccurred(ErrorCode.CharacterReferenceWrongNumber);
                    return null;
                }

                if (c != Specification.SC)
                {
                    RaiseErrorOccurred(ErrorCode.CharacterReferenceSemicolonMissing);
                    _src.Back();
                }

                if (Entities.IsInCharacterTable(num))
                {
                    RaiseErrorOccurred(ErrorCode.CharacterReferenceInvalidCode);
                    return Entities.GetSymbolFromTable(num);
                }

                if (Entities.IsInvalidNumber(num))
                {
                    RaiseErrorOccurred(ErrorCode.CharacterReferenceInvalidNumber);
                    return Specification.REPLACEMENT.ToString();
                }

                if (Entities.IsInInvalidRange(num))
                    RaiseErrorOccurred(ErrorCode.CharacterReferenceInvalidRange);

                return Entities.Convert(num);
            }
            else
            {
                var last = String.Empty;
                var consumed = 0;
                var start = _src.InsertionPoint - 1;
                var reference = new Char[31];
                var index = 0;
                var chr = _src.Current;

                do
                {
                    if (chr == Specification.SC || !chr.IsName())
                        break;

                    reference[index++] = chr;
                    var value = new String(reference, 0, index);
                    chr = _src.Next;
                    consumed++;
                    value = chr == Specification.SC ? Entities.GetSymbol(value) : Entities.GetSymbolWithoutSemicolon(value);

                    if (value != null)
                    {
                        consumed = 0;
                        last = value;
                    }
                }
                while (!_src.IsEnded);

                _src.Back(consumed);
                chr = _src.Current;

                if (chr != Specification.SC)
                {
                    if (allowedCharacter != Specification.NULL && (chr == Specification.EQ || chr.IsAlphanumericAscii()))
                    {
                        if (chr == Specification.EQ)
                            RaiseErrorOccurred(ErrorCode.CharacterReferenceAttributeEqualsFound);

                        _src.InsertionPoint = start;
                        return null;
                    }

                    _src.Back();
                    RaiseErrorOccurred(ErrorCode.CharacterReferenceNotTerminated);
                }

                return last;
            }
        }
Exemple #4
0
        internal static bool FindExponent(ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
        {
            exponent = 0;
            bool neg;

            if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E'))
            {
                exc = null;
                return(false);
            }

            var i = pos + 1;

            if (i == s.Length)
            {
                exc = tryParse ? null : GetFormatException();
                return(true);
            }

            neg = (s [i] == '-');
            if (neg)
            {
                i++;
            }

            if (s [i] == '+' && ++i == s.Length)
            {
                exc = tryParse ? null : GetFormatException();
                return(true);
            }

            long exp = 0;                     // temp long value

            for (; i < s.Length; i++)
            {
                if (!Char.IsDigit(s [i]))
                {
                    exc = tryParse ? null : GetFormatException();
                    return(true);
                }

                // Reduce the risk of throwing an overflow exc
                exp = checked (exp * 10 - (int)(s [i] - '0'));
                if (exp < Int32.MinValue || exp > Int32.MaxValue)
                {
                    exc = tryParse ? null : new OverflowException("Value too large or too small.");
                    return(true);
                }
            }

            // exp value saved as negative, and neg tracks whether we had a negative
            if (!neg)
            {
                exp = -exp;
            }

            exc      = null;
            exponent = (int)exp;
            pos      = i;
            return(true);
        }
Exemple #5
0
        // 3.1) scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
        private static bool ParseScheme(ParserState state)
        {
            string part = state.remaining;

            StringBuilder sb = new StringBuilder();

            sb.Append(part [0]);

            int index;

            for (index = 1; index < part.Length; index++)
            {
                char ch = part [index];
                if (ch != '.' && ch != '-' && ch != '+' && !IsAlpha(ch) && !Char.IsDigit(ch))
                {
                    break;
                }

                sb.Append(ch);
            }

            if (index == 0 || index >= part.Length)
            {
                if (state.kind == UriKind.Absolute)
                {
                    state.error = "Invalid URI: The format of the URI could not be determined.";
                    return(false);
                }

                state.elements.isAbsoluteUri = false;
                return(state.remaining.Length > 0);
            }

            if (part [index] != ':')
            {
                if (state.kind == UriKind.Absolute)
                {
                    state.error = "Invalid URI: The URI scheme is not valid.";
                    return(false);
                }

                state.elements.isAbsoluteUri = false;
                return(state.remaining.Length > 0);
            }

            state.elements.scheme = sb.ToString().ToLowerInvariant();
            state.remaining       = part.Substring(index);

            // Check scheme name characters as specified in RFC2396.
            // Note: different checks in 1.x and 2.0
            if (!Uri.CheckSchemeName(state.elements.scheme))
            {
                if (state.kind == UriKind.Absolute)
                {
                    state.error = "Invalid URI: The URI scheme is not valid.";
                    return(false);
                }

                state.elements.isAbsoluteUri = false;
                return(state.remaining.Length > 0);
            }

            if (state.elements.scheme == Uri.UriSchemeFile)
            {
                // under Windows all file:// URI are considered UNC, which is not the case other MacOS (e.g. Silverlight)
#if BOOTSTRAP_BASIC
                state.elements.isUnc = (Path.DirectorySeparatorChar == '\\');
#else
                state.elements.isUnc = Environment.IsRunningOnWindows;
#endif
            }

            return(ParseDelimiter(state));
        }
Exemple #6
0
        /// <summary>
        /// See 8.2.4.69 Tokenizing character references
        /// </summary>
        /// <param name="c">The next input character.</param>
        /// <param name="allowedCharacter">The additionally allowed character if there is one.</param>
        void AppendCharacterReference(Char c, Char allowedCharacter = Symbols.Null)
        {
            if (c.IsSpaceCharacter() || c == Symbols.LessThan || c == Symbols.EndOfFile || c == Symbols.Ampersand || c == allowedCharacter)
            {
                Back();
                _stringBuffer.Append(Symbols.Ampersand);
                return;
            }

            var entity = default(String);
            
            if (c == Symbols.Num)
            {
                var exp = 10;
                var basis = 1;
                var num = 0;
                var nums = new List<Int32>();
                c = GetNext();
                var isHex = c == 'x' || c == 'X';

                if (isHex)
                {
                    exp = 16;

                    while ((c = GetNext()).IsHex())
                        nums.Add(c.FromHex());
                }
                else
                {
                    while (c.IsDigit())
                    {
                        nums.Add(c.FromHex());
                        c = GetNext();
                    }
                }

                for (var i = nums.Count - 1; i >= 0; i--)
                {
                    num += nums[i] * basis;
                    basis *= exp;
                }

                if (nums.Count == 0)
                {
                    Back(2);

                    if (isHex)
                        Back();

                    RaiseErrorOccurred(HtmlParseError.CharacterReferenceWrongNumber);
                    _stringBuffer.Append(Symbols.Ampersand);
                    return;
                }

                if (c != Symbols.Semicolon)
                {
                    RaiseErrorOccurred(HtmlParseError.CharacterReferenceSemicolonMissing);
                    Back();
                }

                if (Entities.IsInCharacterTable(num))
                {
                    RaiseErrorOccurred(HtmlParseError.CharacterReferenceInvalidCode);
                    entity = Entities.GetSymbolFromTable(num);
                }
                else if (Entities.IsInvalidNumber(num))
                {
                    RaiseErrorOccurred(HtmlParseError.CharacterReferenceInvalidNumber);
                    entity = Symbols.Replacement.ToString();
                }
                else 
                {
                    if (Entities.IsInInvalidRange(num))
                        RaiseErrorOccurred(HtmlParseError.CharacterReferenceInvalidRange);

                    entity = Entities.Convert(num);
                }
            }
            else
            {
                var consumed = 0;
                var start = InsertionPoint - 1;
                var reference = new Char[31];
                var index = 0;
                var chr = Current;

                do
                {
                    if (chr == Symbols.Semicolon || !chr.IsName())
                        break;

                    reference[index++] = chr;
                    var value = new String(reference, 0, index);
                    chr = GetNext();
                    consumed++;
                    value = chr == Symbols.Semicolon ? Entities.GetSymbol(value) : Entities.GetSymbolWithoutSemicolon(value);

                    if (value != null)
                    {
                        consumed = 0;
                        entity = value;
                    }
                }
                while (chr != Symbols.EndOfFile && index < 31);

                Back(consumed);
                chr = Current;

                if (chr != Symbols.Semicolon)
                {
                    if (allowedCharacter != Symbols.Null && (chr == Symbols.Equality || chr.IsAlphanumericAscii()))
                    {
                        if (chr == Symbols.Equality)
                            RaiseErrorOccurred(HtmlParseError.CharacterReferenceAttributeEqualsFound);

                        InsertionPoint = start;
                        _stringBuffer.Append(Symbols.Ampersand);
                        return;
                    }

                    Back();
                    RaiseErrorOccurred(HtmlParseError.CharacterReferenceNotTerminated);
                }

                if (entity == null)
                {
                    _stringBuffer.Append(Symbols.Ampersand);
                    return;
                }
            }

            _stringBuffer.Append(entity);
        }
        /// <summary>
        /// 4.4.12. Number state
        /// </summary>
        CssToken NumberStart(Char current)
        {
            while (true)
            {
                if (current == Specification.Plus || current == Specification.Minus)
                {
                    _stringBuffer.Append(current);
                    current = Next;

                    if (current == Specification.Dot)
                    {
                        _stringBuffer.Append(current);
                        _stringBuffer.Append(Next);
                        return NumberFraction(Next);
                    }

                    _stringBuffer.Append(current);
                    return NumberRest(Next);
                }
                else if (current == Specification.Dot)
                {
                    _stringBuffer.Append(current);
                    _stringBuffer.Append(Next);
                    return NumberFraction(Next);
                }
                else if (current.IsDigit())
                {
                    _stringBuffer.Append(current);
                    return NumberRest(Next);
                }

                current = Next;
            }
        }
        /// <summary>
        /// Substate of several Number states.
        /// </summary>
        CssToken NumberExponential(Char current)
        {
            current = Next;

            if (current.IsDigit())
            {
                _stringBuffer.Append('e').Append(current);
                return SciNotation(Next);
            }
            else if (current == Specification.Plus || current == Specification.Minus)
            {
                var op = current;
                current = Next;

                if (current.IsDigit())
                {
                    _stringBuffer.Append('e').Append(op).Append(current);
                    return SciNotation(Next);
                }

                Back();
            }

            current = Previous;
            var number = FlushBuffer();
            _stringBuffer.Append(current);
            return Dimension(Next, number);
        }
Exemple #9
0
		// 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
			//
			int state = State_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;
			
			for (; sidx < len; sidx++){
				c = s [sidx];

				if (c == '\0') {
					sidx = len;
					continue;
				}

				switch (state){
				case State_AllowSign:
					if ((style & NumberStyles.AllowLeadingSign) != 0){
						if (c == positive [0] &&
						    s.Substring (sidx, positive.Length) == positive){
							state = State_Digits;
							sidx += positive.Length-1;
							continue;
						}

						if (c == negative [0] &&
						    s.Substring (sidx, negative.Length) == negative){
							state = State_Digits;
							b [didx++] = (byte) '-';
							sidx += negative.Length-1;
							continue;
						}
					}
					state = State_Digits;
					goto case State_Digits;
					
				case State_Digits:
					if (Char.IsDigit (c)){
						b [didx++] = (byte) c;
						break;
					}
					if (c == 'e' || c == 'E')
						goto case State_Decimal;
					
					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 = State_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;
							state = State_Digits; 
							break;
						}
					}
					if (currency_symbol_len > 0 &&
					    currency_symbol [0] == c){
						if (s.Substring (sidx, currency_symbol_len) ==
						    currency_symbol){
							sidx += currency_symbol_len-1;
							state = State_Digits; 
							break;
						}
					}
					
					if (Char.IsWhiteSpace (c))
						goto case State_ConsumeWhiteSpace;

					if (!tryParse)
						exc = new FormatException ("Unknown char: " + c);
					return false;

				case State_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 = State_ExponentSign;
						break;
					}
					
					if (Char.IsWhiteSpace (c))
						goto case State_ConsumeWhiteSpace;
					
					if (!tryParse)
						exc = new FormatException ("Unknown char: " + c);
					return false;

				case State_ExponentSign:
					if (Char.IsDigit (c)){
						state = State_Exponent;
						goto case State_Exponent;
					}

					if (c == positive [0] &&
					    s.Substring (sidx, positive.Length) == positive){
						state = State_Digits;
						sidx += positive.Length-1;
						continue;
					}

					if (c == negative [0] &&
					    s.Substring (sidx, negative.Length) == negative){
						state = State_Digits;
						b [didx++] = (byte) '-';
						sidx += negative.Length-1;
						continue;
					}

					if (Char.IsWhiteSpace (c))
						goto case State_ConsumeWhiteSpace;
					
					if (!tryParse)
						exc = new FormatException ("Unknown char: " + c);
					return false;
					
				case State_Exponent:
					if (Char.IsDigit (c)){
						b [didx++] = (byte) c;
						break;
					}
					
					if (Char.IsWhiteSpace (c))
						goto case State_ConsumeWhiteSpace;
					
					if (!tryParse)
						exc = new FormatException ("Unknown char: " + c);
					return false;

				case State_ConsumeWhiteSpace:
					if (allow_trailing_white && Char.IsWhiteSpace (c)) {
						state = State_ConsumeWhiteSpace;
						break;
					}
					
					if (!tryParse)
						exc = new FormatException ("Unknown char");
					return false;
				}

				if (state == State_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;
				}
			}
		}
Exemple #10
0
        /// <summary>
        /// 4.4.12. Number state
        /// </summary>
        CssToken NumberStart(Char current)
        {
            while (true)
            {
                if (current == Specification.PLUS || current == Specification.MINUS)
                {
                    _stringBuffer.Append(current);
                    current = _src.Next;

                    if (current == Specification.DOT)
                    {
                        _stringBuffer.Append(current);
                        _stringBuffer.Append(_src.Next);
                        return NumberFraction(_src.Next);
                    }

                    _stringBuffer.Append(current);
                    return NumberRest(_src.Next);
                }
                else if (current == Specification.DOT)
                {
                    _stringBuffer.Append(current);
                    _stringBuffer.Append(_src.Next);
                    return NumberFraction(_src.Next);
                }
                else if (current.IsDigit())
                {
                    _stringBuffer.Append(current);
                    return NumberRest(_src.Next);
                }

                current = _src.Next;
            }
        }
Exemple #11
0
        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 = new FormatException("Input string was not " +
                                              "in the correct format: s.Length==0.");
                }
                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;

            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 = new FormatException("Input string was not in the correct " +
                                                  "format: Has Negative Sign.");
                    }
                    return(false);
                }
                if (s.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
                {
                    if (!tryParse)
                    {
                        exc = new FormatException("Input string was not in the correct " +
                                                  "format: Has Positive Sign.");
                    }
                    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;

            // 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;
                }
                else 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 = new FormatException("Input string was not in the correct format: nDigits == 0.");
                }
                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
                if (nfi.CurrencyPositivePattern == 3 && s[pos++] != ' ')
                {
                    if (tryParse)
                    {
                        return(false);
                    }
                    else
                    {
                        throw new FormatException("Input string was not in the correct format: no space between number and currency symbol.");
                    }
                }

                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 = new FormatException("Input string was not in the correct " +
                                                  "format: No room for close parens.");
                    }
                    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 = new FormatException("Input string was not in the correct format: Did not parse entire string. pos = "
                                              + pos + " s.Length = " + s.Length);
                }
                return(false);
            }


            if (!negative && !AllowHexSpecifier)
            {
                try
                {
                    number = checked (-number);
                }
                catch (OverflowException e)
                {
                    if (!tryParse)
                    {
                        exc = e;
                    }
                    return(false);
                }
            }

            result = number;
            return(true);
        }
        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);
        }
Exemple #13
0
        internal static bool Parse(string s, NumberStyles style, IFormatProvider fp, bool tryParse, out int 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 = 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 (!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 && !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 && !JumpOverWhite(ref pos, s, true, tryParse, ref exc))
                {
                    return(false);
                }

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

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

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

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

            int  number          = 0;
            int  nDigits         = 0;
            int  decimalPointPos = -1;
            int  digitValue;
            char hexDigit;

            // Number stuff
            do
            {
                if (!ValidDigit(s [pos], AllowHexSpecifier))
                {
                    if (AllowThousands &&
                        (FindOther(ref pos, s, nfi.NumberGroupSeparator) ||
                         FindOther(ref pos, s, nfi.CurrencyGroupSeparator)))
                    {
                        continue;
                    }

                    if (AllowDecimalPoint && decimalPointPos < 0 &&
                        (FindOther(ref pos, s, nfi.NumberDecimalSeparator) ||
                         FindOther(ref pos, s, nfi.CurrencyDecimalSeparator)))
                    {
                        decimalPointPos = nDigits;
                        continue;
                    }

                    break;
                }

                nDigits++;

                if (AllowHexSpecifier)
                {
                    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);
                    }

                    uint unumber = (uint)number;
                    if (tryParse)
                    {
                        if ((unumber & 0xf0000000) != 0)
                        {
                            return(false);
                        }

                        number = (int)(unumber * 16u + (uint)digitValue);
                    }
                    else
                    {
                        number = (int)checked (unumber * 16u + (uint)digitValue);
                    }

                    continue;
                }

                try {
                    // Calculations done as negative
                    // (abs (MinValue) > abs (MaxValue))
                    number = checked (number * 10 - (int)(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 = GetFormatException();
                }
                return(false);
            }

            int exponent = 0;

            if (AllowExponent)
            {
                if (FindExponent(ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
                {
                    return(false);
                }
            }

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

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

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

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

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

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

            if (!negative && !AllowHexSpecifier)
            {
                if (tryParse)
                {
                    long lval = -((long)number);

                    if (lval < MinValue || lval > MaxValue)
                    {
                        return(false);
                    }
                    number = (int)lval;
                }
                else
                {
                    number = checked (-number);
                }
            }

            if (decimalPointPos >= 0)
            {
                exponent = exponent - nDigits + decimalPointPos;
            }

            if (exponent < 0)
            {
                //
                // Any non-zero values after decimal point are not allowed
                //
                int remainder;
                number = 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 = (int)res;
            }

            result = number;
            return(true);
        }
Exemple #14
0
        private static string stripStyles(string s, NumberStyles style, NumberFormatInfo nfi,
                                          out int decPos, out bool isNegative, out bool expFlag, out int exp, bool throwex)
        {
            isNegative = false;
            expFlag    = false;
            exp        = 0;
            decPos     = -1;

            bool hasSign = false;
            bool hasOpeningParentheses     = false;
            bool hasDecimalPoint           = false;
            bool allowedLeadingWhiteSpace  = ((style & NumberStyles.AllowLeadingWhite) != 0);
            bool allowedTrailingWhiteSpace = ((style & NumberStyles.AllowTrailingWhite) != 0);
            bool allowedLeadingSign        = ((style & NumberStyles.AllowLeadingSign) != 0);
            bool allowedTrailingSign       = ((style & NumberStyles.AllowTrailingSign) != 0);
            bool allowedParentheses        = ((style & NumberStyles.AllowParentheses) != 0);
            bool allowedThousands          = ((style & NumberStyles.AllowThousands) != 0);
            bool allowedDecimalPoint       = ((style & NumberStyles.AllowDecimalPoint) != 0);
            bool allowedExponent           = ((style & NumberStyles.AllowExponent) != 0);

            /* get rid of currency symbol */
            bool hasCurrency = false;

            if ((style & NumberStyles.AllowCurrencySymbol) != 0)
            {
                int index = s.IndexOf(nfi.CurrencySymbol);
                if (index >= 0)
                {
                    s           = s.Remove(index, nfi.CurrencySymbol.Length);
                    hasCurrency = true;
                }
            }

            string decimalSep = (hasCurrency) ? nfi.CurrencyDecimalSeparator : nfi.NumberDecimalSeparator;
            string groupSep   = (hasCurrency) ? nfi.CurrencyGroupSeparator : nfi.NumberGroupSeparator;

            int pos = 0;
            int len = s.Length;

            StringBuilder sb = new StringBuilder(len);

            // leading
            while (pos < len)
            {
                char ch = s[pos];
                if (Char.IsDigit(ch))
                {
                    break; // end of leading
                }
                else if (allowedLeadingWhiteSpace && Char.IsWhiteSpace(ch))
                {
                    pos++;
                }
                else if (allowedParentheses && ch == '(' && !hasSign && !hasOpeningParentheses)
                {
                    hasOpeningParentheses = true;
                    hasSign    = true;
                    isNegative = true;
                    pos++;
                }
                else if (allowedLeadingSign && ch == nfi.NegativeSign[0] && !hasSign)
                {
                    int slen = nfi.NegativeSign.Length;
                    if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
                    {
                        hasSign    = true;
                        isNegative = true;
                        pos       += slen;
                    }
                }
                else if (allowedLeadingSign && ch == nfi.PositiveSign[0] && !hasSign)
                {
                    int slen = nfi.PositiveSign.Length;
                    if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
                    {
                        hasSign = true;
                        pos    += slen;
                    }
                }
                else if (allowedDecimalPoint && ch == decimalSep[0])
                {
                    int slen = decimalSep.Length;
                    if (slen != 1 && s.IndexOf(decimalSep, pos, slen) != pos)
                    {
                        if (throwex)
                        {
                            ThrowAtPos(pos);
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    break;
                }
                else
                {
                    if (throwex)
                    {
                        ThrowAtPos(pos);
                    }
                    else
                    {
                        return(null);
                    }
                }
            }

            if (pos == len)
            {
                if (throwex)
                {
                    throw new FormatException(Locale.GetText("No digits found"));
                }
                else
                {
                    return(null);
                }
            }

            // digits
            while (pos < len)
            {
                char ch = s[pos];
                if (Char.IsDigit(ch))
                {
                    sb.Append(ch);
                    pos++;
                }
                else if (allowedThousands && ch == groupSep[0])
                {
                    int slen = groupSep.Length;
                    if (slen != 1 && s.IndexOf(groupSep, pos, slen) != pos)
                    {
                        if (throwex)
                        {
                            ThrowAtPos(pos);
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    pos += slen;
                }
                else if (allowedDecimalPoint && ch == decimalSep[0] && !hasDecimalPoint)
                {
                    int slen = decimalSep.Length;
                    if (slen == 1 || s.IndexOf(decimalSep, pos, slen) == pos)
                    {
                        decPos          = sb.Length;
                        hasDecimalPoint = true;
                        pos            += slen;
                    }
                }
                else
                {
                    break;
                }
            }

            // exponent
            if (pos < len)
            {
                char ch = s[pos];
                if (allowedExponent && Char.ToUpperInvariant(ch) == 'E')
                {
                    expFlag = true;
                    pos++;
                    if (pos >= len)
                    {
                        if (throwex)
                        {
                            ThrowInvalidExp();
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    ch = s[pos];
                    bool isNegativeExp = false;
                    if (ch == nfi.PositiveSign[0])
                    {
                        int slen = nfi.PositiveSign.Length;
                        if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
                        {
                            pos += slen;
                            if (pos >= len)
                            {
                                if (throwex)
                                {
                                    ThrowInvalidExp();
                                }
                                else
                                {
                                    return(null);
                                }
                            }
                        }
                    }
                    else if (ch == nfi.NegativeSign[0])
                    {
                        int slen = nfi.NegativeSign.Length;
                        if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
                        {
                            pos += slen;
                            if (pos >= len)
                            {
                                if (throwex)
                                {
                                    ThrowInvalidExp();
                                }
                                else
                                {
                                    return(null);
                                }
                            }
                            isNegativeExp = true;
                        }
                    }
                    ch = s[pos];
                    if (!Char.IsDigit(ch))
                    {
                        if (throwex)
                        {
                            ThrowInvalidExp();
                        }
                        else
                        {
                            return(null);
                        }
                    }

                    exp = ch - '0';
                    pos++;
                    while (pos < len && Char.IsDigit(s[pos]))
                    {
                        exp *= 10;
                        exp += s[pos] - '0';
                        pos++;
                    }
                    if (isNegativeExp)
                    {
                        exp *= -1;
                    }
                }
            }

            // trailing
            while (pos < len)
            {
                char ch = s[pos];
                if (allowedTrailingWhiteSpace && Char.IsWhiteSpace(ch))
                {
                    pos++;
                }
                else if (allowedParentheses && ch == ')' && hasOpeningParentheses)
                {
                    hasOpeningParentheses = false;
                    pos++;
                }
                else if (allowedTrailingSign && ch == nfi.NegativeSign[0] && !hasSign)
                {
                    int slen = nfi.NegativeSign.Length;
                    if (slen == 1 || s.IndexOf(nfi.NegativeSign, pos, slen) == pos)
                    {
                        hasSign    = true;
                        isNegative = true;
                        pos       += slen;
                    }
                }
                else if (allowedTrailingSign && ch == nfi.PositiveSign[0] && !hasSign)
                {
                    int slen = nfi.PositiveSign.Length;
                    if (slen == 1 || s.IndexOf(nfi.PositiveSign, pos, slen) == pos)
                    {
                        hasSign = true;
                        pos    += slen;
                    }
                }
                else
                {
                    if (throwex)
                    {
                        ThrowAtPos(pos);
                    }
                    else
                    {
                        return(null);
                    }
                }
            }

            if (hasOpeningParentheses)
            {
                if (throwex)
                {
                    throw new FormatException(Locale.GetText("Closing Parentheses not found"));
                }
                else
                {
                    return(null);
                }
            }

            if (!hasDecimalPoint)
            {
                decPos = sb.Length;
            }

            return(sb.ToString());
        }
Exemple #15
0
        /// <summary>
        /// Called once an &amp; character is being seen.
        /// </summary>
        /// <param name="c">The next character after the &amp; character.</param>
        /// <returns>The entity token.</returns>
        XmlEntityToken CharacterReference(Char c)
        {
            var buffer = Pool.NewStringBuilder();

            if (c == Specification.NUM)
            {
                c = _src.Next;
                var hex = c == 'x' || c == 'X';

                if (hex)
                {
                    c = _src.Next;

                    while (c.IsHex())
                    {
                        buffer.Append(c);
                        c = _src.Next;
                    }
                }
                else
                {
                    while (c.IsDigit())
                    {
                        buffer.Append(c);
                        c = _src.Next;
                    }
                }

                if (buffer.Length > 0 && c == Specification.SC)
                    return new XmlEntityToken { Value = buffer.ToPool(), IsNumeric = true, IsHex = hex };
            }
            else if (c.IsXmlNameStart())
            {
                do
                {
                    buffer.Append(c);
                    c = _src.Next;
                }
                while (c.IsXmlName());

                if (c == Specification.SC)
                    return new XmlEntityToken { Value = buffer.ToPool() };
            }

            buffer.ToPool();
            throw Errors.Xml(ErrorCode.CharacterReferenceNotTerminated);
        }
        protected String EReference(Char c)
        {
            var buffer = Pool.NewStringBuilder();

            if (c.IsXmlNameStart())
            {
                do
                {
                    buffer.Append(c);
                    c = _stream.Next;
                }
                while (c.IsXmlName());

                var temp = buffer.ToPool();

                if (temp.Length > 0 && c == Specification.SC)
                {
                    var p = _container.GetEntity(temp);

                    if (p != null)
                        return p.NodeValue;
                }
            }
            else if (c == Specification.NUM)
            {
                c = _src.Next;
                var hex = c == 'x' || c == 'X';

                if (hex)
                    c = _stream.Next;

                while (hex ? c.IsHex() : c.IsDigit())
                {
                    buffer.Append(c);
                    c = _src.Next;
                }

                var temp = buffer.ToPool();

                if (temp.Length > 0 && c == Specification.SC)
                {
                    var num = hex ? temp.FromHex() : temp.FromDec();

                    if (num.IsValidAsCharRef())
                        return Char.ConvertFromUtf32(num);

                    throw Errors.Xml(ErrorCode.CharacterReferenceInvalidNumber);
                }
            }

            throw Errors.Xml(ErrorCode.CharacterReferenceNotTerminated);
        }
Exemple #17
0
        /// <summary>
        /// 4.4.12. Number state
        /// </summary>
        CssToken NumberStart(Char current)
        {
            while (true)
            {
                if (current == Symbols.Plus || current == Symbols.Minus)
                {
                    _stringBuffer.Append(current);
                    current = GetNext();

                    if (current == Symbols.Dot)
                    {
                        _stringBuffer.Append(current);
                        _stringBuffer.Append(GetNext());
                        return NumberFraction();
                    }

                    _stringBuffer.Append(current);
                    return NumberRest();
                }
                else if (current == Symbols.Dot)
                {
                    _stringBuffer.Append(current);
                    _stringBuffer.Append(GetNext());
                    return NumberFraction();
                }
                else if (current.IsDigit())
                {
                    _stringBuffer.Append(current);
                    return NumberRest();
                }

                current = GetNext();
            }
        }
Exemple #18
0
        /// <summary>
        /// Called once an &amp; character is being seen.
        /// </summary>
        /// <param name="c">The next character after the &amp; character.</param>
        /// <returns>The entity token.</returns>
        XmlEntityToken CharacterReference(Char c)
        {
            if (c == Symbols.Num)
            {
                c = GetNext();
                var isHex = c == 'x' || c == 'X';

                if (isHex)
                {
                    c = GetNext();

                    while (c.IsHex())
                    {
                        _stringBuffer.Append(c);
                        c = GetNext();
                    }
                }
                else
                {
                    while (c.IsDigit())
                    {
                        _stringBuffer.Append(c);
                        c = GetNext();
                    }
                }

                if (_stringBuffer.Length > 0 && c == Symbols.Semicolon)
                    return NewEntity(numeric: true, hex: isHex);
            }
            else if (c.IsXmlNameStart())
            {
                do
                {
                    _stringBuffer.Append(c);
                    c = GetNext();
                }
                while (c.IsXmlName());

                if (c == Symbols.Semicolon)
                    return NewEntity();
            }

            throw XmlParseError.CharacterReferenceNotTerminated.At(GetCurrentPosition());
        }
        /// <summary>
        /// 4.4.13. Number-rest state
        /// </summary>
        CssToken NumberRest(Char current)
        {
            while (true)
            {
                if (current.IsDigit())
                    _stringBuffer.Append(current);
                else if (current.IsNameStart())
                {
                    var number = FlushBuffer();
                    _stringBuffer.Append(current);
                    return Dimension(Next, number);
                }
                else if (IsValidEscape(current))
                {
                    current = Next;
                    var number = FlushBuffer();
                    _stringBuffer.Append(ConsumeEscape(current));
                    return Dimension(Next, number);
                }
                else
                    break;

                current = Next;
            }

            switch (current)
            {
                case Specification.Dot:
                    current = Next;

                    if (current.IsDigit())
                    {
                        _stringBuffer.Append(Specification.Dot).Append(current);
                        return NumberFraction(Next);
                    }

                    Back();
                    return CssToken.Number(FlushBuffer());

                case '%':
                    return CssUnitToken.Percentage(FlushBuffer());

                case 'e':
                case 'E':
                    return NumberExponential(current);

                case Specification.Minus:
                    return NumberDash(current);

                default:
                    Back();
                    return CssToken.Number(FlushBuffer());
            }
        }
Exemple #20
0
        // a very gentle way to construct a Version object which takes
        // the first four numbers in a string as the version
        internal static Version CreateVersionFromString(string info)
        {
            int major    = 0;
            int minor    = 0;
            int build    = 0;
            int revision = 0;
            int state    = 1;
            int number   = -1;           // string may not begin with a digit

            if (info == null)
            {
                return(new Version(0, 0, 0, 0));
            }

            for (int i = 0; i < info.Length; i++)
            {
                char c = info [i];
                if (Char.IsDigit(c))
                {
                    if (number < 0)
                    {
                        number = (c - '0');
                    }
                    else
                    {
                        number = (number * 10) + (c - '0');
                    }
                }
                else if (number >= 0)
                {
                    // assign
                    switch (state)
                    {
                    case 1:
                        major = number;
                        break;

                    case 2:
                        minor = number;
                        break;

                    case 3:
                        build = number;
                        break;

                    case 4:
                        revision = number;
                        break;
                    }
                    number = -1;
                    state++;
                }
                // ignore end of string
                if (state == 5)
                {
                    break;
                }
            }

            // Last number
            if (number >= 0)
            {
                switch (state)
                {
                case 1:
                    major = number;
                    break;

                case 2:
                    minor = number;
                    break;

                case 3:
                    build = number;
                    break;

                case 4:
                    revision = number;
                    break;
                }
            }
            return(new Version(major, minor, build, revision));
        }
        /// <summary>
        /// 4.4.16. SciNotation state
        /// </summary>
        CssToken SciNotation(Char current)
        {
            while (true)
            {
                if (current.IsDigit())
                    _stringBuffer.Append(current);
                else
                {
                    Back();
                    return CssToken.Number(FlushBuffer());
                }

                current = Next;
            }
        }
Exemple #22
0
        private String GetNumericCharacterReference(Char c)
        {
            var exp = 10;
            var basis = 1;
            var num = 0;
            var nums = new List<Int32>();
            var isHex = c == 'x' || c == 'X';

            if (isHex)
            {
                exp = 16;

                while ((c = GetNext()).IsHex())
                {
                    nums.Add(c.FromHex());
                }
            }
            else
            {
                while (c.IsDigit())
                {
                    nums.Add(c.FromHex());
                    c = GetNext();
                }
            }

            for (var i = nums.Count - 1; i >= 0; i--)
            {
                num += nums[i] * basis;
                basis *= exp;
            }

            if (nums.Count == 0)
            {
                Back(2);

                if (isHex)
                {
                    Back();
                }

                RaiseErrorOccurred(HtmlParseError.CharacterReferenceWrongNumber);
                return null;
            }

            if (c != Symbols.Semicolon)
            {
                RaiseErrorOccurred(HtmlParseError.CharacterReferenceSemicolonMissing);
                Back();
            }

            if (HtmlEntityService.IsInCharacterTable(num))
            {
                RaiseErrorOccurred(HtmlParseError.CharacterReferenceInvalidCode);
                return HtmlEntityService.GetSymbolFromTable(num);
            }
            else if (HtmlEntityService.IsInvalidNumber(num))
            {
                RaiseErrorOccurred(HtmlParseError.CharacterReferenceInvalidNumber);
                return Symbols.Replacement.ToString();
            }
            else if (HtmlEntityService.IsInInvalidRange(num))
            {
                RaiseErrorOccurred(HtmlParseError.CharacterReferenceInvalidRange);
            }

            return num.ConvertFromUtf32();
        }
        /// <summary>
        /// Called once an &amp; character is being seen.
        /// </summary>
        /// <param name="c">The next character after the &amp; character.</param>
        /// <returns>The entity token.</returns>
        String CharacterReference(Char c)
        {
            var start = _stringBuffer.Length;
            var hex = false;
            var numeric = c == Symbols.Num;

            if (numeric)
            {
                c = GetNext();
                hex = c == 'x' || c == 'X';

                if (hex)
                {
                    c = GetNext();

                    while (c.IsHex())
                    {
                        _stringBuffer.Append(c);
                        c = GetNext();
                    }
                }
                else
                {
                    while (c.IsDigit())
                    {
                        _stringBuffer.Append(c);
                        c = GetNext();
                    }
                }
            }
            else if (c.IsXmlNameStart())
            {
                do
                {
                    _stringBuffer.Append(c);
                    c = GetNext();
                }
                while (c.IsXmlName());
            }

            if (c == Symbols.Semicolon && _stringBuffer.Length > start)
            {
                var length = _stringBuffer.Length - start;
                var content = _stringBuffer.ToString(start, length);
                _stringBuffer.Remove(start, length);

                if (numeric)
                {
                    var number = numeric ? content.FromHex() : content.FromDec();

                    if (!number.IsValidAsCharRef())
                        throw XmlParseError.CharacterReferenceInvalidNumber.At(_position);

                    return number.ConvertFromUtf32();
                }
                else
                {
                    var entity = _resolver.GetSymbol(content);

                    if (String.IsNullOrEmpty(entity))
                        throw XmlParseError.CharacterReferenceInvalidCode.At(_position);

                    return entity;
                }
            }

            throw XmlParseError.CharacterReferenceNotTerminated.At(GetCurrentPosition());
        }
Exemple #24
0
        internal static bool Parse(string s, NumberStyles style, IFormatProvider provider, bool tryParse, out ulong 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);
                            }
                        }
                    }
                }
            }

            ulong number          = 0;
            int   nDigits         = 0;
            int   decimalPointPos = -1;
            ulong 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 = (ulong)(hexDigit - '0');
                    }
                    else if (Char.IsLower(hexDigit))
                    {
                        digitValue = (ulong)(hexDigit - 'a' + 10);
                    }
                    else
                    {
                        digitValue = (ulong)(hexDigit - 'A' + 10);
                    }

                    if (tryParse)
                    {
                        // Any number above 32 will do
                        bool can_overflow = number > 0xffff;

                        number = number * 16 + digitValue;

                        if (can_overflow && number < 16)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        number = checked (number * 16 + digitValue);
                    }

                    continue;
                }

                try {
                    number = checked (number * 10 + (ulong)(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 = (ulong)Math.DivRem((long)number, (long)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 = (ulong)res;
            }

            result = number;
            return(true);
        }