protected bool ParseFormatSpecifier(TextParser format, FormatSpecifier spec)
{
// Return if not a field format specifier
if (format.Peek() != '%')
return false;
format.MoveAhead();
// Return if "%%" (treat as '%' literal)
if (format.Peek() == '%')
return false;
// Test for asterisk, which indicates result is not stored
if (format.Peek() == '*')
{
spec.NoResult = true;
format.MoveAhead();
}
else spec.NoResult = false;
// Parse width
int start = format.Position;
while (Char.IsDigit(format.Peek()))
format.MoveAhead();
if (format.Position > start)
spec.Width = int.Parse(format.Extract(start, format.Position));
else
spec.Width = 0;
// Parse modifier
if (format.Peek() == 'h')
{
format.MoveAhead();
if (format.Peek() == 'h')
{
format.MoveAhead();
spec.Modifier = Modifiers.ShortShort;
}
else spec.Modifier = Modifiers.Short;
}
else if (Char.ToLower(format.Peek()) == 'l')
{
format.MoveAhead();
if (format.Peek() == 'l')
{
format.MoveAhead();
spec.Modifier = Modifiers.LongLong;
}
else spec.Modifier = Modifiers.Long;
}
else spec.Modifier = Modifiers.None;
// Parse type
switch (format.Peek())
{
case 'c':
spec.Type = Types.Character;
break;
case 'd':
case 'i':
spec.Type = Types.Decimal;
break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
spec.Type = Types.Float;
break;
case 'o':
spec.Type = Types.Octal;
break;
case 's':
spec.Type = Types.String;
break;
case 'u':
spec.Type = Types.Unsigned;
break;
case 'x':
case 'X':
spec.Type = Types.Hexadecimal;
break;
case '[':
spec.Type = Types.ScanSet;
format.MoveAhead();
// Parse scan set characters
if (format.Peek() == '^')
{
spec.ScanSetExclude = true;
format.MoveAhead();
}
else spec.ScanSetExclude = false;
start = format.Position;
// Treat immediate ']' as literal
if (format.Peek() == ']')
format.MoveAhead();
format.MoveTo(']');
if (format.EndOfText)
throw new Exception("Type specifier expected character : ']'");
spec.ScanSet = format.Extract(start, format.Position);
break;
default:
string msg = String.Format("Unknown format type specified : '{0}'", format.Peek());
throw new Exception(msg);
}
format.MoveAhead();
return true;
}