forked from fmtlib/fmt
Improve handling of format strings in custom arguments.
This commit is contained in:
27
format.cc
27
format.cc
@@ -175,19 +175,6 @@ int parse_nonnegative_int(const Char *&s) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
const Char *find_closing_brace(const Char *s, int num_open_braces = 1) {
|
|
||||||
for (int n = num_open_braces; *s; ++s) {
|
|
||||||
if (*s == '{') {
|
|
||||||
++n;
|
|
||||||
} else if (*s == '}') {
|
|
||||||
if (--n == 0)
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw fmt::FormatError("unmatched '{' in format");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void check_sign(const Char *&s, const Arg &arg) {
|
void check_sign(const Char *&s, const Arg &arg) {
|
||||||
char sign = static_cast<char>(*s);
|
char sign = static_cast<char>(*s);
|
||||||
@@ -574,7 +561,7 @@ class fmt::internal::ArgFormatter :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void visit_custom(Arg::CustomValue c) {
|
void visit_custom(Arg::CustomValue c) {
|
||||||
c.format(&formatter_, c.value, format_);
|
c.format(&formatter_, c.value, &format_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1019,11 +1006,13 @@ void fmt::internal::PrintfFormatter<Char>::format(
|
|||||||
spec.type_ = 'x';
|
spec.type_ = 'x';
|
||||||
writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
|
writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
|
||||||
break;
|
break;
|
||||||
case Arg::CUSTOM:
|
case Arg::CUSTOM: {
|
||||||
if (spec.type_)
|
if (spec.type_)
|
||||||
internal::report_unknown_type(spec.type_, "object");
|
internal::report_unknown_type(spec.type_, "object");
|
||||||
arg.custom.format(&writer, arg.custom.value, "s");
|
const void *s = "s";
|
||||||
|
arg.custom.format(&writer, arg.custom.value, &s);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
@@ -1034,14 +1023,14 @@ void fmt::internal::PrintfFormatter<Char>::format(
|
|||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
const Char *fmt::BasicFormatter<Char>::format(
|
const Char *fmt::BasicFormatter<Char>::format(
|
||||||
const Char *format_str, const Arg &arg) {
|
const Char *&format_str, const Arg &arg) {
|
||||||
const Char *s = format_str;
|
const Char *s = format_str;
|
||||||
const char *error = 0;
|
const char *error = 0;
|
||||||
FormatSpec spec;
|
FormatSpec spec;
|
||||||
if (*s == ':') {
|
if (*s == ':') {
|
||||||
if (arg.type == Arg::CUSTOM) {
|
if (arg.type == Arg::CUSTOM) {
|
||||||
arg.custom.format(this, arg.custom.value, s);
|
arg.custom.format(this, arg.custom.value, &s);
|
||||||
return find_closing_brace(s) + 1;
|
return s;
|
||||||
}
|
}
|
||||||
++s;
|
++s;
|
||||||
// Parse fill and alignment.
|
// Parse fill and alignment.
|
||||||
|
14
format.h
14
format.h
@@ -132,7 +132,7 @@ template <typename Char>
|
|||||||
class BasicFormatter;
|
class BasicFormatter;
|
||||||
|
|
||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
void format(BasicFormatter<Char> &f, const Char *format_str, const T &value);
|
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
@@ -583,7 +583,7 @@ struct Arg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*FormatFunc)(
|
typedef void (*FormatFunc)(
|
||||||
void *formatter, const void *arg, const void *format_str);
|
void *formatter, const void *arg, void *format_str_ptr);
|
||||||
|
|
||||||
struct CustomValue {
|
struct CustomValue {
|
||||||
const void *value;
|
const void *value;
|
||||||
@@ -634,9 +634,9 @@ class MakeArg : public Arg {
|
|||||||
// Formats an argument of a custom type, such as a user-defined class.
|
// Formats an argument of a custom type, such as a user-defined class.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void format_custom_arg(
|
static void format_custom_arg(
|
||||||
void *formatter, const void *arg, const void *format_str) {
|
void *formatter, const void *arg, void *format_str_ptr) {
|
||||||
format(*static_cast<BasicFormatter<Char>*>(formatter),
|
format(*static_cast<BasicFormatter<Char>*>(formatter),
|
||||||
static_cast<const Char*>(format_str), *static_cast<const T*>(arg));
|
*static_cast<const Char**>(format_str_ptr), *static_cast<const T*>(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -896,7 +896,7 @@ public:
|
|||||||
|
|
||||||
void format(BasicStringRef<Char> format_str, const ArgList &args);
|
void format(BasicStringRef<Char> format_str, const ArgList &args);
|
||||||
|
|
||||||
const Char *format(const Char *format_str, const internal::Arg &arg);
|
const Char *format(const Char *&format_str, const internal::Arg &arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Alignment {
|
enum Alignment {
|
||||||
@@ -1681,10 +1681,10 @@ void BasicWriter<Char>::write_int(T value, const Spec &spec) {
|
|||||||
|
|
||||||
// Formats a value.
|
// Formats a value.
|
||||||
template <typename Char, typename T>
|
template <typename Char, typename T>
|
||||||
void format(BasicFormatter<Char> &f, const Char *format_str, const T &value) {
|
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
|
||||||
std::basic_ostringstream<Char> os;
|
std::basic_ostringstream<Char> os;
|
||||||
os << value;
|
os << value;
|
||||||
f.format(format_str, internal::MakeArg<Char>(os.str()));
|
format_str = f.format(format_str, internal::MakeArg<Char>(os.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reports a system error without throwing an exception.
|
// Reports a system error without throwing an exception.
|
||||||
|
@@ -238,7 +238,8 @@ TEST(ArgTest, MakeArg) {
|
|||||||
EXPECT_EQ(&t, arg.custom.value);
|
EXPECT_EQ(&t, arg.custom.value);
|
||||||
fmt::Writer w;
|
fmt::Writer w;
|
||||||
fmt::BasicFormatter<char> formatter(w);
|
fmt::BasicFormatter<char> formatter(w);
|
||||||
arg.custom.format(&formatter, &t, "}");
|
const char *s = "}";
|
||||||
|
arg.custom.format(&formatter, &t, &s);
|
||||||
EXPECT_EQ("test", w.str());
|
EXPECT_EQ("test", w.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user