mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
lib/format: support asterisk with format specifier
used by some libraries, e.g: printf("%*.s", 5, "Sun"); -> ' Sun' printf("%.*s", 2, "Sun"); -> 'Su' printf("%*.*s", 5, 2, "Sun"); -> ' Su' printf("%.*d", 3, 10); -> ' 10' Issue #5234
This commit is contained in:
parent
0aafec038d
commit
25717df15f
@ -32,19 +32,26 @@ class Format_command
|
||||
enum Type { INT, UINT, STRING, CHAR, PTR, PERCENT, INVALID };
|
||||
enum Length { DEFAULT, LONG, SIZE_T, LONG_LONG };
|
||||
|
||||
struct Decimal { int value; bool star; };
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Read decimal value from string
|
||||
*/
|
||||
int decode_decimal(const char *str, int *consumed)
|
||||
Decimal decode_decimal(const char *str, int *consumed)
|
||||
{
|
||||
if (str[*consumed] == '*') {
|
||||
(*consumed) ++;
|
||||
return { .value = 0, .star = true };
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
while (1) {
|
||||
char c = str[*consumed];
|
||||
|
||||
if (!c || c < '0' || c > '0' + 9)
|
||||
return res;
|
||||
return { .value = res, .star = false };
|
||||
|
||||
res = (res * 10) + c - '0';
|
||||
(*consumed)++;
|
||||
@ -53,15 +60,15 @@ class Format_command
|
||||
|
||||
public:
|
||||
|
||||
Type type = INVALID; /* format argument type */
|
||||
Length length = DEFAULT; /* format argument length */
|
||||
int padding = 0; /* min number of characters to print */
|
||||
int precision = 0; /* max number of characters to print */
|
||||
int base = 10; /* base of numeric arguments */
|
||||
bool lalign = false; /* align left */
|
||||
bool zeropad = false; /* pad with zero instead of space */
|
||||
bool uppercase = false; /* use upper case for hex numbers */
|
||||
int consumed = 0; /* nb of consumed format string chars */
|
||||
Type type = INVALID; /* format argument type */
|
||||
Length length = DEFAULT; /* format argument length */
|
||||
Decimal padding { }; /* min number of characters to print */
|
||||
Decimal precision { }; /* max number of characters to print */
|
||||
int base = 10; /* base of numeric arguments */
|
||||
bool lalign = false; /* align left */
|
||||
bool zeropad = false; /* pad with zero instead of space */
|
||||
bool uppercase = false; /* use upper case for hex numbers */
|
||||
int consumed = 0; /* nb of consumed format string chars */
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -182,6 +189,13 @@ void Console::vprintf(const char *format, va_list list)
|
||||
Format_command cmd(format);
|
||||
|
||||
/* read numeric argument from va_list */
|
||||
|
||||
if (cmd.padding.star)
|
||||
cmd.padding.value = va_arg(list, int);
|
||||
|
||||
if (cmd.precision.star)
|
||||
cmd.precision.value = va_arg(list, int);
|
||||
|
||||
long long numeric_arg = 0;
|
||||
if (cmd.numeric()) {
|
||||
switch (cmd.length) {
|
||||
@ -226,7 +240,8 @@ void Console::vprintf(const char *format, va_list list)
|
||||
case Format_command::UINT:
|
||||
|
||||
if (cmd.length == Format_command::LONG_LONG) {
|
||||
out_unsigned<unsigned long long>(numeric_arg, cmd.base, cmd.padding,
|
||||
out_unsigned<unsigned long long>(numeric_arg, cmd.base,
|
||||
cmd.padding.value,
|
||||
[&] (char c) { _out_char(c); });
|
||||
break;
|
||||
}
|
||||
@ -235,7 +250,8 @@ void Console::vprintf(const char *format, va_list list)
|
||||
|
||||
case Format_command::PTR:
|
||||
|
||||
out_unsigned<unsigned long>((long)numeric_arg, cmd.base, cmd.padding,
|
||||
out_unsigned<unsigned long>((long)numeric_arg, cmd.base,
|
||||
cmd.padding.value,
|
||||
[&] (char c) { _out_char(c); });
|
||||
break;
|
||||
|
||||
@ -246,12 +262,12 @@ void Console::vprintf(const char *format, va_list list)
|
||||
|
||||
case Format_command::STRING:
|
||||
|
||||
if (cmd.precision) {
|
||||
if (cmd.precision.value) {
|
||||
int p = 0;
|
||||
char const *a = va_arg(list, const char *);
|
||||
for (; a && *a && p < cmd.precision; ++a, ++p)
|
||||
for (; a && *a && p < cmd.precision.value; ++a, ++p)
|
||||
_out_char(*a);
|
||||
for (; p < cmd.padding; ++p)
|
||||
for (; p < cmd.padding.value; ++p)
|
||||
_out_char(' ');
|
||||
} else {
|
||||
_out_string(va_arg(list, const char *));
|
||||
|
Loading…
x
Reference in New Issue
Block a user