From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 84CFE3858D3C for ; Mon, 10 Jan 2022 13:40:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 84CFE3858D3C Received: from mail-yb1-f199.google.com (mail-yb1-f199.google.com [209.85.219.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-266-Lasnnm7XMdKxLHRh8B-4Ag-1; Mon, 10 Jan 2022 08:40:19 -0500 X-MC-Unique: Lasnnm7XMdKxLHRh8B-4Ag-1 Received: by mail-yb1-f199.google.com with SMTP id n2-20020a255902000000b0060f9d75eafeso27241133ybb.1 for ; Mon, 10 Jan 2022 05:40:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=cUeJFMlR/V7ye8jCTG/b7d3rEa9+orruqlgh6vJKqDE=; b=IUtIPyik70Cd81cvOoLuIGYlvWb97FyRw0/EllB75Ayo9e747URwEQ2CTZYz7XjcZ+ wu4USiyOUiwowuQLtv6Y79Pe/Lf9r3cuv7LaWu1LmRgkgkgAaPxMmaScvbK03M1hIbMF g9K1q7FQU7Mo8ST7FTfbZdR/NrolaUEyGoEOear+M8hqzqnRSms+RoC+W05zoGeFygGf xD+9hvK54nWEueN/Byetl0zieeeR0W8s8Zn2H3t8cLbEsJZURcZ8RWuaLtYjWLO7XbVv IlRWiac4LFmckuZzvYiYAJSANwrqC9TeGYWl0gyL7zFrRPz3d1bT/V6K2GWwDx1OT40X H0cA== X-Gm-Message-State: AOAM532/i9TjBil3/xqMCFvu6rwe+r7m8P6AqLyUF0+V/NKWlpsm/IV9 EcHfv8Nrbv1jJqURGM4KvMi6H3jmc34syjqxHhk/sE3nRT3dYyziNGnR9VhsEc0ZfcOStTP+8+j B+SgQTsGQNjAFAn0CicsteTkg+nItAJ4N9g== X-Received: by 2002:a05:6902:702:: with SMTP id k2mr59819491ybt.66.1641822018798; Mon, 10 Jan 2022 05:40:18 -0800 (PST) X-Google-Smtp-Source: ABdhPJykZKgGQBRfGvD6WkmsHvlcp2kAngV4Jq240u4DwKOImS80YxMqN4vxOvmIDnDUhvoL5FgthAPjhlHe7gcE8dk= X-Received: by 2002:a05:6902:702:: with SMTP id k2mr59819427ybt.66.1641822018237; Mon, 10 Jan 2022 05:40:18 -0800 (PST) MIME-Version: 1.0 References: <20211216144647.GU2646553@tucnak> <20211217071642.GD2646553@tucnak> In-Reply-To: <20211217071642.GD2646553@tucnak> From: Jonathan Wakely Date: Mon, 10 Jan 2022 13:40:06 +0000 Message-ID: Subject: Re: [PATCH] libstdc++, v2: Add %j, %U, %w, %W time_get support, fix %y, %Y, %C, %p [PR77760] To: Jakub Jelinek Cc: "libstdc++" , gcc Patches X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-6.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, HTML_MESSAGE, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Jan 2022 13:40:31 -0000 On Fri, 17 Dec 2021 at 07:19, Jakub Jelinek via Libstdc++ < libstdc++@gcc.gnu.org> wrote: > On Thu, Dec 16, 2021 at 03:46:47PM +0100, Jakub Jelinek via Gcc-patches > wrote: > > glibc strptime passes around some state, what fields in struct tm have > been > > set and what needs to be finalized through possibly recursive calls, and > > at the end performs various finalizations, like applying %p so that it > > works for both %I %p and %p %I orders, or applying century so that both > > %C %y and %y %C works, or computation of missing fields from others > > (e.g. from %Y and %j one can compute tm_mon, tm_mday and tm_wday, > > from %Y %U %w, %Y %W %w, %Y %U %a, or %Y %W %w one can compute > > tm_mon, tm_mday, tm_yday or e.g. from %Y %m %d one can compute tm_wday > > and tm_yday. > ... > > Here is an updated patch with _M_ prefixes on members instead of __ > and no uglification of parameters and automatic vars in *.cc. No changes > otherwise, bootstrapped/regtested on x86_64-linux and i686-linux > successfully. > OK for trunk, thanks. > > 2021-12-17 Jakub Jelinek > > PR libstdc++/77760 > * include/bits/locale_facets_nonio.h (__time_get_state): New > struct. > (time_get::_M_extract_via_format): Declare new method with > __time_get_state& as an extra argument. > * include/bits/locale_facets_nonio.tcc (_M_extract_via_format): Add > __state argument, set various fields in it while parsing. Handle > %j, > %U, %w and %W, fix up handling of %y, %Y and %C, don't adjust > tm_hour > for %p immediately. Add a wrapper around the method without the > __state argument for backwards compatibility. > (_M_extract_num): Remove all __len == 4 special cases. > (time_get::do_get_time, time_get::do_get_date, time_get::do_get): > Zero > initialize __state, pass it to _M_extract_via_format and finalize > it > at the end. > (do_get_year): For 1-2 digit parsed years, map 0-68 to 2000-2068, > 69-99 to 1969-1999. For 3-4 digit parsed years use that as year. > (get): If do_get isn't overloaded from the locale_facets_nonio.tcc > version, don't call do_get but call _M_extract_via_format instead > to > pass around state. > * config/abi/pre/gnu.ver (GLIBCXX_3.4.30): Export > _M_extract_via_format > with extra __time_get_state and > __time_get_state::_M_finalize_state. > * src/c++98/locale_facets.cc (is_leap, day_of_the_week, > day_of_the_year): New functions in anon namespace. > (mon_yday): New var in anon namespace. > (__time_get_state::_M_finalize_state): Define. > * testsuite/22_locale/time_get/get/char/4.cc: New test. > * testsuite/22_locale/time_get/get/wchar_t/4.cc: New test. > * testsuite/22_locale/time_get/get_year/char/1.cc (test01): Parse > 197 > as year 197AD instead of error. > * testsuite/22_locale/time_get/get_year/char/5.cc (test01): Parse > 1 as > year 2001 instead of error. > * testsuite/22_locale/time_get/get_year/char/6.cc: New test. > * testsuite/22_locale/time_get/get_year/wchar_t/1.cc (test01): > Parse > 197 as year 197AD instead of error. > * testsuite/22_locale/time_get/get_year/wchar_t/5.cc (test01): > Parse > 1 as year 2001 instead of error. > * testsuite/22_locale/time_get/get_year/wchar_t/6.cc: New test. > > --- libstdc++-v3/include/bits/locale_facets_nonio.h.jj 2021-12-10 > 22:17:54.541591942 +0100 > +++ libstdc++-v3/include/bits/locale_facets_nonio.h 2021-12-17 > 00:21:33.125297992 +0100 > @@ -355,6 +355,30 @@ namespace std _GLIBCXX_VISIBILITY(defaul > { > _GLIBCXX_BEGIN_NAMESPACE_VERSION > > + struct __time_get_state > + { > + // Finalize state. > + void > + _M_finalize_state(tm* __tm); > + > + unsigned int _M_have_I : 1; > + unsigned int _M_have_wday : 1; > + unsigned int _M_have_yday : 1; > + unsigned int _M_have_mon : 1; > + unsigned int _M_have_mday : 1; > + unsigned int _M_have_uweek : 1; > + unsigned int _M_have_wweek : 1; > + unsigned int _M_have_century : 1; > + unsigned int _M_is_pm : 1; > + unsigned int _M_want_century : 1; > + unsigned int _M_want_xday : 1; > + unsigned int _M_pad1 : 5; > + unsigned int _M_week_no : 6; > + unsigned int _M_pad2 : 10; > + int _M_century; > + int _M_pad3; > + }; > + > _GLIBCXX_BEGIN_NAMESPACE_CXX11 > > /** > @@ -756,6 +780,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 > _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& > __io, > ios_base::iostate& __err, tm* __tm, > const _CharT* __format) const; > + > + // Extract on a component-by-component basis, via __format > argument, with > + // state. > + iter_type > + _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& > __io, > + ios_base::iostate& __err, tm* __tm, > + const _CharT* __format, > + __time_get_state &__state) const; > }; > > template > --- libstdc++-v3/include/bits/locale_facets_nonio.tcc.jj 2021-12-14 > 22:48:04.656769701 +0100 > +++ libstdc++-v3/include/bits/locale_facets_nonio.tcc 2021-12-17 > 00:22:05.258841761 +0100 > @@ -691,7 +691,8 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > time_get<_CharT, _InIter>:: > _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& > __io, > ios_base::iostate& __err, tm* __tm, > - const _CharT* __format) const > + const _CharT* __format, > + __time_get_state &__state) const > { > const locale& __loc = __io._M_getloc(); > const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> > >(__loc); > @@ -722,7 +723,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > __beg = _M_extract_name(__beg, __end, __mem, __days, > 14, __io, __tmperr); > if (!__tmperr) > - __tm->tm_wday = __mem % 7; > + { > + __tm->tm_wday = __mem % 7; > + __state._M_have_wday = 1; > + } > break; > case 'h': > case 'b': > @@ -734,14 +738,31 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > __beg = _M_extract_name(__beg, __end, __mem, > __months, 24, __io, __tmperr); > if (!__tmperr) > - __tm->tm_mon = __mem % 12; > + { > + __tm->tm_mon = __mem % 12; > + __state._M_have_mon = 1; > + __state._M_want_xday = 1; > + } > break; > case 'c': > // Default time and date representation. > const char_type* __dt[2]; > __tp._M_date_time_formats(__dt); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __dt[0]); > + __tm, __dt[0], __state); > + if (!__tmperr) > + __state._M_want_xday = 1; > + break; > + case 'C': > + // Century. > + __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2, > + __io, __tmperr); > + if (!__tmperr) > + { > + __state._M_century = __mem; > + __state._M_have_century = 1; > + __state._M_want_xday = 1; > + } > break; > case 'd': > case 'e': > @@ -751,35 +772,60 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, > __io, __tmperr); > if (!__tmperr) > - __tm->tm_mday = __mem; > + { > + __tm->tm_mday = __mem; > + __state._M_have_mday = 1; > + __state._M_want_xday = 1; > + } > break; > case 'D': > // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] > __cs = "%m/%d/%y"; > __ctype.widen(__cs, __cs + 9, __wcs); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __wcs); > + __tm, __wcs, __state); > + if (!__tmperr) > + __state._M_want_xday = 1; > break; > case 'H': > // Hour [00, 23]. [tm_hour] > __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, > __io, __tmperr); > if (!__tmperr) > - __tm->tm_hour = __mem; > + { > + __tm->tm_hour = __mem; > + __state._M_have_I = 0; > + } > break; > case 'I': > // Hour [01, 12]. [tm_hour] > __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, > __io, __tmperr); > if (!__tmperr) > - __tm->tm_hour = __mem % 12; > + { > + __tm->tm_hour = __mem % 12; > + __state._M_have_I = 1; > + } > + break; > + case 'j': > + // Day number of year. > + __beg = _M_extract_num(__beg, __end, __mem, 1, 366, 3, > + __io, __tmperr); > + if (!__tmperr) > + { > + __tm->tm_yday = __mem - 1; > + __state._M_have_yday = 1; > + } > break; > case 'm': > // Month [01, 12]. [tm_mon] > __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, > __io, __tmperr); > if (!__tmperr) > - __tm->tm_mon = __mem - 1; > + { > + __tm->tm_mon = __mem - 1; > + __state._M_have_mon = 1; > + } > break; > case 'M': > // Minute [00, 59]. [tm_min] > @@ -802,23 +848,22 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > break; > __beg = _M_extract_name(__beg, __end, __mem, __ampm, > 2, __io, __tmperr); > - // FIXME: This only works if %I comes before %p. > if (!__tmperr && __mem) > - __tm->tm_hour += 12; > + __state._M_is_pm = 1; > break; > case 'r': > // Locale's 12-hour clock time format (in C %I:%M:%S %p). > const char_type* __ampm_format; > __tp._M_am_pm_format(&__ampm_format); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __ampm_format); > + __tm, __ampm_format, > __state); > break; > case 'R': > // Equivalent to (%H:%M). > __cs = "%H:%M"; > __ctype.widen(__cs, __cs + 6, __wcs); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __wcs); > + __tm, __wcs, __state); > break; > case 'S': > // Seconds. [tm_sec] > @@ -830,41 +875,105 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > #endif > __io, __tmperr); > if (!__tmperr) > - __tm->tm_sec = __mem; > + __tm->tm_sec = __mem; > break; > case 'T': > // Equivalent to (%H:%M:%S). > __cs = "%H:%M:%S"; > __ctype.widen(__cs, __cs + 9, __wcs); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __wcs); > + __tm, __wcs, __state); > + break; > + case 'U': > + // Week number of the year (Sunday as first day of week). > + __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2, > + __io, __tmperr); > + if (!__tmperr) > + { > + __state._M_week_no = __mem; > + __state._M_have_uweek = 1; > + } > + break; > + case 'w': > + // Weekday [tm_wday] > + __beg = _M_extract_num(__beg, __end, __mem, 0, 6, 1, > + __io, __tmperr); > + if (!__tmperr) > + { > + __tm->tm_wday = __mem; > + __state._M_have_wday = 1; > + } > + break; > + case 'W': > + // Week number of the year (Monday as first day of week). > + __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2, > + __io, __tmperr); > + if (!__tmperr) > + { > + __state._M_week_no = __mem; > + __state._M_have_wweek = 1; > + } > break; > case 'x': > // Locale's date. > const char_type* __dates[2]; > __tp._M_date_formats(__dates); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __dates[0]); > + __tm, __dates[0], __state); > break; > case 'X': > // Locale's time. > const char_type* __times[2]; > __tp._M_time_formats(__times); > __beg = _M_extract_via_format(__beg, __end, __io, > __tmperr, > - __tm, __times[0]); > + __tm, __times[0], __state); > break; > case 'y': > - case 'C': // C99 > - // Two digit year. > + // The last 2 digits of year. > + __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2, > + __io, __tmperr); > + if (!__tmperr) > + { > + __state._M_want_century = 1; > + __state._M_want_xday = 1; > + // As an extension, if the 2 digits are followed by > + // 1-2 further digits, treat it like %Y. > + __c = 0; > + if (__beg != __end) > + __c = __ctype.narrow(*__beg, '*'); > + if (__c >= '0' && __c <= '9') > + { > + ++__beg; > + __mem = __mem * 10 + (__c - '0'); > + if (__beg != __end) > + { > + __c = __ctype.narrow(*__beg, '*'); > + if (__c >= '0' && __c <= '9') > + { > + ++__beg; > + __mem = __mem * 10 + (__c - '0'); > + } > + } > + __mem -= 1900; > + __state._M_want_century = 0; > + } > + // Otherwise, as per POSIX 2008, 00-68 is 2000-2068, > + // while 69-99 is 1969-1999. > + else if (__mem < 69) > + __mem += 100; > + __tm->tm_year = __mem; > + } > + break; > case 'Y': > - // Year [1900). > - // NB: We parse either two digits, implicitly years since > - // 1900, or 4 digits, full year. In both cases we can > - // reconstruct [tm_year]. See also libstdc++/26701. > + // Year. > __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, > __io, __tmperr); > if (!__tmperr) > - __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900; > + { > + __tm->tm_year = __mem - 1900; > + __state._M_want_century = 0; > + __state._M_want_xday = 1; > + } > break; > case 'Z': > // Timezone info. > @@ -928,6 +1037,18 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > template > _InIter > time_get<_CharT, _InIter>:: > + _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& > __io, > + ios_base::iostate& __err, tm* __tm, > + const _CharT* __format) const > + { > + __time_get_state __state = __time_get_state(); > + return _M_extract_via_format(__beg, __end, __io, __err, __tm, > + __format, __state); > + } > + > + template > + _InIter > + time_get<_CharT, _InIter>:: > _M_extract_num(iter_type __beg, iter_type __end, int& __member, > int __min, int __max, size_t __len, > ios_base& __io, ios_base::iostate& __err) const > @@ -949,13 +1070,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > else > break; > } > - // Special encoding for do_get_year, 'y', and 'Y' above. > - if (__len == 4 && __i == 2) > - __member = __value - 100; > - else if (__len == 4 && __i == 4) > - __member = __value; > - else if (__len == 2 && __i && __i <= 2 > - && __value >= __min && __value <= __max) > + if (__i && __value >= __min && __value <= __max) > __member = __value; > else > __err |= ios_base::failbit; > @@ -1212,8 +1327,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> > >(__loc); > const char_type* __times[2]; > __tp._M_time_formats(__times); > + __time_get_state __state = __time_get_state(); > __beg = _M_extract_via_format(__beg, __end, __io, __err, > - __tm, __times[0]); > + __tm, __times[0], __state); > + __state._M_finalize_state(__tm); > if (__beg == __end) > __err |= ios_base::eofbit; > return __beg; > @@ -1229,8 +1346,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> > >(__loc); > const char_type* __dates[2]; > __tp._M_date_formats(__dates); > + __time_get_state __state = __time_get_state(); > __beg = _M_extract_via_format(__beg, __end, __io, __err, > - __tm, __dates[0]); > + __tm, __dates[0], __state); > + __state._M_finalize_state(__tm); > if (__beg == __end) > __err |= ios_base::eofbit; > return __beg; > @@ -1296,11 +1415,38 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > { > int __tmpyear; > ios_base::iostate __tmperr = ios_base::goodbit; > + const locale& __loc = __io._M_getloc(); > + const ctype<_CharT>& __ctype = use_facet >(__loc); > > - __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4, > + __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2, > __io, __tmperr); > if (!__tmperr) > - __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900; > + { > + char __c = 0; > + if (__beg != __end) > + __c = __ctype.narrow(*__beg, '*'); > + // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is > 2000-2068. > + // For 3-4 digit year, use it as year. > + // __tm->tm_year needs year - 1900 though. > + if (__c >= '0' && __c <= '9') > + { > + ++__beg; > + __tmpyear = __tmpyear * 10 + (__c - '0'); > + if (__beg != __end) > + { > + __c = __ctype.narrow(*__beg, '*'); > + if (__c >= '0' && __c <= '9') > + { > + ++__beg; > + __tmpyear = __tmpyear * 10 + (__c - '0'); > + } > + } > + __tmpyear -= 1900; > + } > + else if (__tmpyear < 69) > + __tmpyear += 100; > + __tm->tm_year = __tmpyear; > + } > else > __err |= ios_base::failbit; > > @@ -1321,6 +1467,21 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > const locale& __loc = __io._M_getloc(); > ctype<_CharT> const& __ctype = use_facet >(__loc); > __err = ios_base::goodbit; > + bool __use_state = false; > +#if __GNUC__ >= 5 > +#pragma GCC diagnostic push > +#pragma GCC diagnostic ignored "-Wpmf-conversions" > + // Nasty hack. The C++ standard mandates that get invokes the > do_get > + // virtual method, but unfortunately at least without an ABI change > + // for the facets we can't keep state across the different do_get > + // calls. So e.g. if __fmt is "%p %I:%M:%S", we can't handle it > + // properly, because we first handle the %p am/pm specifier and only > + // later the 12-hour format specifier. > + if ((void*)(this->*(&time_get::do_get)) == > (void*)(&time_get::do_get)) > + __use_state = true; > +#pragma GCC diagnostic pop > +#endif > + __time_get_state __state = __time_get_state(); > while (__fmt != __fmtend && > __err == ios_base::goodbit) > { > @@ -1331,6 +1492,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > } > else if (__ctype.narrow(*__fmt, 0) == '%') > { > + const char_type* __fmt_start = __fmt; > char __format; > char __mod = 0; > if (++__fmt == __fmtend) > @@ -1351,8 +1513,26 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > __err = ios_base::failbit; > break; > } > - __s = this->do_get(__s, __end, __io, __err, __tm, __format, > - __mod); > + if (__use_state) > + { > + char_type __new_fmt[4]; > + __new_fmt[0] = __fmt_start[0]; > + __new_fmt[1] = __fmt_start[1]; > + if (__mod) > + { > + __new_fmt[2] = __fmt_start[2]; > + __new_fmt[3] = char_type(); > + } > + else > + __new_fmt[2] = char_type(); > + __s = _M_extract_via_format(__s, __end, __io, __err, > __tm, > + __new_fmt, __state); > + if (__s == __end) > + __err |= ios_base::eofbit; > + } > + else > + __s = this->do_get(__s, __end, __io, __err, __tm, __format, > + __mod); > ++__fmt; > } > else if (__ctype.is(ctype_base::space, *__fmt)) > @@ -1379,6 +1559,8 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > break; > } > } > + if (__use_state) > + __state._M_finalize_state(__tm); > return __s; > } > > @@ -1408,7 +1590,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > __fmt[3] = char_type(); > } > > - __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, > __fmt); > + __time_get_state __state = __time_get_state(); > + __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, > __fmt, > + __state); > + __state._M_finalize_state(__tm); > if (__beg == __end) > __err |= ios_base::eofbit; > return __beg; > --- libstdc++-v3/config/abi/pre/gnu.ver.jj 2021-12-10 > 22:17:54.532592071 +0100 > +++ libstdc++-v3/config/abi/pre/gnu.ver 2021-12-16 11:58:48.821827111 +0100 > @@ -628,7 +628,7 @@ GLIBCXX_3.4 { > _ZNSt8time_get*; > > _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE1*; > > _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE8*; > - > _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*; > + > _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*PK[cw]; > > # std::time_get_byname > _ZNSt15time_get_bynameI[cw]*EEEC[12]EPKc[jmy]; > @@ -1887,7 +1887,9 @@ GLIBCXX_3.4.21 { > _ZNKSt7__cxx119money_putI*; > _ZNKSt7__cxx1110moneypunctI*; > _ZNKSt7__cxx118numpunctI*; > - _ZNKSt7__cxx118time_getI*; > + > _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[13-9]*; > + > _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*PK[cw]; > + > _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE24*; > > _ZSt9has_facetINSt7__cxx117collate*; > _ZSt9has_facetINSt7__cxx118messages*; > @@ -2424,6 +2426,12 @@ GLIBCXX_3.4.30 { > # std::__timepunct::_M_am_pm_format(const char**) > _ZNKSt11__timepunctI[cw]E15_M_am_pm_formatEPPK[cw]; > > + # std::time_get > + > _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*__time_get_state; > + > _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*__time_get_state; > + > + _ZNSt16__time_get_state17_M_finalize_stateEP2tm; > + > } GLIBCXX_3.4.29; > > # Symbols in the support library (libsupc++) have their own tag. > --- libstdc++-v3/src/c++98/locale_facets.cc.jj 2021-01-05 > 00:13:58.345296630 +0100 > +++ libstdc++-v3/src/c++98/locale_facets.cc 2021-12-17 > 00:25:04.942290607 +0100 > @@ -134,5 +134,115 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > __grouping_tmp.size()); > } > > + namespace > + { > + bool > + is_leap(int year) > + { > + return (year % 100 != 0 || year % 400 == 0) && year % 4 == 0; > + } > + > + const unsigned short int mon_yday[2][13] = > + { > + // Normal years. > + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, > + // Leap years. > + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } > + }; > + > + int > + day_of_the_week (int year, int mon, int mday) > + { > + // We know that January 1st 1970 was a Thursday (= 4). Compute the > + // difference between this date and the one in arguments and so > + // determine the weekday. > + int corr_year = 1900 + year - (mon < 2); > + int wday = (-473 > + + (365 * (year - 70)) > + + (corr_year / 4) > + - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0) > + + (((corr_year / 4) / 25) / 4) > + + mon_yday[0][mon] > + + mday - 1); > + return ((wday % 7) + 7) % 7; > + } > + > + // Compute the day of the year. > + int > + day_of_the_year (tm *tm) > + { > + return (mon_yday[is_leap (1900 + tm->tm_year)][tm->tm_mon] > + + (tm->tm_mday - 1)); > + } > + } > + > + // Finalize time_get state. > + void > + __time_get_state:: > + _M_finalize_state(tm* tm) > + { > + if (_M_have_I && _M_is_pm) > + tm->tm_hour += 12; > + if (_M_have_century) > + { > + if (_M_want_century) > + tm->tm_year = tm->tm_year % 100; > + else > + tm->tm_year = 0; > + tm->tm_year += (_M_century - 19) * 100; > + } > + if (_M_want_xday && !_M_have_wday) > + { > + if (!(_M_have_mon && _M_have_mday) && _M_have_yday) > + { > + // We don't have tm_mon and/or tm_mday, compute them. > + int t_mon = 0; > + while (mon_yday[is_leap(1900 + tm->tm_year)][t_mon] > + <= tm->tm_yday) > + ++t_mon; > + if (!_M_have_mon) > + tm->tm_mon = t_mon - 1; > + if (!_M_have_mday) > + tm->tm_mday > + = (tm->tm_yday > + - mon_yday[is_leap(1900 + tm->tm_year)][t_mon - 1] + 1); > + _M_have_mon = 1; > + _M_have_mday = 1; > + } > + // Don't crash in day_of_the_week if tm_mon is uninitialized. > + if (_M_have_mon || (unsigned) tm->tm_mon <= 11) > + tm->tm_wday > + = day_of_the_week (tm->tm_year, tm->tm_mon, tm->tm_mday); > + } > + if (_M_want_xday > + && !_M_have_yday > + && (_M_have_mon || (unsigned) tm->tm_mon <= 11)) > + tm->tm_yday = day_of_the_year (tm); > + if ((_M_have_uweek || _M_have_wweek) && _M_have_wday) > + { > + int w_offset = _M_have_uweek ? 0 : 1; > + int wday = day_of_the_week (tm->tm_year, 0, 1); > + > + if (!_M_have_yday) > + tm->tm_yday = ((7 - (wday - w_offset)) % 7 > + + (_M_week_no - 1) * 7 > + + (tm->tm_wday - w_offset + 7) % 7); > + > + if (!_M_have_mday || !_M_have_mon) > + { > + int t_mon = 0; > + while (mon_yday[is_leap(1900 + tm->tm_year)][t_mon] > + <= tm->tm_yday) > + ++t_mon; > + if (!_M_have_mon) > + tm->tm_mon = t_mon - 1; > + if (!_M_have_mday) > + tm->tm_mday > + = (tm->tm_yday > + - mon_yday[is_leap(1900 + tm->tm_year)][t_mon - 1] + 1); > + } > + } > + } > + > _GLIBCXX_END_NAMESPACE_VERSION > } // namespace > --- libstdc++-v3/testsuite/22_locale/time_get/get/char/4.cc.jj 2021-12-16 > 13:31:29.000704911 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get/char/4.cc 2021-12-16 > 15:17:09.180601201 +0100 > @@ -0,0 +1,243 @@ > +// { dg-do run { target c++11 } } > + > +// Copyright (C) 2021 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// . > + > +#include > +#include > +#include > +#include > + > +void > +test01() > +{ > + using namespace std; > + > + locale loc_c = locale::classic(); > + > + istringstream iss; > + iss.imbue(loc_c); > + const time_get& tget = use_facet>(iss.getloc()); > + typedef istreambuf_iterator iter; > + const iter end; > + > + tm time; > + ios_base::iostate err = ios_base::badbit; > + > + iss.str("PM01:38:12"); > + string format = "%p%I:%M:%S"; > + time = tm(); > + auto ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_hour == 13 ); > + VERIFY( time.tm_min == 38 ); > + VERIFY( time.tm_sec == 12 ); > + > + iss.str("05 37"); > + format = "%C %y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 537 - 1900 ); > + > + iss.str("68"); > + format = "%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2068 - 1900 ); > + > + iss.str("69"); > + format = "%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 1969 - 1900 ); > + > + iss.str("03-Feb-2003"); > + format = "%d-%b-%Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2003 - 1900 ); > + VERIFY( time.tm_mon == 1 ); > + VERIFY( time.tm_mday == 3 ); > + VERIFY( time.tm_wday == 1 ); > + VERIFY( time.tm_yday == 33 ); > + > + iss.str("16-Dec-2020"); > + format = "%d-%b-%Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 11 ); > + VERIFY( time.tm_mday == 16 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 350 ); > + > + iss.str("16-Dec-2021"); > + format = "%d-%b-%Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2021 - 1900 ); > + VERIFY( time.tm_mon == 11 ); > + VERIFY( time.tm_mday == 16 ); > + VERIFY( time.tm_wday == 4 ); > + VERIFY( time.tm_yday == 349 ); > + > + iss.str("253 2020"); > + format = "%j %Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 8 ); > + VERIFY( time.tm_mday == 9 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 252 ); > + > + iss.str("233 2021"); > + format = "%j %Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2021 - 1900 ); > + VERIFY( time.tm_mon == 7 ); > + VERIFY( time.tm_mday == 21 ); > + VERIFY( time.tm_wday == 6 ); > + VERIFY( time.tm_yday == 232 ); > + > + iss.str("2020 23 3"); > + format = "%Y %U %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 10 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 161 ); > + > + iss.str("2020 23 3"); > + format = "%Y %W %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 10 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 161 ); > + > + iss.str("2021 43 Fri"); > + format = "%Y %W %a"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2021 - 1900 ); > + VERIFY( time.tm_mon == 9 ); > + VERIFY( time.tm_mday == 29 ); > + VERIFY( time.tm_wday == 5 ); > + VERIFY( time.tm_yday == 301 ); > + > + iss.str("2024 23 3"); > + format = "%Y %U %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2024 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 12 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 163 ); > + > + iss.str("2024 23 3"); > + format = "%Y %W %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2024 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 5 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 156 ); > + > + // As an extension, parse also 4 digit years. > + iss.str("0068"); > + format = "%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 68 - 1900 ); > + > + iss.str("0069"); > + format = "%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 69 - 1900 ); > + > + iss.str("1492"); > + format = "%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 1492 - 1900 ); > +} > + > +int > +main() > +{ > + test01(); > + return 0; > +} > --- libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/4.cc.jj > 2021-12-16 13:43:01.435849616 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/4.cc 2021-12-16 > 15:18:06.672780110 +0100 > @@ -0,0 +1,243 @@ > +// { dg-do run { target c++11 } } > + > +// Copyright (C) 2021 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// . > + > +#include > +#include > +#include > +#include > + > +void > +test01() > +{ > + using namespace std; > + > + locale loc_c = locale::classic(); > + > + wistringstream iss; > + iss.imbue(loc_c); > + const time_get& tget = > use_facet>(iss.getloc()); > + typedef istreambuf_iterator iter; > + const iter end; > + > + tm time; > + ios_base::iostate err = ios_base::badbit; > + > + iss.str(L"PM01:38:12"); > + wstring format = L"%p%I:%M:%S"; > + time = tm(); > + auto ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_hour == 13 ); > + VERIFY( time.tm_min == 38 ); > + VERIFY( time.tm_sec == 12 ); > + > + iss.str(L"05 37"); > + format = L"%C %y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 537 - 1900 ); > + > + iss.str(L"68"); > + format = L"%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2068 - 1900 ); > + > + iss.str(L"69"); > + format = L"%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 1969 - 1900 ); > + > + iss.str(L"03-Feb-2003"); > + format = L"%d-%b-%Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2003 - 1900 ); > + VERIFY( time.tm_mon == 1 ); > + VERIFY( time.tm_mday == 3 ); > + VERIFY( time.tm_wday == 1 ); > + VERIFY( time.tm_yday == 33 ); > + > + iss.str(L"16-Dec-2020"); > + format = L"%d-%b-%Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 11 ); > + VERIFY( time.tm_mday == 16 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 350 ); > + > + iss.str(L"16-Dec-2021"); > + format = L"%d-%b-%Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2021 - 1900 ); > + VERIFY( time.tm_mon == 11 ); > + VERIFY( time.tm_mday == 16 ); > + VERIFY( time.tm_wday == 4 ); > + VERIFY( time.tm_yday == 349 ); > + > + iss.str(L"253 2020"); > + format = L"%j %Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 8 ); > + VERIFY( time.tm_mday == 9 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 252 ); > + > + iss.str(L"233 2021"); > + format = L"%j %Y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2021 - 1900 ); > + VERIFY( time.tm_mon == 7 ); > + VERIFY( time.tm_mday == 21 ); > + VERIFY( time.tm_wday == 6 ); > + VERIFY( time.tm_yday == 232 ); > + > + iss.str(L"2020 23 3"); > + format = L"%Y %U %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 10 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 161 ); > + > + iss.str(L"2020 23 3"); > + format = L"%Y %W %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2020 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 10 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 161 ); > + > + iss.str(L"2021 43 Fri"); > + format = L"%Y %W %a"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2021 - 1900 ); > + VERIFY( time.tm_mon == 9 ); > + VERIFY( time.tm_mday == 29 ); > + VERIFY( time.tm_wday == 5 ); > + VERIFY( time.tm_yday == 301 ); > + > + iss.str(L"2024 23 3"); > + format = L"%Y %U %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2024 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 12 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 163 ); > + > + iss.str(L"2024 23 3"); > + format = L"%Y %W %w"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 2024 - 1900 ); > + VERIFY( time.tm_mon == 5 ); > + VERIFY( time.tm_mday == 5 ); > + VERIFY( time.tm_wday == 3 ); > + VERIFY( time.tm_yday == 156 ); > + > + // As an extension, parse also 4 digit years. > + iss.str(L"0068"); > + format = L"%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 68 - 1900 ); > + > + iss.str(L"0069"); > + format = L"%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 69 - 1900 ); > + > + iss.str(L"1492"); > + format = L"%y"; > + time = tm(); > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_year == 1492 - 1900 ); > +} > + > +int > +main() > +{ > + test01(); > + return 0; > +} > --- libstdc++-v3/testsuite/22_locale/time_get/get_year/char/1.cc.jj > 2021-01-05 00:13:58.000000000 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get_year/char/1.cc > 2021-12-16 12:17:55.828490362 +0100 > @@ -76,8 +76,8 @@ void test01() > errorstate = good; > iterator_type ret03 = tim_get.get_year(is_it03, end, iss, errorstate, > &time03); > - VERIFY( time03.tm_year == 3 ); > - VERIFY( errorstate == ios_base::failbit ); > + VERIFY( time03.tm_year == 197 - 1900 ); > + VERIFY( errorstate == good ); > VERIFY( *ret03 == 'd' ); > > iss.str("71d71"); > --- libstdc++-v3/testsuite/22_locale/time_get/get_year/char/5.cc.jj > 2021-01-05 00:13:58.000000000 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get_year/char/5.cc > 2021-12-16 13:50:47.481218269 +0100 > @@ -49,12 +49,13 @@ void test01() > > const string str0 = "1"; > tg.get_year(str0.begin(), str0.end(), iss, err, &tm0); > - VERIFY( err == (failbit | eofbit) ); > - VERIFY( tm0.tm_year == 0 ); > + VERIFY( err == eofbit ); > + VERIFY( tm0.tm_year == 2001 - 1900 ); > > const string str1 = "1997 "; > + err = goodbit; > iter_type end1 = tg.get_year(str1.begin(), str1.end(), iss, err, &tm1); > - VERIFY( err == (failbit | eofbit) ); > + VERIFY( err == goodbit ); > VERIFY( tm1.tm_year == time_sanity.tm_year ); > VERIFY( *end1 == ' ' ); > } > --- libstdc++-v3/testsuite/22_locale/time_get/get_year/char/6.cc.jj > 2021-12-16 13:23:34.596457450 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get_year/char/6.cc > 2021-12-16 13:49:35.055248817 +0100 > @@ -0,0 +1,79 @@ > +// Copyright (C) 2001-2021 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// . > + > +// 22.2.5.1.1 time_get members > + > +#include > +#include > +#include > + > +void test01() > +{ > + using namespace std; > + > + typedef istreambuf_iterator iterator_type; > + > + locale loc_c = locale::classic(); > + > + iterator_type end; > + > + istringstream iss; > + iss.imbue(loc_c); > + const time_get& tim_get = use_facet > >(iss.getloc()); > + ios_base::iostate errorstate = ios_base::goodbit; > + > + iss.str("69"); > + iterator_type is_it01(iss); > + tm time01; > + tim_get.get_year(is_it01, end, iss, errorstate, &time01); > + VERIFY( time01.tm_year == 1969 - 1900 ); > + VERIFY( errorstate == ios_base::eofbit ); > + > + iss.str("68 "); > + iterator_type is_it02(iss); > + tm time02; > + errorstate = ios_base::goodbit; > + iterator_type ret02 = tim_get.get_year(is_it02, end, iss, errorstate, > + &time02); > + VERIFY( time02.tm_year == 2068 - 1900 ); > + VERIFY( errorstate == ios_base::goodbit ); > + VERIFY( *ret02 == ' ' ); > + > + iss.str("0069"); > + iterator_type is_it03(iss); > + tm time03; > + errorstate = ios_base::goodbit; > + iterator_type ret03 = tim_get.get_year(is_it03, end, iss, errorstate, > + &time03); > + VERIFY( time03.tm_year == 69 - 1900 ); > + VERIFY( errorstate == ios_base::eofbit ); > + > + iss.str("0068"); > + iterator_type is_it04(iss); > + tm time04; > + errorstate = ios_base::goodbit; > + iterator_type ret04 = tim_get.get_year(is_it04, end, iss, errorstate, > + &time04); > + VERIFY( time04.tm_year == 68 - 1900 ); > + VERIFY( errorstate == ios_base::eofbit ); > +} > + > +int main() > +{ > + test01(); > + return 0; > +} > --- libstdc++-v3/testsuite/22_locale/time_get/get_year/wchar_t/1.cc.jj > 2021-01-05 00:13:58.000000000 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get_year/wchar_t/1.cc > 2021-12-16 12:19:44.565943238 +0100 > @@ -76,8 +76,8 @@ void test01() > errorstate = good; > iterator_type ret03 = tim_get.get_year(is_it03, end, iss, errorstate, > &time03); > - VERIFY( time03.tm_year == 3 ); > - VERIFY( errorstate == ios_base::failbit ); > + VERIFY( time03.tm_year == 197 - 1900 ); > + VERIFY( errorstate == good ); > VERIFY( *ret03 == L'd' ); > > iss.str(L"71d71"); > --- libstdc++-v3/testsuite/22_locale/time_get/get_year/wchar_t/5.cc.jj > 2021-12-16 12:28:45.505246696 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get_year/wchar_t/5.cc > 2021-12-16 13:50:29.931467983 +0100 > @@ -49,12 +49,13 @@ void test01() > > const wstring str0 = L"1"; > tg.get_year(str0.begin(), str0.end(), iss, err, &tm0); > - VERIFY( err == (failbit | eofbit) ); > - VERIFY( tm0.tm_year == 0 ); > + VERIFY( err == eofbit ); > + VERIFY( tm0.tm_year == 2001 - 1900 ); > > const wstring str1 = L"1997 "; > + err = goodbit; > iter_type end1 = tg.get_year(str1.begin(), str1.end(), iss, err, &tm1); > - VERIFY( err == (failbit | eofbit) ); > + VERIFY( err == goodbit ); > VERIFY( tm1.tm_year == time_sanity.tm_year ); > VERIFY( *end1 == L' ' ); > } > --- libstdc++-v3/testsuite/22_locale/time_get/get_year/wchar_t/6.cc.jj > 2021-12-16 13:29:10.402677678 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get_year/wchar_t/6.cc > 2021-12-16 13:49:54.812967682 +0100 > @@ -0,0 +1,79 @@ > +// Copyright (C) 2001-2021 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// . > + > +// 22.2.5.1.1 time_get members > + > +#include > +#include > +#include > + > +void test01() > +{ > + using namespace std; > + > + typedef istreambuf_iterator iterator_type; > + > + locale loc_c = locale::classic(); > + > + iterator_type end; > + > + wistringstream iss; > + iss.imbue(loc_c); > + const time_get& tim_get = use_facet > >(iss.getloc()); > + ios_base::iostate errorstate = ios_base::goodbit; > + > + iss.str(L"69"); > + iterator_type is_it01(iss); > + tm time01; > + tim_get.get_year(is_it01, end, iss, errorstate, &time01); > + VERIFY( time01.tm_year == 1969 - 1900 ); > + VERIFY( errorstate == ios_base::eofbit ); > + > + iss.str(L"68 "); > + iterator_type is_it02(iss); > + tm time02; > + errorstate = ios_base::goodbit; > + iterator_type ret02 = tim_get.get_year(is_it02, end, iss, errorstate, > + &time02); > + VERIFY( time02.tm_year == 2068 - 1900 ); > + VERIFY( errorstate == ios_base::goodbit ); > + VERIFY( *ret02 == L' ' ); > + > + iss.str(L"0069"); > + iterator_type is_it03(iss); > + tm time03; > + errorstate = ios_base::goodbit; > + iterator_type ret03 = tim_get.get_year(is_it03, end, iss, errorstate, > + &time03); > + VERIFY( time03.tm_year == 69 - 1900 ); > + VERIFY( errorstate == ios_base::eofbit ); > + > + iss.str(L"0068"); > + iterator_type is_it04(iss); > + tm time04; > + errorstate = ios_base::goodbit; > + iterator_type ret04 = tim_get.get_year(is_it04, end, iss, errorstate, > + &time04); > + VERIFY( time04.tm_year == 68 - 1900 ); > + VERIFY( errorstate == ios_base::eofbit ); > +} > + > +int main() > +{ > + test01(); > + return 0; > +} > > > Jakub > >