Refactor argument visitor API (#422)

This commit is contained in:
Victor Zverovich
2016-11-19 07:39:07 -08:00
parent 6d24116763
commit 95a53e1f62
2 changed files with 39 additions and 18 deletions

View File

@@ -1536,7 +1536,8 @@ typedef basic_format_args<basic_format_context<wchar_t>> wformat_args;
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call #define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
template <typename Visitor> template <typename Visitor>
typename std::result_of<Visitor(int)>::type visit(Visitor &&vis, format_arg arg) { typename std::result_of<Visitor(int)>::type visit(Visitor &&vis,
format_arg arg) {
switch (arg.type) { switch (arg.type) {
case format_arg::NONE: case format_arg::NONE:
case format_arg::NAMED_ARG: case format_arg::NAMED_ARG:
@@ -1746,7 +1747,9 @@ class ArgVisitor {
called. called.
\endrst \endrst
*/ */
Result visit(const format_arg &arg) { return fmt::visit(*this, arg); } Result visit(const format_arg &arg) {
return fmt::visit(*static_cast<Impl*>(this), arg);
}
}; };
enum Alignment { enum Alignment {
@@ -2056,6 +2059,22 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_); writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
} }
template <typename StrChar>
void write_str(Arg::StringValue<StrChar> value,
typename EnableIf<
std::is_same<Char, wchar_t>::value &&
std::is_same<StrChar, wchar_t>::value, int>::type = 0) {
writer_.write_str(value, spec_);
}
template <typename StrChar>
void write_str(Arg::StringValue<StrChar> value,
typename EnableIf<
!std::is_same<Char, wchar_t>::value ||
!std::is_same<StrChar, wchar_t>::value, int>::type = 0) {
// Do nothing.
}
protected: protected:
BasicWriter<Char> &writer() { return writer_; } BasicWriter<Char> &writer() { return writer_; }
FormatSpec &spec() { return spec_; } FormatSpec &spec() { return spec_; }
@@ -2083,13 +2102,15 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
template <typename T> template <typename T>
void visit_any_double(T value) { writer_.write_double(value, spec_); } void visit_any_double(T value) { writer_.write_double(value, spec_); }
void visit_bool(bool value) { using ArgVisitor<Impl, void>::operator();
void operator()(bool value) {
if (spec_.type_) if (spec_.type_)
return visit_any_int(value); return visit_any_int(value);
write(value); write(value);
} }
void visit_char(int value) { void operator()(wchar_t value) {
if (spec_.type_ && spec_.type_ != 'c') { if (spec_.type_ && spec_.type_ != 'c') {
spec_.flags_ |= CHAR_FLAG; spec_.flags_ |= CHAR_FLAG;
writer_.write_int(value, spec_); writer_.write_int(value, spec_);
@@ -2119,23 +2140,21 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
*out = internal::CharTraits<Char>::cast(value); *out = internal::CharTraits<Char>::cast(value);
} }
void visit_cstring(const char *value) { void operator()(const char *value) {
if (spec_.type_ == 'p') if (spec_.type_ == 'p')
return write_pointer(value); return write_pointer(value);
write(value); write(value);
} }
void visit_string(Arg::StringValue<char> value) { void operator()(Arg::StringValue<char> value) {
writer_.write_str(value, spec_); writer_.write_str(value, spec_);
} }
using ArgVisitor<Impl, void>::visit_wstring; void operator()(Arg::StringValue<wchar_t> value) {
write_str(value);
void visit_wstring(Arg::StringValue<Char> value) {
writer_.write_str(value, spec_);
} }
void visit_pointer(const void *value) { void operator()(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");
write_pointer(value); write_pointer(value);

View File

@@ -210,8 +210,10 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
BasicPrintfArgFormatter(BasicWriter<Char> &writer, FormatSpec &spec) BasicPrintfArgFormatter(BasicWriter<Char> &writer, FormatSpec &spec)
: internal::ArgFormatterBase<Impl, Char>(writer, spec) {} : internal::ArgFormatterBase<Impl, Char>(writer, spec) {}
using Base::operator();
/** Formats an argument of type ``bool``. */ /** Formats an argument of type ``bool``. */
void visit_bool(bool value) { void operator()(bool value) {
FormatSpec &fmt_spec = this->spec(); FormatSpec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's') if (fmt_spec.type_ != 's')
return this->visit_any_int(value); return this->visit_any_int(value);
@@ -220,7 +222,7 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
} }
/** Formats a character. */ /** Formats a character. */
void visit_char(int value) { void operator()(wchar_t value) {
const FormatSpec &fmt_spec = this->spec(); const FormatSpec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer(); BasicWriter<Char> &w = this->writer();
if (fmt_spec.type_ && fmt_spec.type_ != 'c') if (fmt_spec.type_ && fmt_spec.type_ != 'c')
@@ -243,9 +245,9 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
} }
/** Formats a null-terminated C string. */ /** Formats a null-terminated C string. */
void visit_cstring(const char *value) { void operator()(const char *value) {
if (value) if (value)
Base::visit_cstring(value); Base::operator()(value);
else if (this->spec().type_ == 'p') else if (this->spec().type_ == 'p')
write_null_pointer(); write_null_pointer();
else else
@@ -253,15 +255,15 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
} }
/** Formats a pointer. */ /** Formats a pointer. */
void visit_pointer(const void *value) { void operator()(const void *value) {
if (value) if (value)
return Base::visit_pointer(value); return Base::operator()(value);
this->spec().type_ = 0; this->spec().type_ = 0;
write_null_pointer(); write_null_pointer();
} }
/** Formats an argument of a custom (user-defined) type. */ /** Formats an argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c) { void operator()(internal::Arg::CustomValue c) {
const Char format_str[] = {'}', '\0'}; const Char format_str[] = {'}', '\0'};
auto args = basic_format_args<basic_format_context<Char>>(); auto args = basic_format_args<basic_format_context<Char>>();
basic_format_context<Char> ctx(format_str, args); basic_format_context<Char> ctx(format_str, args);