]> git.ipfire.org Git - thirdparty/gcc.git/commit
libstdc++: Minimalize temporary allocations when width is specified [PR109162]
authorTomasz Kamiński <tkaminsk@redhat.com>
Wed, 23 Apr 2025 11:17:09 +0000 (13:17 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Fri, 25 Apr 2025 14:12:16 +0000 (16:12 +0200)
commit01e5ef3e8b91288f5d387a27708f9f8979a50edf
treeff71f9e4907769a327d5ed834d5f967370202956
parentb115ae245a6afbe86756be9056c4365cd0811b88
libstdc++: Minimalize temporary allocations when width is specified [PR109162]

When width parameter is specified for formatting range, tuple or escaped
presentation of string, we used to format characters to temporary string,
and write produce sequence padded according to the spec. However, once the
estimated width of formatted representation of input is larger than the value
of spec width, it can be written directly to the output. This limits size of
required allocation, especially for large ranges.

Similarly, if precision (maximum) width is provided for string presentation,
only a prefix of sequence with estimated width not greater than precision, needs
to be buffered.

To realize above, this commit implements a new _Padding_sink specialization.
This sink holds an output iterator, a value of padding width, (optionally)
maximum width and a string buffer inherited from _Str_sink.
Then any incoming characters are treated in one of following ways, depending of
estimated width W of written sequence:
* written to string if W is smaller than padding width and maximum width (if present)
* ignored, if W is greater than maximum width
* written to output iterator, if W is greater than padding width

The padding sink is used instead of _Str_sink in __format::__format_padded,
__formatter_str::_M_format_escaped functions.

Furthermore __formatter_str::_M_format implementation was reworked, to:
* reduce number of instantiations by delegating to _Rg& and const _Rg& overloads,
* non-debug presentation is written to _Out directly or via _Padding_sink
* if maximum width is specified for debug format with non-unicode encoding,
  string size is limited to that number.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/bits/formatfwd.h (__simply_formattable_range): Moved from
std/format.
* include/std/format (__formatter_str::_format): Extracted escaped
string handling to separate method...
(__formatter_str::_M_format_escaped): Use __Padding_sink.
(__formatter_str::_M_format): Adjusted implementation.
(__formatter_str::_S_trunc): Extracted as namespace function...
(__format::_truncate): Extracted from __formatter_str::_S_trunc.
(__format::_Seq_sink): Removed forward declarations, made members
protected and non-final.
(_Seq_sink::_M_trim): Define.
(_Seq_sink::_M_span): Renamed from view.
(_Seq_sink::view): Returns string_view instead of span.
(__format::_Str_sink): Moved after _Seq_sink.
(__format::__format_padded): Use _Padding_sink.
* testsuite/std/format/debug.cc: Add timeout and new tests.
* testsuite/std/format/ranges/sequence.cc: Specify unicode as
encoding and new tests.
* testsuite/std/format/ranges/string.cc: Likewise.
* testsuite/std/format/tuple.cc: Likewise.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
libstdc++-v3/include/bits/formatfwd.h
libstdc++-v3/include/std/format
libstdc++-v3/testsuite/std/format/debug.cc
libstdc++-v3/testsuite/std/format/ranges/sequence.cc
libstdc++-v3/testsuite/std/format/ranges/string.cc
libstdc++-v3/testsuite/std/format/tuple.cc