On Tue, 6 May 2025 at 13:30, Tomasz Kamiński <tkami...@redhat.com> wrote:
>
> This patch provides _M_discarding functiosn for _Sink_iter and _Sink function
> that returns true, if any further writes to the _Sink_iter and underlying 
> _Sink,
> will be discared, and thus can be omitted.
>
> Currently only the _Padding_sink reports discarding mode of if width of 
> sequence
> characters is greater than _M_maxwidth (precision), or underlying _Sink is
> discarding characters. The _M_discarding override, is separate function from
> _M_ignoring, that remain annotated with [[__gnu__::__always_inline__]].
>
> Despite having notion of maximum characters to be written (_M_max), _Iter_sink
> nevers discard characters, as the total number of characters that would be 
> written
> needs to be returned by format_to_n. This is documented in-source by 
> providing an
> _Iter_sink::_M_discarding override, that always returns false.
>
> The function is currently queried only by the _Padding_sinks, that may be 
> stacked
> for example a range is formatted, with padding with being specified both for 
> range
> itself and it's elements. The state of underlying sink is checked during 
> construction
> and after each write (_M_sync_discarding).
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/format (__Sink_iter<_CharT>::_M_discarding)
>         (__Sink<_CharT>::_M_discarding, _Iter_sink<_CharT, 
> _OutIter>::_M_discarding)
>         (_Padding_sinl<_CharT, _Out>::_M_padwidth)
>         (_Padding_sink<_CharT, _Out>::_M_maxwidth): Remove const.
>         (_Padding_sink<_CharT, _Out>::_M_sync_discarding)
>         (_Padding_sink<_CharT, _Out>::_M_discarding): Define.
>         (_Padding_sink<_CharT, _Out>::_Padding_sink(_Out, size_t, size_t))
>         (_Padding_sink<_CharT, _Out>::_M_force_update):
>         (_Padding_sink<_CharT, _Out>::_M_flush): Call _M_sync_discarding.
>         (_Padding_sink<_CharT, _Out>::_Padding_sink(_Out, size_t)): Delegate.
> ---
> I have replaced operator==(default_sentinel_t) with _M_discarding member
> function. Replaced standard reference to textual one.
> For the comments on _Iter_sink, I have removed the second sentence:
> +       // format_to_n return total number of characters, that would be 
> written,
> +       // see C++20 [format.functions] p20
> OK for trunk?

OK, thanks.


>
>
>  libstdc++-v3/include/std/format | 64 ++++++++++++++++++++++++++-------
>  1 file changed, 52 insertions(+), 12 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
> index 054ce350440..b3192cf2868 100644
> --- a/libstdc++-v3/include/std/format
> +++ b/libstdc++-v3/include/std/format
> @@ -3144,6 +3144,10 @@ namespace __format
>        auto
>        _M_reserve(size_t __n) const
>        { return _M_sink->_M_reserve(__n); }
> +
> +      bool
> +      _M_discarding() const
> +      { return _M_sink->_M_discarding(); }
>      };
>
>    // Abstract base class for type-erased character sinks.
> @@ -3263,6 +3267,11 @@ namespace __format
>        _M_bump(size_t __n)
>        { _M_next += __n; }
>
> +      // Returns true if the _Sink is discarding incoming characters.
> +      virtual bool
> +      _M_discarding() const
> +      { return false; }
> +
>      public:
>        _Sink(const _Sink&) = delete;
>        _Sink& operator=(const _Sink&) = delete;
> @@ -3488,6 +3497,14 @@ namespace __format
>         _M_count += __s.size();
>        }
>
> +      bool
> +      _M_discarding() const override
> +      {
> +       // format_to_n return total number of characters, that would be 
> written,
> +       // see C++20 [format.functions] p20
> +       return false;
> +      }
> +
>      public:
>        [[__gnu__::__always_inline__]]
>        explicit
> @@ -3550,6 +3567,14 @@ namespace __format
>           }
>        }
>
> +      bool
> +      _M_discarding() const override
> +      {
> +       // format_to_n return total number of characters, that would be 
> written,
> +       // see C++20 [format.functions] p20
> +       return false;
> +      }
> +
>        typename _Sink<_CharT>::_Reservation
>        _M_reserve(size_t __n) final
>        {
> @@ -3636,17 +3661,15 @@ namespace __format
>    template<typename _Out, typename _CharT>
>      class _Padding_sink : public _Str_sink<_CharT>
>      {
> -      const size_t _M_padwidth;
> -      const size_t _M_maxwidth;
> +      size_t _M_padwidth;
> +      size_t _M_maxwidth;
>        _Out _M_out;
>        size_t _M_printwidth;
>
>        [[__gnu__::__always_inline__]]
>        bool
>        _M_ignoring() const
> -      {
> -       return _M_printwidth >= _M_maxwidth;
> -      }
> +      { return _M_printwidth >= _M_maxwidth; }
>
>        [[__gnu__::__always_inline__]]
>        bool
> @@ -3659,12 +3682,21 @@ namespace __format
>         return false;
>        }
>
> +      void
> +      _M_sync_discarding()
> +      {
> +       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
> +         if (_M_out._M_discarding())
> +           _M_maxwidth = _M_printwidth;
> +      }
> +
>        void
>        _M_flush()
>        {
>         span<_CharT> __new = this->_M_used();
>         basic_string_view<_CharT> __str(__new.data(), __new.size());
>         _M_out = __format::__write(std::move(_M_out), __str);
> +       _M_sync_discarding();
>         this->_M_rewind();
>        }
>
> @@ -3682,7 +3714,10 @@ namespace __format
>         // We have more characters than padidng, no padding is needed,
>         // write direclty to _M_out.
>         if (_M_printwidth >= _M_padwidth)
> -         _M_out = __format::__write(std::move(_M_out), __str);
> +         {
> +           _M_out = __format::__write(std::move(_M_out), __str);
> +           _M_sync_discarding();
> +         }
>         // We reached _M_maxwidth that is smaller than _M_padwidth.
>         // Store the prefix sequence in _M_seq, and free _M_buf.
>         else
> @@ -3718,6 +3753,10 @@ namespace __format
>           _Str_sink<_CharT>::_M_overflow();
>        }
>
> +      bool
> +      _M_discarding() const override
> +      { return _M_ignoring(); }
> +
>        typename _Sink<_CharT>::_Reservation
>        _M_reserve(size_t __n) override
>        {
> @@ -3752,15 +3791,16 @@ namespace __format
>
>      public:
>        [[__gnu__::__always_inline__]]
> -      explicit _Padding_sink(_Out __out, size_t __padwidth)
> -      : _M_padwidth(__padwidth), _M_maxwidth(-1),
> +      explicit
> +      _Padding_sink(_Out __out, size_t __padwidth, size_t __maxwidth)
> +      : _M_padwidth(__padwidth), _M_maxwidth(__maxwidth),
>         _M_out(std::move(__out)), _M_printwidth(0)
> -      { }
> +      { _M_sync_discarding(); }
>
>        [[__gnu__::__always_inline__]]
> -      explicit _Padding_sink(_Out __out, size_t __padwidth, size_t 
> __maxwidth)
> -      : _M_padwidth(__padwidth), _M_maxwidth(__maxwidth),
> -       _M_out(std::move(__out)), _M_printwidth(0)
> +      explicit
> +      _Padding_sink(_Out __out, size_t __padwidth)
> +      : _Padding_sink(std::move(__out), __padwidth, (size_t)-1)
>        { }
>
>        _Out
> --
> 2.49.0
>

Reply via email to