Skip to content

Commit 312f48b

Browse files
committed
vsprintf: deal with format flags with a simple lookup table
Rather than a case statement, just look up the printf format flags (justification, zero-padding etc) using a small table. Signed-off-by: Linus Torvalds <[email protected]>
1 parent 938df69 commit 312f48b

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

lib/vsprintf.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,20 @@ struct fmt {
25272527
enum format_state state;
25282528
};
25292529

2530+
#define SPEC_CHAR(x, flag) [(x)-32] = flag
2531+
static unsigned char spec_flag(unsigned char c)
2532+
{
2533+
static const unsigned char spec_flag_array[] = {
2534+
SPEC_CHAR(' ', SPACE),
2535+
SPEC_CHAR('#', SPECIAL),
2536+
SPEC_CHAR('+', PLUS),
2537+
SPEC_CHAR('-', LEFT),
2538+
SPEC_CHAR('0', ZEROPAD),
2539+
};
2540+
c -= 32;
2541+
return (c < sizeof(spec_flag_array)) ? spec_flag_array[c] : 0;
2542+
}
2543+
25302544
/*
25312545
* Helper function to decode printf style format.
25322546
* Each call decode a token from the format and return the
@@ -2552,7 +2566,7 @@ static noinline_for_stack
25522566
struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
25532567
{
25542568
const char *start = fmt.str;
2555-
char qualifier;
2569+
char flag, qualifier;
25562570

25572571
/* we finished early by reading the field width */
25582572
if (fmt.state == FORMAT_STATE_WIDTH) {
@@ -2585,26 +2599,13 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec)
25852599
if (fmt.str != start || !*fmt.str)
25862600
return fmt;
25872601

2588-
/* Process flags */
2602+
/* Process flags. This also skips the first '%' */
25892603
spec->flags = 0;
2590-
2591-
while (1) { /* this also skips first '%' */
2592-
bool found = true;
2593-
2594-
fmt.str++;
2595-
2596-
switch (*fmt.str) {
2597-
case '-': spec->flags |= LEFT; break;
2598-
case '+': spec->flags |= PLUS; break;
2599-
case ' ': spec->flags |= SPACE; break;
2600-
case '#': spec->flags |= SPECIAL; break;
2601-
case '0': spec->flags |= ZEROPAD; break;
2602-
default: found = false;
2603-
}
2604-
2605-
if (!found)
2606-
break;
2607-
}
2604+
do {
2605+
/* this also skips first '%' */
2606+
flag = spec_flag(*++fmt.str);
2607+
spec->flags |= flag;
2608+
} while (flag);
26082609

26092610
/* get field width */
26102611
spec->field_width = -1;

0 commit comments

Comments
 (0)