Allow formatting C strings as pointers (#223)

This commit is contained in:
vitaut 2015-11-09 07:17:36 -08:00
parent 7c24973637
commit 8b86a74ad5
5 changed files with 25 additions and 9 deletions

View File

@ -409,6 +409,12 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter); FMT_DISALLOW_COPY_AND_ASSIGN(BasicArgFormatter);
void write_pointer(const void *p) {
spec_.flags_ = HASH_FLAG;
spec_.type_ = 'x';
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
}
protected: protected:
BasicWriter<Char> &writer() { return writer_; } BasicWriter<Char> &writer() { return writer_; }
const FormatSpec &spec() const { return spec_; } const FormatSpec &spec() const { return spec_; }
@ -462,6 +468,15 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
*out = internal::CharTraits<Char>::cast(value); *out = internal::CharTraits<Char>::cast(value);
} }
void visit_cstring(const char *value) {
if (spec_.type_ == 'p') {
write_pointer(value);
return;
}
Arg::StringValue<char> str = {value, 0};
writer_.write_str(str, spec_);
}
void visit_string(Arg::StringValue<char> value) { void visit_string(Arg::StringValue<char> value) {
writer_.write_str(value, spec_); writer_.write_str(value, spec_);
} }
@ -475,9 +490,7 @@ class BasicArgFormatter : public ArgVisitor<Impl, void> {
void visit_pointer(const void *value) { void visit_pointer(const void *value) {
if (spec_.type_ && spec_.type_ != 'p') if (spec_.type_ && spec_.type_ != 'p')
report_unknown_type(spec_.type_, "pointer"); report_unknown_type(spec_.type_, "pointer");
spec_.flags_ = HASH_FLAG; write_pointer(value);
spec_.type_ = 'x';
writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
} }
}; };

View File

@ -1186,6 +1186,9 @@ class ArgVisitor {
return FMT_DISPATCH(visit_unhandled_arg()); return FMT_DISPATCH(visit_unhandled_arg());
} }
Result visit_cstring(const char *) {
return FMT_DISPATCH(visit_unhandled_arg());
}
Result visit_string(Arg::StringValue<char>) { Result visit_string(Arg::StringValue<char>) {
return FMT_DISPATCH(visit_unhandled_arg()); return FMT_DISPATCH(visit_unhandled_arg());
} }
@ -1220,11 +1223,8 @@ class ArgVisitor {
return FMT_DISPATCH(visit_double(arg.double_value)); return FMT_DISPATCH(visit_double(arg.double_value));
case Arg::LONG_DOUBLE: case Arg::LONG_DOUBLE:
return FMT_DISPATCH(visit_long_double(arg.long_double_value)); return FMT_DISPATCH(visit_long_double(arg.long_double_value));
case Arg::CSTRING: { case Arg::CSTRING:
Arg::StringValue<char> str = arg.string; return FMT_DISPATCH(visit_cstring(arg.string.value));
str.size = 0;
return FMT_DISPATCH(visit_string(str));
}
case Arg::STRING: case Arg::STRING:
return FMT_DISPATCH(visit_string(arg.string)); return FMT_DISPATCH(visit_string(arg.string));
case Arg::WSTRING: case Arg::WSTRING:

View File

@ -1336,7 +1336,7 @@ TEST(FormatterTest, FormatWChar) {
} }
TEST(FormatterTest, FormatCString) { TEST(FormatterTest, FormatCString) {
check_unknown_types("test", "s", "string"); check_unknown_types("test", "sp", "string");
EXPECT_EQ("test", format("{0}", "test")); EXPECT_EQ("test", format("{0}", "test"));
EXPECT_EQ("test", format("{0:s}", "test")); EXPECT_EQ("test", format("{0:s}", "test"));
char nonconst[] = "nonconst"; char nonconst[] = "nonconst";

View File

@ -425,6 +425,8 @@ 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);
const char *s = "test";
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
} }
TEST(PrintfTest, Custom) { TEST(PrintfTest, Custom) {

View File

@ -593,6 +593,7 @@ struct TestVisitor : fmt::internal::ArgVisitor<TestVisitor, Result> {
Result visit_double(double value) { return value; } Result visit_double(double value) { return value; }
Result visit_long_double(long double value) { return value; } Result visit_long_double(long double value) { return value; }
Result visit_char(int value) { return static_cast<char>(value); } Result visit_char(int value) { return static_cast<char>(value); }
Result visit_cstring(const char *s) { return s; }
Result visit_string(Arg::StringValue<char> s) { return s.value; } Result visit_string(Arg::StringValue<char> s) { return s.value; }
Result visit_wstring(Arg::StringValue<wchar_t> s) { return s.value; } Result visit_wstring(Arg::StringValue<wchar_t> s) { return s.value; }
Result visit_pointer(const void *p) { return p; } Result visit_pointer(const void *p) { return p; }