forked from fmtlib/fmt
Implement dynamic precision in printf.
This commit is contained in:
76
format.cc
76
format.cc
@@ -620,6 +620,7 @@ unsigned fmt::BasicWriter<Char>::PrintfParser::ParseHeader(
|
|||||||
spec.width_ = GetIntValue(arg);
|
spec.width_ = GetIntValue(arg);
|
||||||
else if (!error)
|
else if (!error)
|
||||||
error = "width is not integer";
|
error = "width is not integer";
|
||||||
|
// TODO: check for negative width
|
||||||
}
|
}
|
||||||
return arg_index;
|
return arg_index;
|
||||||
}
|
}
|
||||||
@@ -682,8 +683,26 @@ void fmt::BasicWriter<Char>::PrintfParser::Format(
|
|||||||
// is OK for both cases.
|
// is OK for both cases.
|
||||||
const char *error = 0;
|
const char *error = 0;
|
||||||
|
|
||||||
c = *s;
|
// Parse argument index, flags and width.
|
||||||
const ArgInfo &arg = HandleArgIndex(ParseHeader(s, spec, error), error);
|
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)
|
if (spec.hash_flag() && GetIntValue(arg) == 0)
|
||||||
spec.flags_ &= ~HASH_FLAG;
|
spec.flags_ &= ~HASH_FLAG;
|
||||||
if (spec.fill_ == '0') {
|
if (spec.fill_ == '0') {
|
||||||
@@ -693,58 +712,7 @@ void fmt::BasicWriter<Char>::PrintfParser::Format(
|
|||||||
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
|
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse precision.
|
// TODO: parse length
|
||||||
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");
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse type.
|
// Parse type.
|
||||||
if (!*s)
|
if (!*s)
|
||||||
|
@@ -263,6 +263,11 @@ TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
|
|||||||
EXPECT_PRINTF("abc", "%.5s", "abc");
|
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
|
// TODO: test length and type specifier
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user