From da0f84c42cd608c4938ece93762cacf9ac5ff3da Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sat, 13 Jan 2024 09:21:42 -0800 Subject: [PATCH] Cleanup copy functions and move to base.h --- include/fmt/base.h | 34 ++++++++++++++ include/fmt/chrono.h | 14 +++--- include/fmt/compile.h | 8 ++-- include/fmt/format.h | 100 +++++++++++++----------------------------- include/fmt/ranges.h | 15 +++---- 5 files changed, 83 insertions(+), 88 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index cd2c7df5..d41de5f2 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1123,6 +1123,40 @@ using appender = basic_appender; namespace detail { +// An optimized version of std::copy with the output value type (T). +template +auto copy(InputIt begin, InputIt end, appender out) -> appender { + get_container(out).append(begin, end); + return out; +} + +template ::value)> +auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + get_container(out).append(begin, end); + return out; +} + +template ::value)> +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { + while (begin != end) *out++ = static_cast(*begin++); + return out; +} + +template +FMT_CONSTEXPR auto copy(const T* begin, const T* end, T* out) -> T* { + if (is_constant_evaluated()) return copy(begin, end, out); + auto size = to_unsigned(end - begin); + if (size > 0) memcpy(out, begin, size * sizeof(T)); + return out + size; +} + +template +FMT_CONSTEXPR auto copy(basic_string_view s, OutputIt out) -> OutputIt { + return copy(s.begin(), s.end(), out); +} + template constexpr auto has_const_formatter_impl(T*) -> decltype(typename Context::template formatter_type().format( diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 9d54574e..f7cd975b 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -382,9 +382,9 @@ auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) to_utf8>(); if (!u.convert({unit.buf, to_unsigned(unit.end - unit.buf)})) FMT_THROW(format_error("failed to format time")); - return copy_str(u.c_str(), u.c_str() + u.size(), out); + return copy(u.c_str(), u.c_str() + u.size(), out); } - return copy_str(in.data(), in.data() + in.size(), out); + return copy(in.data(), in.data() + in.size(), out); } template OutputIt { codecvt_result unit; write_codecvt(unit, sv, loc); - return copy_str(unit.buf, unit.end, out); + return copy(unit.buf, unit.end, out); } template OutputIt { return out_; } FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { - out_ = copy_str(begin, end, out_); + out_ = copy(begin, end, out_); } void on_abbr_weekday() { @@ -1437,7 +1437,7 @@ class tm_writer { write_digit2_separated(buf, to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()), to_unsigned(split_year_lower(tm_year())), '/'); - out_ = copy_str(std::begin(buf), std::end(buf), out_); + out_ = copy(std::begin(buf), std::end(buf), out_); } void on_iso_date() { auto year = tm_year(); @@ -1453,7 +1453,7 @@ class tm_writer { write_digit2_separated(buf + 2, static_cast(year % 100), to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()), '-'); - out_ = copy_str(std::begin(buf) + offset, std::end(buf), out_); + out_ = copy(std::begin(buf) + offset, std::end(buf), out_); } void on_utc_offset(numeric_system ns) { format_utc_offset_impl(tm_, ns); } @@ -1586,7 +1586,7 @@ class tm_writer { char buf[8]; write_digit2_separated(buf, to_unsigned(tm_hour12()), to_unsigned(tm_min()), to_unsigned(tm_sec()), ':'); - out_ = copy_str(std::begin(buf), std::end(buf), out_); + out_ = copy(std::begin(buf), std::end(buf), out_); *out_++ = ' '; on_am_pm(); } else { diff --git a/include/fmt/compile.h b/include/fmt/compile.h index b4767b58..d6278521 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -15,9 +15,9 @@ FMT_BEGIN_NAMESPACE namespace detail { -template -FMT_CONSTEXPR inline auto copy_str(InputIt begin, InputIt end, - counting_iterator it) -> counting_iterator { +template +FMT_CONSTEXPR inline auto copy(InputIt begin, InputIt end, counting_iterator it) + -> counting_iterator { return it + (end - begin); } @@ -148,7 +148,7 @@ template struct field { const T& arg = get_arg_checked(args...); if constexpr (std::is_convertible_v>) { auto s = basic_string_view(arg); - return copy_str(s.begin(), s.end(), out); + return copy(s.begin(), s.end(), out); } return write(out, arg); } diff --git a/include/fmt/format.h b/include/fmt/format.h index 46c89e34..17b8e761 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -513,42 +513,6 @@ FMT_INLINE void assume(bool condition) { #endif } -template -auto copy_str(InputIt begin, InputIt end, appender out) -> appender { - get_container(out).append(begin, end); - return out; -} - -template ::value)> -auto copy_str(InputIt begin, InputIt end, OutputIt out) -> OutputIt { - get_container(out).append(begin, end); - return out; -} - -template ::value)> -FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) - -> OutputIt { - while (begin != end) *out++ = static_cast(*begin++); - return out; -} - -template , U>::value&& is_char::value)> -FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* { - if (is_constant_evaluated()) return copy_str(begin, end, out); - auto size = to_unsigned(end - begin); - if (size > 0) memcpy(out, begin, size * sizeof(U)); - return out + size; -} - -template -FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt { - return detail::copy_str(rng.begin(), rng.end(), out); -} - // An approximation of iterator_t for pre-C++20 systems. template using iterator_t = decltype(std::begin(std::declval())); @@ -640,9 +604,9 @@ FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { } template -FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end, - OutputIt out) -> OutputIt { - return copy_str(begin, end, out); +FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end, + OutputIt out) -> OutputIt { + return copy(begin, end, out); } // A public domain branchless UTF-8 decoder by Christopher Wellons: @@ -723,7 +687,7 @@ FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { } if (auto num_chars_left = s.data() + s.size() - p) { char buf[2 * block_size - 1] = {}; - copy_str(p, p + num_chars_left, buf); + copy(p, p + num_chars_left, buf); const char* buf_ptr = buf; do { auto end = decode(buf_ptr, p); @@ -952,7 +916,7 @@ class basic_memory_buffer : public detail::buffer { size_t size = other.size(), capacity = other.capacity(); if (data == other.store_) { this->set(store_, capacity); - detail::copy_str(other.store_, other.store_ + size, store_); + detail::copy(other.store_, other.store_ + size, store_); } else { this->set(data, capacity); // Set pointer to the inline array so that delete is not called @@ -1035,8 +999,8 @@ namespace detail_exported { #if FMT_USE_NONTYPE_TEMPLATE_ARGS template struct fixed_string { constexpr fixed_string(const Char (&str)[N]) { - detail::copy_str(static_cast(str), - str + N, data); + detail::copy(static_cast(str), + str + N, data); } Char data[N] = {}; }; @@ -1393,7 +1357,7 @@ FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size) // Buffer is large enough to hold all digits (digits10 + 1). Char buffer[digits10() + 1] = {}; auto end = format_decimal(buffer, value, size).end; - return {out, detail::copy_str_noinline(buffer, end, out)}; + return {out, detail::copy_noinline(buffer, end, out)}; } template @@ -1420,7 +1384,7 @@ FMT_CONSTEXPR inline auto format_uint(It out, UInt value, int num_digits, // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). char buffer[num_bits() / BASE_BITS + 1] = {}; format_uint(buffer, value, num_digits, upper); - return detail::copy_str_noinline(buffer, buffer + num_digits, out); + return detail::copy_noinline(buffer, buffer + num_digits, out); } // A converter from UTF-8 to UTF-16. @@ -1776,8 +1740,7 @@ FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, auto fill_size = fill.size(); if (fill_size == 1) return detail::fill_n(it, n, fill[0]); auto data = fill.data(); - for (size_t i = 0; i < n; ++i) - it = copy_str(data, data + fill_size, it); + for (size_t i = 0; i < n; ++i) it = copy(data, data + fill_size, it); return it; } @@ -1813,11 +1776,11 @@ constexpr auto write_padded(OutputIt out, const format_specs& specs, template FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, const format_specs& specs) -> OutputIt { - return write_padded( - out, specs, bytes.size(), [bytes](reserve_iterator it) { - const char* data = bytes.data(); - return copy_str(data, data + bytes.size(), it); - }); + return write_padded(out, specs, bytes.size(), + [bytes](reserve_iterator it) { + const char* data = bytes.data(); + return copy(data, data + bytes.size(), it); + }); } template @@ -1913,7 +1876,7 @@ auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt { Char buf[width]; fill_n(buf, width, static_cast('0')); format_uint<4>(buf, cp, width); - return copy_str(buf, buf + width, out); + return copy(buf, buf + width, out); } template @@ -1964,7 +1927,7 @@ auto write_escaped_string(OutputIt out, basic_string_view str) auto begin = str.begin(), end = str.end(); do { auto escape = find_escape(begin, end); - out = copy_str(begin, escape.begin, out); + out = copy(begin, escape.begin, out); begin = escape.end; if (!begin) break; out = write_escaped_cp(out, escape); @@ -2115,9 +2078,8 @@ template class digit_grouping { for (int i = 0, sep_index = static_cast(separators.size() - 1); i < num_digits; ++i) { if (num_digits - i == separators[sep_index]) { - out = - copy_str(thousands_sep_.data(), - thousands_sep_.data() + thousands_sep_.size(), out); + out = copy(thousands_sep_.data(), + thousands_sep_.data() + thousands_sep_.size(), out); --sep_index; } *out++ = static_cast(digits[to_unsigned(i)]); @@ -2386,7 +2348,7 @@ FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, return write_padded(out, specs, size, width, [=](reserve_iterator it) { if (is_debug) return write_escaped_string(it, s); - return copy_str(data, data + size, it); + return copy(data, data + size, it); }); } template @@ -2547,7 +2509,7 @@ FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, if (is_zero_fill) specs.fill[0] = static_cast(' '); return write_padded(out, specs, size, [=](reserve_iterator it) { if (sign) *it++ = detail::sign(sign); - return copy_str(str, str + str_size, it); + return copy(str, str + str_size, it); }); } @@ -2569,7 +2531,7 @@ inline auto get_significand_size(const dragonbox::decimal_fp& f) -> int { template constexpr auto write_significand(OutputIt out, const char* significand, int significand_size) -> OutputIt { - return copy_str(significand, significand + significand_size, out); + return copy(significand, significand + significand_size, out); } template inline auto write_significand(OutputIt out, UInt significand, @@ -2622,19 +2584,19 @@ inline auto write_significand(OutputIt out, UInt significand, Char buffer[digits10() + 2]; auto end = write_significand(buffer, significand, significand_size, integral_size, decimal_point); - return detail::copy_str_noinline(buffer, end, out); + return detail::copy_noinline(buffer, end, out); } template FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, int significand_size, int integral_size, Char decimal_point) -> OutputIt { - out = detail::copy_str_noinline(significand, - significand + integral_size, out); + out = detail::copy_noinline(significand, significand + integral_size, + out); if (!decimal_point) return out; *out++ = decimal_point; - return detail::copy_str_noinline(significand + integral_size, - significand + significand_size, out); + return detail::copy_noinline(significand + integral_size, + significand + significand_size, out); } template @@ -2651,8 +2613,8 @@ FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, integral_size, decimal_point); grouping.apply( out, basic_string_view(buffer.data(), to_unsigned(integral_size))); - return detail::copy_str_noinline(buffer.data() + integral_size, - buffer.end(), out); + return detail::copy_noinline(buffer.data() + integral_size, + buffer.end(), out); } template (data, data + size, bigits_.data()); + copy(data, data + size, bigits_.data()); exp_ = other.exp_; } @@ -3741,7 +3703,7 @@ template FMT_CONSTEXPR auto write(OutputIt out, basic_string_view value) -> OutputIt { auto it = reserve(out, value.size()); - it = copy_str_noinline(value.begin(), value.end(), it); + it = copy_noinline(value.begin(), value.end(), it); return base_iterator(out, it); } diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 0f78d484..6a66843a 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -265,8 +265,7 @@ template struct format_tuple_element { template void operator()(const formatter& f, const T& v) { - if (i > 0) - ctx.advance_to(detail::copy_str(separator, ctx.out())); + if (i > 0) ctx.advance_to(detail::copy(separator, ctx.out())); ctx.advance_to(f.format(v, ctx)); ++i; } @@ -327,11 +326,11 @@ struct formatter auto format(const Tuple& value, FormatContext& ctx) const -> decltype(ctx.out()) { - ctx.advance_to(detail::copy_str(opening_bracket_, ctx.out())); + ctx.advance_to(detail::copy(opening_bracket_, ctx.out())); detail::for_each2( formatters_, value, detail::format_tuple_element{0, ctx, separator_}); - return detail::copy_str(closing_bracket_, ctx.out()); + return detail::copy(closing_bracket_, ctx.out()); } }; @@ -439,18 +438,18 @@ struct range_formatter< auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) { detail::range_mapper> mapper; auto out = ctx.out(); - out = detail::copy_str(opening_bracket_, out); + out = detail::copy(opening_bracket_, out); int i = 0; auto it = detail::range_begin(range); auto end = detail::range_end(range); for (; it != end; ++it) { - if (i > 0) out = detail::copy_str(separator_, out); + if (i > 0) out = detail::copy(separator_, out); ctx.advance_to(out); auto&& item = *it; out = underlying_.format(mapper.map(item), ctx); ++i; } - out = detail::copy_str(closing_bracket_, out); + out = detail::copy(closing_bracket_, out); return out; } }; @@ -568,7 +567,7 @@ struct formatter, Char> { out = value_formatter_.format(*it, ctx); ++it; while (it != value.end) { - out = detail::copy_str(value.sep.begin(), value.sep.end(), out); + out = detail::copy(value.sep.begin(), value.sep.end(), out); ctx.advance_to(out); out = value_formatter_.format(*it, ctx); ++it;