[PATCH] libstdc++: Use on_month_day istream operator in ZoneInfo parsing. [PR124852]
Jonathan Wakely
jwakely@redhat.com
Fri May 15 19:37:12 GMT 2026
On Wed, 13 May 2026 at 10:22 +0200, Tomasz Kamiński wrote:
>This patch changes ZoneInfo parsing, to use operator>> for on_month_day
>direclty, and removes on_day tag. The operator>>(istream&, on_month_day)
"directly"
>is updated to not override on.month if the MONTH component is not present,
>and set failbit instead. This allows to use in >> on >> time, to parse
>MONT DAY TIME.
"MONTH"
>
>We also handle failure to parse day number N for Www>=N or Www<=N
>productions, by leaving the day part of input unchanged and setting
>failbit.
>
> PR libsdc++/124852
>
>libstdc++-v3/ChangeLog:
>
> * src/c++20/tzdb.cc (on_month_day::on_day_t, on_month_day::on_day):
> Remove.
> (operator>>(istream&, on_month_day::day_t&)): Inlined in...
> (operator>>(istream&, on_month_day): Inlined on_month_day::on_day.
> Avoid modifying on.month if MONTH is not present. Report failure
> on failure to parse day for LessEq / GreaterEq.
>---
>Realized this yesterday, but decied that doing this as separate patch as this
>is reverting direction. If this causes some failure, I want git blame to
>show only me for it.
>
>Tested on x86_64-linux locally. OK for trunk?
OK for trunk with a few typos fixed (two above, two below).
> libstdc++-v3/src/c++20/tzdb.cc | 89 ++++++++++++----------------------
> 1 file changed, 30 insertions(+), 59 deletions(-)
>
>diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
>index f9238542274..8db86a8d4b0 100644
>--- a/libstdc++-v3/src/c++20/tzdb.cc
>+++ b/libstdc++-v3/src/c++20/tzdb.cc
>@@ -371,13 +371,6 @@ namespace std::chrono
> return ymd;
> }
>
>- struct on_day_t // tag type for reading ON and DAY fields only
>- {
>- on_month_day& parent;
>- friend istream& operator>>(istream&, on_day_t&&);
>- };
>-
>- on_day_t on_day() { return on_day_t{*this}; }
>
> friend istream& operator>>(istream&, on_month_day&);
> };
>@@ -2334,73 +2327,55 @@ namespace
> }
> };
>
>- // Read the day-component of an on_month_day expression (everything after
>- // the month). Three forms are accepted: a plain day-of-month number,
>- // "lastXxx" where Xxx is a weekday name (LastWeekday), or "Xxx<=N" or
>- // "Xxx>=N" (LessEq / GreaterEq). On failure the function sets failbit
>- // and leaves `to.parent` unchanged.
>- istream& operator>>(istream& in, on_month_day::on_day_t&& to)
>+ // Read the MONTH DAY. Three forms are accepted for DAY:
>+ // * a plain day-of-month number (DayOfMonth),
>+ // * "lastWww" where Www is a weekday name (LastWeekday),
>+ // * "Www<=N" or "Www>=N" (LessEq / GreaterEq).
>+ // On failure to read either MONTH or DAY this function set
"sets"
>+ // failbit. If DAY is not pared, only `on.month` is modified,
"parsed"
>+ // otherwise `on` is left unchanged.
>+ istream& operator>>(istream& in, on_month_day& on)
> {
> using enum on_month_day::Kind;
>-
>- on_month_day& on = to.parent;
>- int c = ws(in).peek();
>- if ('0' <= c && c <= '9')
>+ if (abbrev_month m{}; in >> m)
> {
>- unsigned d;
>- in >> d;
>- if (d <= 31) [[likely]]
>+ on.month = static_cast<unsigned>(m.m);
>+ if (int c = ws(in).peek(); '0' <= c && c <= '9')
> {
>- on.kind = DayOfMonth;
>- on.day_of_month = d;
>- return in;
>+ if (unsigned d; (in >> d) && (d <= 31)) [[likely]]
>+ {
>+ on.kind = DayOfMonth;
>+ on.day_of_month = d;
>+ return in;
>+ }
> }
>- }
>- else if (c == 'l') // lastSunday, lastWed, ...
>- {
>- in.ignore(4);
>- if (abbrev_weekday w{}; in >> w) [[likely]]
>+ else if (c == 'l') // lastSunday, lastWed, ...
> {
>- on.kind = LastWeekday;
>- on.day_of_week = w.wd.c_encoding();
>- return in;
>+ in.ignore(4);
>+ if (abbrev_weekday w{}; in >> w) [[likely]]
>+ {
>+ on.kind = LastWeekday;
>+ on.day_of_week = w.wd.c_encoding();
>+ return in;
>+ }
> }
>- }
>- else
>- {
>- abbrev_weekday w;
>- in >> w;
>- if (auto c = in.get(); c == '<' || c == '>')
>+ else if (abbrev_weekday w; in >> w) [[likely]]
> {
>- if (in.get() == '=')
>- {
>- unsigned d;
>- in >> d;
>- if (d <= 31) [[likely]]
>+ if (c = in.get(); c == '<' || c == '>')
>+ if (in.get() == '=')
>+ if (unsigned d; (in >> d) && (d <= 31)) [[likely]]
> {
> on.kind = c == '<' ? LessEq : GreaterEq;
> on.day_of_week = w.wd.c_encoding();
> on.day_of_month = d;
> return in;
> }
>- }
> }
> }
> in.setstate(ios::failbit);
> return in;
> }
>
>- istream& operator>>(istream& in, on_month_day& to)
>- {
>- on_month_day md{};
>- abbrev_month m{};
>- in >> m;
>- md.month = static_cast<unsigned>(m.m);
>- if (in >> md.on_day())
>- to = md;
>- return in;
>- }
>-
> istream& operator>>(istream& in, at_time& at)
> {
> int sign = 1;
>@@ -2506,11 +2481,7 @@ namespace
> on_month_day on{ .kind = on_month_day::DayOfMonth,
> .month = 1, .day_of_month = 1 };
> at_time t{};
>- if (abbrev_month m{January}; in >> m)
>- {
>- on.month = static_cast<unsigned>(m.m);
>- in >> on.on_day() >> t;
>- }
>+ in >> on >> t;
> year_month_day ymd = on.pin(year(y));
> inf.m_until = sys_days(ymd) + seconds(t.time);
> if (t.indicator != at_time::Universal)
>--
>2.54.0
>
>
More information about the Libstdc++
mailing list