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 >