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); }
/// <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; } }
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); }
// 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)); }
/// <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); }
// 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; } } }
/// <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; } }
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); }
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); }
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()); }
/// <summary> /// Called once an & character is being seen. /// </summary> /// <param name="c">The next character after the & 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); }
/// <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(); } }
/// <summary> /// Called once an & character is being seen. /// </summary> /// <param name="c">The next character after the & 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()); } }
// 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; } }
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 & character is being seen. /// </summary> /// <param name="c">The next character after the & 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()); }
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); }