]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Use _Padding_sink in __formatter_chrono to produce padded output.
authorTomasz Kamiński <tkaminsk@redhat.com>
Wed, 7 May 2025 10:25:01 +0000 (12:25 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Fri, 9 May 2025 06:34:57 +0000 (08:34 +0200)
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>
libstdc++-v3/include/bits/chrono_io.h

index 620227a9f35215cf33b2d558c0e4b6081177a136..ace8b9f2629208fba9f371b3cffea2c1aa8b3acc 100644 (file)
@@ -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;