Use write directly in formatter specializations

This commit is contained in:
Victor Zverovich
2021-05-08 20:54:18 -07:00
parent 4211d86539
commit cd2c78fb8a
2 changed files with 40 additions and 23 deletions

View File

@ -1482,8 +1482,11 @@ OutputIt write_bytes(OutputIt out, string_view bytes,
} }
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt>
constexpr OutputIt write_char(OutputIt out, Char value, FMT_CONSTEXPR OutputIt write(OutputIt out, Char value,
const basic_format_specs<Char>& specs) { const basic_format_specs<Char>& specs,
locale_ref loc = {}) {
if (specs.type && specs.type != 'c')
return write(out, static_cast<int>(value), specs, loc);
return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) { return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
*it++ = value; *it++ = value;
return it; return it;
@ -1598,10 +1601,12 @@ FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
prefix += (1u + (value > 0xff ? 1 : 0)) << 24; prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
} }
template <typename OutputIt, typename T, typename Char> template <typename Char, typename OutputIt, typename T,
FMT_CONSTEXPR OutputIt write_int(OutputIt out, T value, FMT_ENABLE_IF(std::is_integral<T>::value &&
const basic_format_specs<Char>& specs, !std::is_same<T, bool>::value)>
locale_ref loc) { FMT_CONSTEXPR OutputIt write(OutputIt out, T value,
const basic_format_specs<Char>& specs,
locale_ref loc) {
auto prefix = 0u; auto prefix = 0u;
auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value); auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
if (is_negative(value)) { if (is_negative(value)) {
@ -1657,7 +1662,7 @@ FMT_CONSTEXPR OutputIt write_int(OutputIt out, T value,
}); });
} }
case 'c': case 'c':
return write_char(out, static_cast<Char>(abs_value), specs); return write<Char>(out, static_cast<Char>(abs_value), specs);
default: default:
FMT_THROW(format_error("invalid type specifier")); FMT_THROW(format_error("invalid type specifier"));
} }
@ -1679,6 +1684,13 @@ FMT_CONSTEXPR OutputIt write(OutputIt out, basic_string_view<StrChar> s,
return copy_str<Char>(data, data + size, it); return copy_str<Char>(data, data + size, it);
}); });
} }
template <typename Char, typename OutputIt>
FMT_CONSTEXPR OutputIt write(OutputIt out,
basic_string_view<type_identity_t<Char>> s,
const basic_format_specs<Char>& specs,
locale_ref) {
return write(out, s, specs); // Adapt write to formatter::format.
}
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt>
OutputIt write_nonfinite(OutputIt out, bool isinf, OutputIt write_nonfinite(OutputIt out, bool isinf,
@ -2021,9 +2033,14 @@ FMT_CONSTEXPR OutputIt write(OutputIt out, T value) {
out, static_cast<typename std::underlying_type<T>::type>(value)); out, static_cast<typename std::underlying_type<T>::type>(value));
} }
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt, typename T,
constexpr OutputIt write(OutputIt out, bool value) { FMT_ENABLE_IF(std::is_same<T, bool>::value)>
return write<Char>(out, string_view(value ? "true" : "false")); FMT_CONSTEXPR OutputIt write(OutputIt out, T value,
const basic_format_specs<Char>& specs = {},
locale_ref = {}) {
return specs.type && specs.type != 's'
? write(out, value ? 1 : 0, specs, {})
: write(out, string_view(value ? "true" : "false"), specs);
} }
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt>
@ -2044,9 +2061,11 @@ FMT_CONSTEXPR_CHAR_TRAITS OutputIt write(OutputIt out, const Char* value) {
return out; return out;
} }
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt, typename T,
OutputIt write(OutputIt out, const void* value) { FMT_ENABLE_IF(std::is_same<T, void>::value)>
return write_ptr<Char>(out, to_uintptr(value), nullptr); OutputIt write(OutputIt out, const T* value,
const basic_format_specs<Char>& specs = {}, locale_ref = {}) {
return write_ptr<Char>(out, to_uintptr(value), &specs);
} }
template <typename Char, typename OutputIt, typename T> template <typename Char, typename OutputIt, typename T>
@ -2152,12 +2171,12 @@ class arg_formatter_base {
FMT_CONSTEXPR void on_int() { FMT_CONSTEXPR void on_int() {
// char is only formatted as int if there are specs. // char is only formatted as int if there are specs.
formatter.out_ = formatter.out_ = detail::write(formatter.out_, static_cast<int>(value),
detail::write_int(formatter.out_, static_cast<int>(value), formatter.specs_, formatter.locale_);
formatter.specs_, formatter.locale_);
} }
FMT_CONSTEXPR void on_char() { FMT_CONSTEXPR void on_char() {
formatter.out_ = write_char(formatter.out_, value, formatter.specs_); formatter.out_ =
detail::write<Char>(formatter.out_, value, formatter.specs_);
} }
}; };
@ -2199,7 +2218,7 @@ class arg_formatter_base {
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)> template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
FMT_CONSTEXPR FMT_INLINE iterator operator()(T value) { FMT_CONSTEXPR FMT_INLINE iterator operator()(T value) {
return out_ = detail::write_int(out_, value, specs_, locale_); return out_ = detail::write(out_, value, specs_, locale_);
} }
FMT_CONSTEXPR iterator operator()(Char value) { FMT_CONSTEXPR iterator operator()(Char value) {
@ -2883,10 +2902,7 @@ struct formatter<T, Char,
specs.width_ref, ctx); specs.width_ref, ctx);
detail::handle_dynamic_spec<detail::precision_checker>( detail::handle_dynamic_spec<detail::precision_checker>(
specs.precision, specs.precision_ref, ctx); specs.precision, specs.precision_ref, ctx);
using af = detail::arg_formatter<typename FormatContext::iterator, return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
typename FormatContext::char_type>;
return visit_format_arg(af(ctx, specs),
detail::make_arg<FormatContext>(val));
} }
private: private:

View File

@ -247,7 +247,8 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> {
// ignored for non-numeric types // ignored for non-numeric types
if (fmt_specs.align == align::none || fmt_specs.align == align::numeric) if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
fmt_specs.align = align::right; fmt_specs.align = align::right;
return write_char(this->out(), static_cast<Char>(value), fmt_specs); return detail::write<Char>(this->out(), static_cast<Char>(value),
fmt_specs);
} }
return base::operator()(value); return base::operator()(value);
} }