/// <summary> /// Parse a string field /// </summary> private bool ParseString(TextParser input, FormatSpecifier spec) { // Skip any whitespace input.MovePastWhitespace(); // Parse string characters int start = input.Position; while (!input.EndOfText && !Char.IsWhiteSpace(input.Peek())) { input.MoveAhead(); } // Don't exceed field width if (spec.Width > 0) { int count = input.Position - start; if (spec.Width < count) { input.MoveAhead(spec.Width - count); } } // Extract token if (input.Position > start) { if (!spec.NoResult) { Results.Add(input.Extract(start, input.Position)); } return(true); } return(false); }
/// <summary> /// Parse an octal field /// </summary> private bool ParseOctal(TextParser input, FormatSpecifier spec) { // Skip any whitespace input.MovePastWhitespace(); // Parse digits int start = input.Position; while (IsValidDigit(input.Peek(), 8)) { input.MoveAhead(); } // Don't exceed field width if (spec.Width > 0) { int count = input.Position - start; if (spec.Width < count) { input.MoveAhead(spec.Width - count); } } // Extract token if (input.Position > start) { if (!spec.NoResult) { AddUnsigned(input.Extract(start, input.Position), spec.Modifier, 8); } return(true); } return(false); }
/// <summary> /// Parses the input string according to the rules in the /// format string. Similar to the standard C library's /// sscanf() function. Parsed fields are placed in the /// class' Results member. /// </summary> /// <param name="input">String to parse</param> /// <param name="format">Specifies rules for parsing input</param> public int Parse(string input, string format) { TextParser inp = new TextParser(input); TextParser fmt = new TextParser(format); List <object> results = new List <object>(); FormatSpecifier spec = new FormatSpecifier(); int count = 0; // Clear any previous results Results.Clear(); // Process input string as indicated in format string while (!fmt.EndOfText && !inp.EndOfText) { if (ParseFormatSpecifier(fmt, spec)) { // Found a format specifier TypeParser parser = _typeParsers.First(tp => tp.Type == spec.Type); if (parser.Parser(inp, spec)) { count++; } else { break; } } else if (Char.IsWhiteSpace(fmt.Peek())) { // Whitespace inp.MovePastWhitespace(); fmt.MoveAhead(); } else if (fmt.Peek() == inp.Peek()) { // Matching character inp.MoveAhead(); fmt.MoveAhead(); } else { break; // Break at mismatch } } // Return number of fields successfully parsed return(count); }
/// <summary> /// Parse hexadecimal field /// </summary> protected bool ParseHexadecimal(TextParser input, FormatSpecifier spec) { // Skip any whitespace input.MovePastWhitespace(); // Parse 0x prefix int start = input.Position; if (input.Peek() == '0' && input.Peek(1) == 'x') { input.MoveAhead(2); } // Parse digits while (IsValidDigit(input.Peek(), 16)) { input.MoveAhead(); } // Don't exceed field width if (spec.Width > 0) { int count = input.Position - start; if (spec.Width < count) { input.MoveAhead(spec.Width - count); } } // Extract token if (input.Position > start) { if (!spec.NoResult) { AddUnsigned(input.Extract(start, input.Position), spec.Modifier, 16); } return(true); } return(false); }
/// <summary> /// Parse a floating-point field /// </summary> private bool ParseFloat(TextParser input, FormatSpecifier spec) { // Skip any whitespace input.MovePastWhitespace(); // Parse leading sign int start = input.Position; if (input.Peek() == '+' || input.Peek() == '-') { input.MoveAhead(); } // Parse digits bool hasPoint = false; while (Char.IsDigit(input.Peek()) || input.Peek() == '.') { if (input.Peek() == '.') { if (hasPoint) { break; } hasPoint = true; } input.MoveAhead(); } // Parse exponential notation if (Char.ToLower(input.Peek()) == 'e') { input.MoveAhead(); if (input.Peek() == '+' || input.Peek() == '-') { input.MoveAhead(); } while (Char.IsDigit(input.Peek())) { input.MoveAhead(); } } // Don't exceed field width if (spec.Width > 0) { int count = input.Position - start; if (spec.Width < count) { input.MoveAhead(spec.Width - count); } } // Because we parse the exponential notation before we apply // any field-width constraint, it becomes awkward to verify // we have a valid floating point token. To prevent an // exception, we use TryParse() here instead of Parse(). double result; // Extract token if (input.Position > start && double.TryParse(input.Extract(start, input.Position), out result)) { if (!spec.NoResult) { if (spec.Modifier == Modifiers.Long || spec.Modifier == Modifiers.LongLong) { Results.Add(result); } else { Results.Add((float)result); } } return(true); } return(false); }
/// <summary> /// Parse integer field /// </summary> private bool ParseDecimal(TextParser input, FormatSpecifier spec) { int radix = 10; // Skip any whitespace input.MovePastWhitespace(); // Parse leading sign int start = input.Position; if (input.Peek() == '+' || input.Peek() == '-') { input.MoveAhead(); } else if (input.Peek() == '0') { if (Char.ToLower(input.Peek(1)) == 'x') { radix = 16; input.MoveAhead(2); } else { radix = 8; input.MoveAhead(); } } // Parse digits while (IsValidDigit(input.Peek(), radix)) { input.MoveAhead(); } // Don't exceed field width if (spec.Width > 0) { int count = input.Position - start; if (spec.Width < count) { input.MoveAhead(spec.Width - count); } } // Extract token if (input.Position > start) { if (!spec.NoResult) { if (spec.Type == Types.Decimal) { AddSigned(input.Extract(start, input.Position), spec.Modifier, radix); } else { AddUnsigned(input.Extract(start, input.Position), spec.Modifier, radix); } } return(true); } return(false); }