aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-05-05 11:07:59 +0200
committerTomasz Kamiński <tkaminsk@redhat.com>2025-05-09 07:22:48 +0200
commita8db867515837a232cae10968b32480a3b3a7ee3 (patch)
treecc8d2ee53b75e7faff581c92a6d493ca5edd8cab
parent1a2c62212bd912f5c8130e992ce282b542599f98 (diff)
downloadgcc-a8db867515837a232cae10968b32480a3b3a7ee3.zip
gcc-a8db867515837a232cae10968b32480a3b3a7ee3.tar.gz
gcc-a8db867515837a232cae10968b32480a3b3a7ee3.tar.bz2
libstdc++: Provide ability to query _Sink_iter if writes are discarded.
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. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
-rw-r--r--libstdc++-v3/include/std/format64
1 files changed, 52 insertions, 12 deletions
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 054ce35..b3192cf 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
@@ -3660,11 +3683,20 @@ namespace __format
}
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