From d39ebf3ff251bf199f88f917cecc504230823342 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Mon, 21 Oct 2019 06:51:21 -0700 Subject: [PATCH] Optimize counting --- include/fmt/chrono.h | 4 ++-- include/fmt/color.h | 17 ++++++++--------- include/fmt/compile.h | 5 +---- include/fmt/format.h | 18 ++++++++++-------- include/fmt/printf.h | 3 +-- test/format-test.cc | 2 +- 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index e0fd21b1..671d2f33 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -582,8 +582,8 @@ struct chrono_formatter { void write(Rep value, int width) { write_sign(); if (isnan(value)) return write_nan(); - uint32_or_64_or_128_t n = to_unsigned( - to_nonnegative_int(value, max_value())); + uint32_or_64_or_128_t n = + to_unsigned(to_nonnegative_int(value, max_value())); int num_digits = internal::count_digits(n); if (width > num_digits) out = std::fill_n(out, width - num_digits, '0'); out = format_decimal(out, n, num_digits); diff --git a/include/fmt/color.h b/include/fmt/color.h index dbaafb2a..8de5b294 100644 --- a/include/fmt/color.h +++ b/include/fmt/color.h @@ -498,9 +498,9 @@ void vformat_to(basic_memory_buffer& buf, const text_style& ts, } } // namespace internal -template > +template > void vprint(std::FILE* f, const text_style& ts, const S& format, - basic_format_args > args) { + basic_format_args> args) { basic_memory_buffer buf; internal::vformat_to(buf, ts, to_string_view(format), args); buf.push_back(Char(0)); @@ -519,7 +519,7 @@ template (format_str); - using context = buffer_context >; + using context = buffer_context>; format_arg_store as{args...}; vprint(f, ts, format_str, basic_format_args(as)); } @@ -537,10 +537,10 @@ void print(const text_style& ts, const S& format_str, const Args&... args) { return print(stdout, ts, format_str, args...); } -template > +template > inline std::basic_string vformat( const text_style& ts, const S& format_str, - basic_format_args > args) { + basic_format_args> args) { basic_memory_buffer buf; internal::vformat_to(buf, ts, to_string_view(format_str), args); return fmt::to_string(buf); @@ -558,12 +558,11 @@ inline std::basic_string vformat( "The answer is {}", 42); \endrst */ -template > +template > inline std::basic_string format(const text_style& ts, const S& format_str, const Args&... args) { - return vformat( - ts, to_string_view(format_str), - {internal::make_args_checked(format_str, args...)}); + return vformat(ts, to_string_view(format_str), + {internal::make_args_checked(format_str, args...)}); } FMT_END_NAMESPACE diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 337bed31..491d6574 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -570,10 +570,7 @@ format_to_n_result format_to_n(OutputIt out, size_t n, template std::size_t formatted_size(const CompiledFormat& cf, const Args&... args) { - return format_to( - internal::counting_iterator(), - cf, args...) - .count(); + return format_to(internal::counting_iterator(), cf, args...).count(); } FMT_END_NAMESPACE diff --git a/include/fmt/format.h b/include/fmt/format.h index 9ca0be18..c359840e 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -292,19 +292,21 @@ inline Iterator& reserve(Iterator& it, std::size_t) { // An output iterator that counts the number of objects written to it and // discards them. -template class counting_iterator { +class counting_iterator { private: std::size_t count_; - mutable T blackhole_; public: using iterator_category = std::output_iterator_tag; - using value_type = T; using difference_type = std::ptrdiff_t; - using pointer = T*; - using reference = T&; + using pointer = void; + using reference = void; using _Unchecked_type = counting_iterator; // Mark iterator as checked. + struct value_type { + template void operator=(const T&) {} + }; + counting_iterator() : count_(0) {} std::size_t count() const { return count_; } @@ -320,7 +322,7 @@ template class counting_iterator { return it; } - T& operator*() const { return blackhole_; } + value_type operator*() const { return {}; } }; template class truncating_iterator_base { @@ -1132,7 +1134,7 @@ template class grisu_writer { int full_exp = num_digits + exp - 1; int precision = params.num_digits > 0 ? params.num_digits : 16; params_.fixed |= full_exp >= -4 && full_exp < precision; - auto it = grisu_prettify(digits, num_digits, exp, counting_iterator(), + auto it = grisu_prettify(digits, num_digits, exp, counting_iterator(), params_, '\0'); size_ = it.count(); } @@ -3482,7 +3484,7 @@ inline std::basic_string internal::vformat( */ template inline std::size_t formatted_size(string_view format_str, const Args&... args) { - auto it = format_to(internal::counting_iterator(), format_str, args...); + auto it = format_to(internal::counting_iterator(), format_str, args...); return it.count(); } diff --git a/include/fmt/printf.h b/include/fmt/printf.h index 8be33b99..ced6b1b2 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -469,8 +469,7 @@ OutputIt basic_printf_context::format() { // Parse argument index, flags and width. unsigned arg_index = parse_header(it, end, specs); - if (arg_index == 0) - on_error("argument index out of range"); + if (arg_index == 0) on_error("argument index out of range"); // Parse precision. if (it != end && *it == '.') { diff --git a/test/format-test.cc b/test/format-test.cc index 8bd2fe9d..67eb9be8 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -182,7 +182,7 @@ TEST(UtilTest, ParseNonnegativeInt) { } TEST(IteratorTest, CountingIterator) { - fmt::internal::counting_iterator it; + fmt::internal::counting_iterator it; auto prev = it++; EXPECT_EQ(prev.count(), 0); EXPECT_EQ(it.count(), 1);