From 519571edecd77cd5d44e9fd638af1b9578cd72ad Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 29 May 2020 09:10:08 -0700 Subject: [PATCH] Simplify arg_formatter_base --- include/fmt/chrono.h | 3 ++- include/fmt/format.h | 50 ++++++++++++++++++++++++-------------------- include/fmt/printf.h | 12 +++++++---- test/format | 10 +++++---- test/format-test.cc | 6 +++--- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 79a119e6..938f117a 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -200,7 +200,8 @@ To safe_duration_cast(std::chrono::duration from, ec = 1; return {}; } - const auto min1 = (std::numeric_limits::min)() / Factor::num; + const auto min1 = + (std::numeric_limits::min)() / Factor::num; if (count < min1) { ec = 1; return {}; diff --git a/include/fmt/format.h b/include/fmt/format.h index 17acde08..f5829a6d 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -886,6 +886,13 @@ template <> inline wchar_t decimal_point(locale_ref loc) { return decimal_point_impl(loc); } +template bool equal2(const Char* lhs, const char* rhs) { + return lhs[0] == rhs[0] && lhs[1] == rhs[1]; +} +inline bool equal2(const char* lhs, const char* rhs) { + return memcmp(lhs, rhs, 2) == 0; +} + template void copy2(Char* dst, const char* src) { *dst++ = static_cast(*src++); *dst = static_cast(*src); @@ -1677,11 +1684,12 @@ template struct is_integral : std::is_integral {}; template <> struct is_integral : std::true_type {}; template <> struct is_integral : std::true_type {}; -template +template class arg_formatter_base { public: - using char_type = typename Range::value_type; - using iterator = typename Range::iterator; + using char_type = Char; + using iterator = OutputIt; using format_specs = basic_format_specs; private: @@ -1753,8 +1761,8 @@ class arg_formatter_base { *it++ = value; } - template ::value)> - void write(Char value) { + template ::value)> + void write(Ch value) { auto&& it = reserve(1); *it++ = value; } @@ -1769,18 +1777,18 @@ class arg_formatter_base { it = std::copy(value.begin(), value.end(), it); } - template - void write(const Char* s, size_t size, const format_specs& specs) { + template + void write(const Ch* s, size_t size, const format_specs& specs) { auto width = specs.width != 0 - ? count_code_points(basic_string_view(s, size)) + ? count_code_points(basic_string_view(s, size)) : 0; out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) { return copy_str(s, s + size, it); }); } - template - void write(basic_string_view s, const format_specs& specs = {}) { + template + void write(basic_string_view s, const format_specs& specs = {}) { out_ = detail::write(out_, s, specs); } @@ -1808,8 +1816,8 @@ class arg_formatter_base { } public: - arg_formatter_base(Range r, format_specs* s, locale_ref loc) - : out_(r.begin()), locale_(loc), specs_(s) {} + arg_formatter_base(OutputIt out, format_specs* s, locale_ref loc) + : out_(out), locale_(loc), specs_(s) {} iterator operator()(monostate) { FMT_ASSERT(false, "invalid argument type"); @@ -2716,10 +2724,13 @@ FMT_API void report_error(format_func func, int error_code, /** The default argument formatter. */ template -class arg_formatter : public detail::arg_formatter_base { +class arg_formatter + : public detail::arg_formatter_base { private: using char_type = typename Range::value_type; - using base = detail::arg_formatter_base; + using base = detail::arg_formatter_base; using context_type = basic_format_context; context_type& ctx_; @@ -2741,7 +2752,7 @@ class arg_formatter : public detail::arg_formatter_base { context_type& ctx, basic_format_parse_context* parse_ctx = nullptr, format_specs* specs = nullptr) - : base(Range(ctx.out()), specs, ctx.locale()), + : base(ctx.out(), specs, ctx.locale()), ctx_(ctx), parse_ctx_(parse_ctx) {} @@ -3156,13 +3167,6 @@ struct format_handler : detail::error_handler { basic_format_arg arg; }; -template bool equal2(const Char* lhs, const char* rhs) { - return lhs[0] == rhs[0] && lhs[1] == rhs[1]; -} -inline bool equal2(const char* lhs, const char* rhs) { - return memcmp(lhs, rhs, 2) == 0; -} - /** Formats arguments and writes the output to the range. */ template typename Context::iterator vformat_to( @@ -3170,7 +3174,7 @@ typename Context::iterator vformat_to( basic_format_args args, detail::locale_ref loc = detail::locale_ref()) { format_handler h(out, format_str, args, loc); - if (format_str.size() == 2 && equal2(format_str.data(), "{}")) { + if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) { auto arg = detail::get_arg(h.context, 0); h.parse_context.advance_to(&format_str[1]); return visit_format_arg(ArgFormatter(h.context, &h.parse_context), arg); diff --git a/include/fmt/printf.h b/include/fmt/printf.h index a1c4b403..0649abb3 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -208,13 +208,16 @@ template class basic_printf_context; \endrst */ template -class printf_arg_formatter : public detail::arg_formatter_base { +class printf_arg_formatter + : public detail::arg_formatter_base { public: using iterator = typename Range::iterator; private: using char_type = typename Range::value_type; - using base = detail::arg_formatter_base; + using base = detail::arg_formatter_base; using context_type = basic_printf_context; context_type& context_; @@ -240,7 +243,7 @@ class printf_arg_formatter : public detail::arg_formatter_base { \endrst */ printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx) - : base(Range(iter), &specs, detail::locale_ref()), context_(ctx) {} + : base(iter, &specs, detail::locale_ref()), context_(ctx) {} template ::value)> iterator operator()(T value) { @@ -512,7 +515,8 @@ OutputIt basic_printf_context::format() { // For d, i, o, u, x, and X conversion specifiers, if a precision is // specified, the '0' flag is ignored if (specs.precision >= 0 && arg.is_integral()) - specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-' present. + specs.fill[0] = + ' '; // Ignore '0' flag for non-numeric types or if '-' present. if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) { auto str = visit_format_arg(detail::get_cstring(), arg); auto str_end = str + specs.precision; diff --git a/test/format b/test/format index 589ac241..3ba38f49 100644 --- a/test/format +++ b/test/format @@ -490,10 +490,12 @@ namespace detail { template class arg_formatter - : public fmt::internal::arg_formatter_base { + : public fmt::internal::arg_formatter_base< + typename Range::iterator, typename Range::value_type, error_handler> { private: using char_type = typename Range::value_type; - using base = fmt::internal::arg_formatter_base; + using base = fmt::internal::arg_formatter_base< + typename Range::iterator, char_type, error_handler>; using format_context = std::basic_format_context; using parse_context = basic_format_parse_context; @@ -513,7 +515,7 @@ class arg_formatter \endrst */ arg_formatter(format_context& ctx, parse_context* parse_ctx = nullptr, fmt::format_specs* spec = nullptr) - : base(Range(ctx.out()), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {} + : base(ctx.out(), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {} using base::operator(); @@ -693,7 +695,7 @@ struct formatter { fmt::internal::handle_dynamic_spec( specs_.precision, specs_.precision_ref, ctx); using range_type = fmt::internal::output_range; + typename FormatContext::char_type>; return visit_format_arg(arg_formatter(ctx, nullptr, &specs_), basic_format_arg(val)); } diff --git a/test/format-test.cc b/test/format-test.cc index dfdf2e45..19d16e2f 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1809,7 +1809,7 @@ TEST(FormatTest, StrongEnum) { using buffer_range = fmt::buffer_range; class mock_arg_formatter - : public fmt::detail::arg_formatter_base { + : public fmt::detail::arg_formatter_base { private: #if FMT_USE_INT128 MOCK_METHOD1(call, void(__int128_t value)); @@ -1818,12 +1818,12 @@ class mock_arg_formatter #endif public: - typedef fmt::detail::arg_formatter_base base; + typedef fmt::detail::arg_formatter_base base; typedef buffer_range range; mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*, fmt::format_specs* s = nullptr) - : base(fmt::detail::get_container(ctx.out()), s, ctx.locale()) { + : base(ctx.out(), s, ctx.locale()) { EXPECT_CALL(*this, call(42)); }