diff options
author | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-05-05 16:32:58 +0200 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-05-07 12:14:51 +0200 |
commit | 52f6ab55051ff43fd1b40ff06d9501043f8ba844 (patch) | |
tree | d5147bb12ef66988acd498c7f048d7727f58c4f7 /libstdc++-v3/testsuite/std | |
parent | 83ef989ee189902ca1d434feb0f3dd50519e92cb (diff) | |
download | gcc-52f6ab55051ff43fd1b40ff06d9501043f8ba844.zip gcc-52f6ab55051ff43fd1b40ff06d9501043f8ba844.tar.gz gcc-52f6ab55051ff43fd1b40ff06d9501043f8ba844.tar.bz2 |
libstdc++: Fix width computation for the chrono formatting [PR120114]
Use `__unicode::_field_width` to compute the field width of the output when writting
the formatted output for std::chrono::types. This applies both to characters copied
from format string, and one produced by localized formatting.
We also use _Str_sink::view() instead of get(), which avoids copying the content of
the buffer to std::string in case of small output.
PR libstdc++/120114
libstdc++-v3/ChangeLog:
* include/bits/chrono_io.h (__formatter_chrono::_M_format): Use __field_width.
* testsuite/std/time/format/pr120114.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite/std')
-rw-r--r-- | libstdc++-v3/testsuite/std/time/format/pr120114.cc | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120114.cc b/libstdc++-v3/testsuite/std/time/format/pr120114.cc new file mode 100644 index 0000000..c630bb3 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/format/pr120114.cc @@ -0,0 +1,125 @@ +// { dg-do run { target c++23 } } +// { dg-options "-fexec-charset=UTF-8" } +// { dg-timeout-factor 2 } + +#include <algorithm> +#include <chrono> +#include <testsuite_hooks.h> + +#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S) +#define WIDEN(S) WIDEN_(_CharT, S) + +template<typename _CharT> +void +test_from_format_string() +{ + std::basic_string<_CharT> res; + using namespace std::chrono_literals; + auto date = 2025y/std::chrono::May/05d; + + res = std::format(WIDEN("{:+<13%F\U0001f921}"), date); + VERIFY( res == WIDEN("2025-05-05\U0001f921+") ); + + res = std::format(WIDEN("{:->15%F\U0001f921}"), date); + VERIFY( res == WIDEN("---2025-05-05\U0001f921") ); + + res = std::format(WIDEN("{:=^20%F\U0001f921}"), date); + VERIFY( res == WIDEN("====2025-05-05\U0001f921====") ); +} + +template<typename _CharT> +void +test_formatted_value() +{ + // Custom time_put facet which returns Ideographic Telegraph Symbol + // for given month for Om. + struct TimePut : std::time_put<_CharT> + { + using iter_type = std::time_put<_CharT>::iter_type; + using char_type = std::time_put<_CharT>::char_type; + + iter_type + do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t, + char format, char modifier) const override + { + if (format != 'm' && modifier != 'm') + return std::time_put<_CharT>::do_put(out, io, fill, t, format, modifier); + std::basic_string_view<_CharT> str; + switch (t->tm_mon) + { + case 0: + str = WIDEN("\u32C0"); + break; + case 1: + str = WIDEN("\u32C1"); + break; + case 2: + str = WIDEN("\u32C2"); + break; + case 3: + str = WIDEN("\u32C3"); + break; + case 4: + str = WIDEN("\u32C4"); + break; + case 5: + str = WIDEN("\u32C5"); + break; + case 6: + str = WIDEN("\u32C6"); + break; + case 7: + str = WIDEN("\u32C7"); + break; + case 8: + str = WIDEN("\u32C8"); + break; + case 9: + str = WIDEN("\u32C9"); + break; + case 10: + str = WIDEN("\u32CA"); + break; + case 11: + str = WIDEN("\u32CB"); + break; + }; + return std::copy(str.begin(), str.end(), out); + } + }; + const std::locale loc(std::locale::classic(), new TimePut); + + std::basic_string<_CharT> res; + + res = std::format(loc, WIDEN("{:<1L%Om}"), std::chrono::January); + VERIFY( res == WIDEN("\u32C0") ); + + res = std::format(loc, WIDEN("{:>2L%Om}"), std::chrono::February); + VERIFY( res == WIDEN("\u32C1") ); + + res = std::format(loc, WIDEN("{:<3L%Om}"), std::chrono::March); + VERIFY( res == WIDEN("\u32C2 ") ); + + res = std::format(loc, WIDEN("{:^4L%Om}"), std::chrono::April); + VERIFY( res == WIDEN(" \u32C3 ") ); + + res = std::format(loc, WIDEN("{:>5L%Om}"), std::chrono::May); + VERIFY( res == WIDEN(" \u32C4") ); + + res = std::format(loc, WIDEN("{:+<6L%Om}"), std::chrono::June); + VERIFY( res == WIDEN("\u32C5++++") ); + + res = std::format(loc, WIDEN("{:=^7L%Om}"), std::chrono::July); + VERIFY( res == WIDEN("==\u32C6===") ); + + res = std::format(loc, WIDEN("{:->8L%Om}"), std::chrono::August); + VERIFY( res == WIDEN("------\u32C7") ); +} + +int main() +{ + test_from_format_string<char>(); + test_from_format_string<wchar_t>(); + test_formatted_value<char>(); + test_formatted_value<wchar_t>(); +} |