From: Tomasz Kamiński Date: Wed, 7 May 2025 10:25:01 +0000 (+0200) Subject: libstdc++: Use _Padding_sink in __formatter_chrono to produce padded output. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=08d34c8812f0d1927dfedea14dc4f50799066dc3;p=thirdparty%2Fgcc.git libstdc++: Use _Padding_sink in __formatter_chrono to produce padded output. Formatting code is extracted to _M_format_to function, that produced output to specified iterator. This function is now invoked either with __fc.out() directly (if width is not specified) or _Padding_sink::out(). This avoid formatting to temporary string if no padding is requested, and minimize allocations otherwise. For more details see commit message of r16-142-g01e5ef3e8b91288f5d387a27708f9f8979a50edf. This should not increase number of instantiations, as implementation only produce basic_format_context with _Sink_iter as iterator, which is also _Padding_sink iterator. libstdc++-v3/ChangeLog: * include/bits/chrono_io.h (__formatter_chrono::_M_format_to): Extracted from _M_format. (__formatter_chrono::_M_format): Use _Padding_sink and delegate to _M_format_to. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 620227a9f35..ace8b9f2629 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -503,9 +503,7 @@ namespace __format _M_format(const _Tp& __t, _FormatContext& __fc, bool __is_neg = false) const { - auto __first = _M_spec._M_chrono_specs.begin(); - const auto __last = _M_spec._M_chrono_specs.end(); - if (__first == __last) + if (_M_spec._M_chrono_specs.empty()) return _M_format_to_ostream(__t, __fc, __is_neg); #if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8 @@ -525,29 +523,29 @@ namespace __format __fc._M_loc = __with_encoding_conversion(__loc); } #endif - - _Sink_iter<_CharT> __out; - __format::_Str_sink<_CharT> __sink; - bool __write_direct = false; - if constexpr (is_same_v>) - { - if (_M_spec._M_width_kind == __format::_WP_none) - { - __out = __fc.out(); - __write_direct = true; - } - else - __out = __sink.out(); - } - else - __out = __sink.out(); - // formatter passes the correct value of __is_neg // for durations but for hh_mm_ss we decide it here. if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) __is_neg = __t.is_negative(); + const size_t __padwidth = _M_spec._M_get_width(__fc); + if (__padwidth == 0) + return _M_format_to(__t, __fc.out(), __fc, __is_neg); + + using _Out = typename _FormatContext::iterator; + _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth); + _M_format_to(__t, __sink.out(), __fc, __is_neg); + return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill); + } + + template + _Out + _M_format_to(const _Tp& __t, _Out __out, _FormatContext& __fc, + bool __is_neg) const + { + auto __first = _M_spec._M_chrono_specs.begin(); + const auto __last = _M_spec._M_chrono_specs.end(); + auto __print_sign = [&__is_neg, &__out] { if constexpr (chrono::__is_duration_v<_Tp> || __is_specialization_of<_Tp, chrono::hh_mm_ss>) @@ -699,20 +697,7 @@ namespace __format } } while (__first != __last); - - if constexpr (is_same_v>) - if (__write_direct) - return __out; - - auto __str = __sink.view(); - size_t __width; - if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) - __width = __unicode::__field_width(__str); - else - __width = __str.size(); - return __format::__write_padded_as_spec(__str, __width, - __fc, _M_spec); + return std::move(__out); } _ChronoSpec<_CharT> _M_spec;