mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-25 15:21:54 +00:00
Implement dynamic precision in printf.
This commit is contained in:
parent
0552f5b809
commit
1a75ed01cd
76
format.cc
76
format.cc
@ -620,6 +620,7 @@ unsigned fmt::BasicWriter<Char>::PrintfParser::ParseHeader(
|
||||
spec.width_ = GetIntValue(arg);
|
||||
else if (!error)
|
||||
error = "width is not integer";
|
||||
// TODO: check for negative width
|
||||
}
|
||||
return arg_index;
|
||||
}
|
||||
@ -682,8 +683,26 @@ void fmt::BasicWriter<Char>::PrintfParser::Format(
|
||||
// is OK for both cases.
|
||||
const char *error = 0;
|
||||
|
||||
c = *s;
|
||||
const ArgInfo &arg = HandleArgIndex(ParseHeader(s, spec, error), error);
|
||||
// Parse argument index, flags and width.
|
||||
unsigned arg_index = ParseHeader(s, spec, error);
|
||||
|
||||
// Parse precision.
|
||||
if (*s == '.') {
|
||||
++s;
|
||||
if ('0' <= *s && *s <= '9') {
|
||||
spec.precision_ = internal::ParseNonnegativeInt(s, error);
|
||||
} else if (*s == '*') {
|
||||
++s;
|
||||
const ArgInfo &arg = HandleArgIndex(UINT_MAX, error);
|
||||
if (arg.type <= LAST_INTEGER_TYPE)
|
||||
spec.precision_ = GetIntValue(arg);
|
||||
else if (!error)
|
||||
error = "precision is not integer";
|
||||
// TODO: check for negative precision
|
||||
}
|
||||
}
|
||||
|
||||
const ArgInfo &arg = HandleArgIndex(arg_index, error);
|
||||
if (spec.hash_flag() && GetIntValue(arg) == 0)
|
||||
spec.flags_ &= ~HASH_FLAG;
|
||||
if (spec.fill_ == '0') {
|
||||
@ -693,58 +712,7 @@ void fmt::BasicWriter<Char>::PrintfParser::Format(
|
||||
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
|
||||
}
|
||||
|
||||
// Parse precision.
|
||||
if (*s == '.') {
|
||||
++s;
|
||||
if ('0' <= *s && *s <= '9')
|
||||
spec.precision_ = internal::ParseNonnegativeInt(s, error);
|
||||
/*else if (*s == '*') {
|
||||
++s;
|
||||
++num_open_braces_;
|
||||
const ArgInfo &precision_arg = ParseArgIndex(s);
|
||||
ULongLong value = 0;
|
||||
switch (precision_arg.type) {
|
||||
case INT:
|
||||
if (precision_arg.int_value < 0)
|
||||
ReportError(s, "negative precision in format");
|
||||
value = precision_arg.int_value;
|
||||
break;
|
||||
case UINT:
|
||||
value = precision_arg.uint_value;
|
||||
break;
|
||||
case LONG:
|
||||
if (precision_arg.long_value < 0)
|
||||
ReportError(s, "negative precision in format");
|
||||
value = precision_arg.long_value;
|
||||
break;
|
||||
case ULONG:
|
||||
value = precision_arg.ulong_value;
|
||||
break;
|
||||
case LONG_LONG:
|
||||
if (precision_arg.long_long_value < 0)
|
||||
ReportError(s, "negative precision in format");
|
||||
value = precision_arg.long_long_value;
|
||||
break;
|
||||
case ULONG_LONG:
|
||||
value = precision_arg.ulong_long_value;
|
||||
break;
|
||||
default:
|
||||
ReportError(s, "precision is not integer");
|
||||
}
|
||||
if (value > INT_MAX)
|
||||
ReportError(s, "number is too big in format");
|
||||
precision = static_cast<int>(value);
|
||||
if (*s++ != '}')
|
||||
throw FormatError("unmatched '{' in format");
|
||||
--num_open_braces_;
|
||||
} else {
|
||||
ReportError(s, "missing precision in format");
|
||||
}
|
||||
if (arg.type != DOUBLE && arg.type != LONG_DOUBLE) {
|
||||
ReportError(s,
|
||||
"precision specifier requires floating-point argument");
|
||||
}*/
|
||||
}
|
||||
// TODO: parse length
|
||||
|
||||
// Parse type.
|
||||
if (!*s)
|
||||
|
@ -263,6 +263,11 @@ TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
|
||||
EXPECT_PRINTF("abc", "%.5s", "abc");
|
||||
}
|
||||
|
||||
TEST(PrintfTest, DynamicPrecision) {
|
||||
EXPECT_EQ("00042", str(fmt::sprintf("%.*d", 5, 42)));
|
||||
// TODO: more tests
|
||||
}
|
||||
|
||||
// TODO: test length and type specifier
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user