stdio: more compact scanf format parsing

This commit is contained in:
Lephenixnoir 2024-01-14 21:34:46 +01:00
parent 527c2e48fc
commit 177c4eea3f
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495

View file

@ -191,79 +191,52 @@ static int parse_fmt(char const *fmt, int *pos, struct scanf_format *opt)
int width = 0; int width = 0;
char size_letter = 0; char size_letter = 0;
while(1) { for((*pos)++;; (*pos)++) {
(*pos)++; int c = fmt[*pos];
switch(fmt[*pos]) { if(c == '*')
case '*':
opt->skip = true; opt->skip = true;
break; else if(strchr("hlzjtL", c)) {
if(c == 'h')
case 'h':
opt->size = (size_letter=='h') ? sizeof(char) : sizeof(short); opt->size = (size_letter=='h') ? sizeof(char) : sizeof(short);
size_letter = 'h'; else if(c == 'l')
break; opt->size = (size_letter=='l') ? sizeof(long long) :
case 'l': sizeof(long);
opt->size = (size_letter=='l') ? sizeof(long long) : sizeof(long); else if(c == 'z')
size_letter = 'l';
break;
case 'L':
opt->size = sizeof(long double);
size_letter = 'L';
break;
case 'j':
opt->size = sizeof(intmax_t);
break;
case 'z':
opt->size = sizeof(size_t); opt->size = sizeof(size_t);
break; else if(c == 'j')
case 't': opt->size = sizeof(intmax_t);
else if(c == 't')
opt->size = sizeof(ptrdiff_t); opt->size = sizeof(ptrdiff_t);
break; else if(c == 'L')
opt->size = sizeof(long double);
case '0' ... '9': size_letter = c;
}
else if(isdigit(c)) {
width = width * 10 + (fmt[*pos] - '0'); width = width * 10 + (fmt[*pos] - '0');
opt->field_width = width; opt->field_width = width;
break; }
else if(c == '[') {
case '[':
(*pos)++; (*pos)++;
return bracket_set_parse(opt->bracket_set, fmt, pos) ? '[' : 0; return bracket_set_parse(opt->bracket_set, fmt, pos) ? '[' : 0;
}
case 'd': else if(strchr("diouxXpsn", c))
case 'i': return c;
case 'o': else if(strchr("aAeEfFgG", c)) {
case 'u':
case 'x':
case 'X':
case 'p':
case 's':
case 'n':
return fmt[*pos];
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
/* Adjust interpretation of no size / 'l' size */ /* Adjust interpretation of no size / 'l' size */
if(size_letter == 0) if(size_letter == 0)
opt->size = sizeof(float); opt->size = sizeof(float);
if(size_letter == 'l') if(size_letter == 'l')
opt->size = sizeof(double); opt->size = sizeof(double);
return fmt[*pos]; return c;
}
case 'c': else if(c == 'c') {
if(opt->field_width == INT_MAX) if(opt->field_width == INT_MAX)
opt->field_width = 1; opt->field_width = 1;
return 'c'; return c;
default:
return 0;
} }
else return 0;
} }
return 0; return 0;
} }
@ -301,7 +274,6 @@ int __scanf(
return validrets; return validrets;
switch(spec) { switch(spec) {
// we need to decrypt the corresponding scanf set of character
case '[': { case '[': {
int currentlength = 0; int currentlength = 0;
// we need to assign the read char to the corresponding pointer // we need to assign the read char to the corresponding pointer
@ -324,7 +296,6 @@ int __scanf(
break; break;
} }
// return the number of char read so far (cannot be skipped %*n is not valid)
case 'n': case 'n':
*va_arg(*args, int *) = in->bytes_read; *va_arg(*args, int *) = in->bytes_read;
break; break;