Allow %s as generic format specifier in printf
Signed integers are formatted as %d Unsigned integers are formatted as %u Doubles are formatted as %f Chars are formatted as %c Void Pointers are formatted as %p
This commit is contained in:
parent
e0251fdcef
commit
b059a5e647
26
fmt/printf.h
26
fmt/printf.h
@ -92,9 +92,18 @@ class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
|
|||||||
visit_any_int(value);
|
visit_any_int(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visit_char(char value) {
|
||||||
|
if (type_ != 's' && type_ != 'S')
|
||||||
|
visit_any_int(value);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
void visit_any_int(U value) {
|
void visit_any_int(U value) {
|
||||||
bool is_signed = type_ == 'd' || type_ == 'i';
|
bool is_signed = type_ == 'd' || type_ == 'i';
|
||||||
|
if (type_ == 's' || type_ == 'S') {
|
||||||
|
is_signed = std::numeric_limits<U>::is_signed;
|
||||||
|
}
|
||||||
|
|
||||||
using internal::Arg;
|
using internal::Arg;
|
||||||
typedef typename internal::Conditional<
|
typedef typename internal::Conditional<
|
||||||
is_same<T, void>::value, U, T>::type TargetType;
|
is_same<T, void>::value, U, T>::type TargetType;
|
||||||
@ -463,6 +472,23 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
|
|||||||
if (!*s)
|
if (!*s)
|
||||||
FMT_THROW(FormatError("invalid format string"));
|
FMT_THROW(FormatError("invalid format string"));
|
||||||
spec.type_ = static_cast<char>(*s++);
|
spec.type_ = static_cast<char>(*s++);
|
||||||
|
|
||||||
|
if (spec.type_ == 's' || spec.type_ == 'S') {
|
||||||
|
if (arg.type == Arg::POINTER) {
|
||||||
|
spec.type_ = 'p';
|
||||||
|
} else if (arg.type == Arg::CHAR) {
|
||||||
|
spec.type_ = 'c';
|
||||||
|
} else if (arg.type == Arg::BOOL) {
|
||||||
|
// leave bool alone
|
||||||
|
} else if (arg.type <= Arg::LAST_INTEGER_TYPE) {
|
||||||
|
// all other integer types
|
||||||
|
spec.type_ = 'd';
|
||||||
|
} else if (arg.type <= Arg::LAST_NUMERIC_TYPE) {
|
||||||
|
// all floating point types
|
||||||
|
spec.type_ = 'f';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
|
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
|
||||||
// Normalize type.
|
// Normalize type.
|
||||||
switch (spec.type_) {
|
switch (spec.type_) {
|
||||||
|
|||||||
@ -202,6 +202,8 @@ TEST(PrintfTest, HashFlag) {
|
|||||||
|
|
||||||
TEST(PrintfTest, Width) {
|
TEST(PrintfTest, Width) {
|
||||||
EXPECT_PRINTF(" abc", "%5s", "abc");
|
EXPECT_PRINTF(" abc", "%5s", "abc");
|
||||||
|
EXPECT_PRINTF(" -42", "%5s", "-42");
|
||||||
|
EXPECT_PRINTF(" 0.123456", "%10s", 0.123456);
|
||||||
|
|
||||||
// Width cannot be specified twice.
|
// Width cannot be specified twice.
|
||||||
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,
|
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,
|
||||||
@ -381,11 +383,14 @@ TEST(PrintfTest, Bool) {
|
|||||||
TEST(PrintfTest, Int) {
|
TEST(PrintfTest, Int) {
|
||||||
EXPECT_PRINTF("-42", "%d", -42);
|
EXPECT_PRINTF("-42", "%d", -42);
|
||||||
EXPECT_PRINTF("-42", "%i", -42);
|
EXPECT_PRINTF("-42", "%i", -42);
|
||||||
|
EXPECT_PRINTF("-42", "%s", -42);
|
||||||
unsigned u = 0 - 42u;
|
unsigned u = 0 - 42u;
|
||||||
EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
|
EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
|
||||||
EXPECT_PRINTF(fmt::format("{:o}", u), "%o", -42);
|
EXPECT_PRINTF(fmt::format("{:o}", u), "%o", -42);
|
||||||
EXPECT_PRINTF(fmt::format("{:x}", u), "%x", -42);
|
EXPECT_PRINTF(fmt::format("{:x}", u), "%x", -42);
|
||||||
EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
|
EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
|
||||||
|
EXPECT_PRINTF(fmt::format("{}", u), "%s", u);
|
||||||
|
EXPECT_PRINTF(fmt::format("{}", u), "%S", u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, LongLong) {
|
TEST(PrintfTest, LongLong) {
|
||||||
@ -398,6 +403,8 @@ TEST(PrintfTest, LongLong) {
|
|||||||
TEST(PrintfTest, Float) {
|
TEST(PrintfTest, Float) {
|
||||||
EXPECT_PRINTF("392.650000", "%f", 392.65);
|
EXPECT_PRINTF("392.650000", "%f", 392.65);
|
||||||
EXPECT_PRINTF("392.650000", "%F", 392.65);
|
EXPECT_PRINTF("392.650000", "%F", 392.65);
|
||||||
|
EXPECT_PRINTF("392.650000", "%s", 392.65);
|
||||||
|
EXPECT_PRINTF("392.650000", "%S", 392.65);
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
safe_sprintf(buffer, "%e", 392.65);
|
safe_sprintf(buffer, "%e", 392.65);
|
||||||
EXPECT_PRINTF(buffer, "%e", 392.65);
|
EXPECT_PRINTF(buffer, "%e", 392.65);
|
||||||
@ -422,6 +429,7 @@ TEST(PrintfTest, Inf) {
|
|||||||
|
|
||||||
TEST(PrintfTest, Char) {
|
TEST(PrintfTest, Char) {
|
||||||
EXPECT_PRINTF("x", "%c", 'x');
|
EXPECT_PRINTF("x", "%c", 'x');
|
||||||
|
EXPECT_PRINTF("x", "%s", 'x');
|
||||||
int max = std::numeric_limits<int>::max();
|
int max = std::numeric_limits<int>::max();
|
||||||
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
|
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
|
||||||
//EXPECT_PRINTF("x", "%lc", L'x');
|
//EXPECT_PRINTF("x", "%lc", L'x');
|
||||||
@ -440,13 +448,17 @@ TEST(PrintfTest, Pointer) {
|
|||||||
int n;
|
int n;
|
||||||
void *p = &n;
|
void *p = &n;
|
||||||
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
|
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
|
||||||
|
EXPECT_PRINTF(fmt::format("{}", p), "%s", p);
|
||||||
p = 0;
|
p = 0;
|
||||||
EXPECT_PRINTF("(nil)", "%p", p);
|
EXPECT_PRINTF("(nil)", "%p", p);
|
||||||
EXPECT_PRINTF(" (nil)", "%10p", p);
|
EXPECT_PRINTF(" (nil)", "%10p", p);
|
||||||
|
EXPECT_PRINTF("(nil)", "%s", p);
|
||||||
|
EXPECT_PRINTF(" (nil)", "%10s", p);
|
||||||
const char *s = "test";
|
const char *s = "test";
|
||||||
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
|
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
|
||||||
const char *null_str = 0;
|
const char *null_str = 0;
|
||||||
EXPECT_PRINTF("(nil)", "%p", null_str);
|
EXPECT_PRINTF("(nil)", "%p", null_str);
|
||||||
|
EXPECT_PRINTF("(null)", "%s", null_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, Location) {
|
TEST(PrintfTest, Location) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user