[PATCH v2] libstdc++: Provide ability to query _Sink_iter if writes are discarded.
Jonathan Wakely
jwakely@redhat.com
Thu May 8 17:30:32 GMT 2025
On Tue, 6 May 2025 at 13:30, Tomasz Kamiński <tkaminsk@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
>
More information about the Libstdc++
mailing list