aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/std
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-06-24 14:07:46 +0200
committerTomasz Kamiński <tkaminsk@redhat.com>2025-06-26 16:21:05 +0200
commit4b3cefed1a08344495fedec4982d85168bd8173f (patch)
tree5a40e343f598494ab7303e0ff2c81e97862b6f2b /libstdc++-v3/testsuite/std
parentaf5b72cf9f5640d24f28398b37c7208d6b2439ab (diff)
downloadgcc-4b3cefed1a08344495fedec4982d85168bd8173f.zip
gcc-4b3cefed1a08344495fedec4982d85168bd8173f.tar.gz
gcc-4b3cefed1a08344495fedec4982d85168bd8173f.tar.bz2
libstdc++: Type-erase chrono-data for formatting [PR110739]
This patch reworks the formatting for the chrono types, such that they are all formatted in terms of _ChronoData class, that includes all required fields. Populating each required field is performed in formatter for specific type, based on the chrono-spec used. To facilitate above, the _ChronoSpec now includes additional _M_needed field, that represnts the chrono data that is referenced by format spec (this value is also configured for __defSpec). This value differs from the value of __parts passed to _M_parse, which does include all fields that can be computed from input (e.g. weekday_indexed can be computed for year_month_day). Later it is used to fill _ChronoData, in particular _M_fill_* family of functions, to determine if given field needs to be set, and thus its value needs to be computed. In consequence _ChronoParts enum was extended with additional values, that allows more fine grained identification: * _TimeOfDay is separated into _HoursMinutesSeconds and _Subseconds, * _TimeZone is separated into _ZoneAbbrev and _ZoneOffset, * _LocalDays, _WeekdayIndex are defined and in included in _Date, * _Duration is removed, and instead _EpochUnits and _UnitSuffix are introduced. Furthermore, to avoid name conflicts _ChonoParts is now defined as enum class, with additional operators that simplify uses. In addition to fields that can be printed using chrono-spec, _ChronoData stores: * Total days in wall time (_M_ldays), day of year (_M_day_of_year) - used by struct tm construction, and for ISO calendar computation. * Total seconds in wall time (_M_lseconds) - this value may be different from sum of days, hours, minutes, seconds (e.g. see utc_time below). Included to allow future extension, like printing total minutes. * Total seconds since epoch - due offset different from above. Again to be used with future extension (e.g. %s as proposed in P2945R1). * Subseconds - count of attoseconds (10^(-18)), in addition to printing can be used to compute fractional hours, minutes. The both total seconds fields use single _TotalSeconds enumerator in _ChronoParts, that when present in combination with _EpochUnits or _LocalDays indicates that _M_eseconds (_EpochSeconds) or _M_lseconds (_LocalSeconds) are provided/required. To handle type formatting of time since epoch ('%Q'|_EpochUnits), we use the format_args mechanism, where the result of +d.count() (see LWG4118) is erased into make_format_args to local __arg_store, that is later referenced by _M_ereps (_M_ereps.get(0)). To handle precision values, and in prepartion to allow user to configure ones, we store the precision as third element of _M_ereps (_M_ereps.get(2)), this allows duration with precision to be printed using "{0:{2}}". For subseconds the precision is handled differently depending on the representation: * for integral reps, _M_subseconds value is used to determine fractional value, precision is trimmed to 18 digits; * for floating-points, _M_ereps stores duration<Rep> initialized with only fractional seconds, that is later formatted with precision. Always using _M_subseconds fields for integral duration, means that we do not use formattter for user-defined durations that are considered to be integral (see empty_spec.cc file change). To avoid potentially expensive computation of _M_subseconds, we make sure that _ChronoParts::_Subseconds is set only if _Subseconds are needed. In particular we remove this flag for localized ouput in _M_parse. Construction of the _M_ereps as described above is handled by __formatter_duration, that is then used to format duration, hh_mm_ss and time_points specializations. This class also handles _UnitSuffix, the _M_units_suffix field is populated either with predefined suffix (chrono::__detail::__units_suffix) or one produced locally. Finally, formatters for types listed below contains type specific logic: * hh_mm_ss - we do not compute total duration and seconds, unless explicitly requested, as such computation may overflow; * utc_time - for time during leap second insertion, the _M_seconds field is increased to 60; * __local_time_fmt - exception is thrown if zone offset (_ZoneOffset) or abbrevation (_ZoneAbbrev) is requsted, but corresponding pointer is null, futhermore conversion from `char` to `wchar_t` for abbreviation is performed if needed. PR libstdc++/110739 libstdc++-v3/ChangeLog: * include/bits/chrono_io.h (__format::__no_timezone_available): Removed, replaced with separate throws in formatter for __local_time_fmt (__format::_ChronoParts): Defined additional enumertors and declared as enum class. (__format::operator&(_ChronoParts, _ChronoParts)) (__format::operator&=(_ChronoParts&, _ChronoParts)) (__format::operator-(_ChronoParts, _ChronoParts)) (__format::operator-=(_ChronoParts&, _ChronoParts)) (__format::operator==(_ChronoParts, decltype(nullptr))) (_ChronoSpec::_M_time_only, _ChronoSpec::_M_floating_point_rep) (_ChronoSpec::_M_custom_rep, _ChronoSpec::_M_needed) (_ChronoSpec::_M_needs, __format::_ChronoData): Define. (__format::__formatter_chrono): Redefine to accept _ChronoData. (__formatter_chrono::_M_format_to_ostream): Moved to __formatter_duration. (__format::__formatter_duration): Define. (__formatter_chrono_info::format): Pass value-constructed _ChronoData. (std::formatter<chrono::day, _CharT>) (std::formatter<chrono::month, _CharT>) (std::formatter<chrono::year, _CharT>) (std::formatter<chrono::weekday, _CharT>) (std::formatter<chrono::weekday_indexed, _CharT>) (std::formatter<chrono::weekday_last, _CharT>) (std::formatter<chrono::month_day, _CharT>) (std::formatter<chrono::month_day_last, _CharT>) (std::formatter<chrono::month_weekday, _CharT>) (std::formatter<chrono::month_weekday_indexed, _CharT>) (std::formatter<chrono::month_weekday_last, _CharT>) (std::formatter<chrono::year_month, _CharT>) (std::formatter<chrono::year_month_day, _CharT>) (std::formatter<chrono::year_month_day_last, _CharT>) (std::formatter<chrono::year_month_weekday, _CharT>) (std::formatter<chrono::year_month_weekday_indexed, _CharT>) (std::formatter<chrono::year_month_weekday_last, _CharT>): Construct _ChronoData in format, and configure _M_needed in _ChronoSpec. (std::formatter<chrono::duration<_Rep, _Period>, _CharT>) (std::formatter<chrono::hh_mm_ss<_Duration>, _CharT>) (std::formatter<chrono::sys_time<_Duration>, _CharT>) (std::formatter<chrono::utc_time<_Duration>, _CharT>) (std::formatter<chrono::tai_time<_Duration>, _CharT>) (std::formatter<chrono::gps_time<_Duration>, _CharT>) (std::formatter<chrono::file_time<_Duration>, _CharT>) (std::formatter<chrono::local_time<_Duration>, _CharT>) (std::formatter<chrono::_detail::__local_time_fmt<_Duration>, _CharT>): Reworked in terms of __formatter_duration and _ChronoData. (std::formatter<chrono::_detail::__utc_leap_second<_Duration>, _CharT>): Removed. (_Parser<_Duration>::operator()): Adjusted for _ChronoParts being enum class. * include/std/chrono (__detail::__utc_leap_second): Removed, replaced with simply bumping _M_seconds in _ChronoData. * testsuite/std/time/format/empty_spec.cc: Updated %S integral ouput. 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/empty_spec.cc16
1 files changed, 8 insertions, 8 deletions
diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index 5f7b868..923df3d 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -355,30 +355,30 @@ test_hh_mm_ss_cust()
// +plus returns long, so formatted as long
const duration<Rep<long>, std::milli> asLong(dt.count());
verify( hms<milliseconds>(asLong),
- WIDEN("22:24:54.123[via format]") );
+ WIDEN("22:24:54.123") );
verify( hms<deciseconds>(asLong),
- WIDEN("22:24:54.1[via format]") );
+ WIDEN("22:24:54.1") );
verify( hms<seconds>(asLong),
WIDEN("22:24:54") );
verify( hms<milliseconds>(-asLong),
- WIDEN("-22:24:54.123[via format]") );
+ WIDEN("-22:24:54.123") );
verify( hms<deciseconds>(-asLong),
- WIDEN("-22:24:54.1[via format]") );
+ WIDEN("-22:24:54.1") );
verify( hms<seconds>(-asLong),
WIDEN("-22:24:54") );
// +asRep returns Rep<>, so formatted as Rep<>
const duration<Rep<>, std::milli> asRep(dt.count());
verify( hms<milliseconds>(asRep),
- WIDEN("22:24:54.123[via format]") );
+ WIDEN("22:24:54.123") );
verify( hms<deciseconds>(asRep),
- WIDEN("22:24:54.1[via format]") );
+ WIDEN("22:24:54.1") );
verify( hms<seconds>(asLong),
WIDEN("22:24:54") );
verify( hms<milliseconds>(-asLong),
- WIDEN("-22:24:54.123[via format]") );
+ WIDEN("-22:24:54.123") );
verify( hms<deciseconds>(-asLong),
- WIDEN("-22:24:54.1[via format]") );
+ WIDEN("-22:24:54.1") );
verify( hms<seconds>(-asLong),
WIDEN("-22:24:54") );
}