mirror of
https://github.com/fmtlib/fmt.git
synced 2025-11-26 12:19:45 +01:00
Improve handling of custom arguments
This commit is contained in:
@@ -1385,7 +1385,22 @@ class basic_arg {
|
||||
friend class basic_args<Context>;
|
||||
friend class internal::arg_map<Context>;
|
||||
|
||||
using char_type = typename Context::char_type;
|
||||
|
||||
public:
|
||||
class handle {
|
||||
public:
|
||||
explicit handle(internal::custom_value<char_type> custom)
|
||||
: custom_(custom) {}
|
||||
|
||||
void format(basic_buffer<char_type> &buf, Context &ctx) {
|
||||
custom_.format(buf, custom_.value, &ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
internal::custom_value<char_type> custom_;
|
||||
};
|
||||
|
||||
constexpr basic_arg() : type_(internal::NONE) {}
|
||||
|
||||
explicit operator bool() const noexcept { return type_ != internal::NONE; }
|
||||
@@ -1407,7 +1422,7 @@ class basic_arg {
|
||||
template <typename Visitor, typename Context>
|
||||
constexpr typename std::result_of<Visitor(int)>::type
|
||||
visit(Visitor &&vis, basic_arg<Context> arg) {
|
||||
typedef typename Context::char_type Char;
|
||||
using char_type = typename Context::char_type;
|
||||
switch (arg.type_) {
|
||||
case internal::NONE:
|
||||
return vis(monostate());
|
||||
@@ -1425,7 +1440,7 @@ constexpr typename std::result_of<Visitor(int)>::type
|
||||
case internal::BOOL:
|
||||
return vis(arg.value_.int_value != 0);
|
||||
case internal::CHAR:
|
||||
return vis(static_cast<Char>(arg.value_.int_value));
|
||||
return vis(static_cast<char_type>(arg.value_.int_value));
|
||||
case internal::DOUBLE:
|
||||
return vis(arg.value_.double_value);
|
||||
case internal::LONG_DOUBLE:
|
||||
@@ -1433,12 +1448,12 @@ constexpr typename std::result_of<Visitor(int)>::type
|
||||
case internal::CSTRING:
|
||||
return vis(arg.value_.string.value);
|
||||
case internal::STRING:
|
||||
return vis(basic_string_view<Char>(
|
||||
return vis(basic_string_view<char_type>(
|
||||
arg.value_.string.value, arg.value_.string.size));
|
||||
case internal::POINTER:
|
||||
return vis(arg.value_.pointer);
|
||||
case internal::CUSTOM:
|
||||
return vis(arg.value_.custom);
|
||||
return vis(typename basic_arg<Context>::handle(arg.value_.custom));
|
||||
}
|
||||
return typename std::result_of<Visitor(int)>::type();
|
||||
}
|
||||
@@ -2161,8 +2176,8 @@ class custom_formatter {
|
||||
custom_formatter(basic_buffer<Char> &buffer, Context &ctx)
|
||||
: buffer_(buffer), ctx_(ctx) {}
|
||||
|
||||
bool operator()(internal::custom_value<Char> custom) {
|
||||
custom.format(buffer_, custom.value, &ctx_);
|
||||
bool operator()(typename basic_arg<Context>::handle h) {
|
||||
h.format(buffer_, ctx_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2795,8 +2810,8 @@ class arg_formatter : public internal::arg_formatter_base<Char> {
|
||||
using internal::arg_formatter_base<Char>::operator();
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
void operator()(internal::custom_value<Char> c) {
|
||||
c.format(this->writer().buffer(), c.value, &ctx_);
|
||||
void operator()(typename basic_arg<basic_context<Char>>::handle handle) {
|
||||
handle.format(this->writer().buffer(), ctx_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -200,6 +200,13 @@ class PrintfWidthHandler {
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename Char>
|
||||
class printf_arg_formatter;
|
||||
|
||||
template <typename Char,
|
||||
typename ArgFormatter = printf_arg_formatter<Char> >
|
||||
class printf_context;
|
||||
|
||||
/**
|
||||
\rst
|
||||
The ``printf`` argument formatter.
|
||||
@@ -208,6 +215,8 @@ class PrintfWidthHandler {
|
||||
template <typename Char>
|
||||
class printf_arg_formatter : public internal::arg_formatter_base<Char> {
|
||||
private:
|
||||
printf_context<Char>& context_;
|
||||
|
||||
void write_null_pointer() {
|
||||
this->spec().type_ = 0;
|
||||
this->write("(nil)");
|
||||
@@ -225,8 +234,9 @@ class printf_arg_formatter : public internal::arg_formatter_base<Char> {
|
||||
specifier information for standard argument types.
|
||||
\endrst
|
||||
*/
|
||||
printf_arg_formatter(basic_buffer<Char> &buffer, format_specs &spec)
|
||||
: internal::arg_formatter_base<Char>(buffer, spec) {}
|
||||
printf_arg_formatter(
|
||||
basic_buffer<Char> &buffer, format_specs &spec, printf_context<Char> &ctx)
|
||||
: internal::arg_formatter_base<Char>(buffer, spec), context_(ctx) {}
|
||||
|
||||
using Base::operator();
|
||||
|
||||
@@ -268,18 +278,11 @@ class printf_arg_formatter : public internal::arg_formatter_base<Char> {
|
||||
}
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
void operator()(internal::custom_value<Char> c) {
|
||||
const Char format_str[] = {'}', '\0'};
|
||||
auto args = basic_args<basic_context<Char>>();
|
||||
basic_context<Char> ctx(basic_string_view<Char>(format_str), args);
|
||||
c.format(this->writer().buffer(), c.value, &ctx);
|
||||
void operator()(typename basic_arg<printf_context<Char>>::handle handle) {
|
||||
handle.format(this->writer().buffer(), context_);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char,
|
||||
typename ArgFormatter = printf_arg_formatter<Char> >
|
||||
class printf_context;
|
||||
|
||||
template <typename T, typename Char = char>
|
||||
struct printf_formatter {
|
||||
template <typename ParseContext>
|
||||
@@ -506,7 +509,7 @@ void printf_context<Char, AF>::format(basic_buffer<Char> &buffer) {
|
||||
start = it;
|
||||
|
||||
// Format argument.
|
||||
visit(AF(buffer, spec), arg);
|
||||
visit(AF(buffer, spec, *this), arg);
|
||||
}
|
||||
buffer.append(pointer_from(start), pointer_from(it));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user