[gcc r16-489] libstdc++: Use _Padding_sink in __formatter_chrono to produce padded output.

Tomasz Kaminski tkaminsk@gcc.gnu.org
Fri May 9 06:43:23 GMT 2025


https://gcc.gnu.org/g:08d34c8812f0d1927dfedea14dc4f50799066dc3

commit r16-489-g08d34c8812f0d1927dfedea14dc4f50799066dc3
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date:   Wed May 7 12:25:01 2025 +0200

    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 <jwakely@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h | 55 +++++++++++++----------------------
 1 file changed, 20 insertions(+), 35 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 620227a9f352..ace8b9f26292 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<typename _FormatContext::iterator,
-				  _Sink_iter<_CharT>>)
-	    {
-	      if (_M_spec._M_width_kind == __format::_WP_none)
-		{
-		  __out = __fc.out();
-		  __write_direct = true;
-		}
-	      else
-		__out = __sink.out();
-	    }
-	  else
-	    __out = __sink.out();
-
 	  // formatter<duration> 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<typename _Tp, typename _Out, typename _FormatContext>
+	_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<typename _FormatContext::iterator,
-				  _Sink_iter<_CharT>>)
-	    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;


More information about the Libstdc++-cvs mailing list