diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-12-19 21:02:45 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-12-23 22:18:35 +0300 |
commit | 312f48b2e27f0f8ede4260e024352fdad225d1c5 (patch) | |
tree | db25f26c4b22b883be094772afb0ec8bc8b966b7 /lib/vsprintf.c | |
parent | 938df695e98db7e0df540cce3b12da8c382955b4 (diff) | |
download | linux-312f48b2e27f0f8ede4260e024352fdad225d1c5.tar.xz |
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 <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e6bd223b0184..123e58724262 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2527,6 +2527,20 @@ struct fmt { enum format_state state; }; +#define SPEC_CHAR(x, flag) [(x)-32] = flag +static unsigned char spec_flag(unsigned char c) +{ + static const unsigned char spec_flag_array[] = { + SPEC_CHAR(' ', SPACE), + SPEC_CHAR('#', SPECIAL), + SPEC_CHAR('+', PLUS), + SPEC_CHAR('-', LEFT), + SPEC_CHAR('0', ZEROPAD), + }; + c -= 32; + return (c < sizeof(spec_flag_array)) ? spec_flag_array[c] : 0; +} + /* * Helper function to decode printf style format. * Each call decode a token from the format and return the @@ -2552,7 +2566,7 @@ static noinline_for_stack struct fmt format_decode(struct fmt fmt, struct printf_spec *spec) { const char *start = fmt.str; - char qualifier; + char flag, qualifier; /* we finished early by reading the field width */ if (fmt.state == FORMAT_STATE_WIDTH) { @@ -2585,26 +2599,13 @@ struct fmt format_decode(struct fmt fmt, struct printf_spec *spec) if (fmt.str != start || !*fmt.str) return fmt; - /* Process flags */ + /* Process flags. This also skips the first '%' */ spec->flags = 0; - - while (1) { /* this also skips first '%' */ - bool found = true; - - fmt.str++; - - switch (*fmt.str) { - case '-': spec->flags |= LEFT; break; - case '+': spec->flags |= PLUS; break; - case ' ': spec->flags |= SPACE; break; - case '#': spec->flags |= SPECIAL; break; - case '0': spec->flags |= ZEROPAD; break; - default: found = false; - } - - if (!found) - break; - } + do { + /* this also skips first '%' */ + flag = spec_flag(*++fmt.str); + spec->flags |= flag; + } while (flag); /* get field width */ spec->field_width = -1; |