From patchwork Fri Dec 17 07:16:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 49041 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 999A23858003 for ; Fri, 17 Dec 2021 07:20:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 999A23858003 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1639725615; bh=NN8fcMoS99rtDC10KcxpRSqNXQ1iN5dQFO0k9f8bzss=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=MqkHrc3QOQazZO90af1DvnYMwNfhtPHRFaM05TzCAMNqOzEFwadVq5qLy+Ia+pdoC IlptPvh5n+rx91ng2OP8LsWAlGB6FJtEjE69YTXoCN3Tbw/6xxFNEYh6fn422RHH/b B+f4M1KiZCVooyEt8JGDPJu7chJuLRpLGEkJOLvU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org 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 4EDB53858003 for ; Fri, 17 Dec 2021 07:16:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4EDB53858003 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-364-52R-HWuZPTi1hjYi47ZiIg-1; Fri, 17 Dec 2021 02:16:46 -0500 X-MC-Unique: 52R-HWuZPTi1hjYi47ZiIg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0292A10151E0; Fri, 17 Dec 2021 07:16:46 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.2.16.169]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4C0BC7A413; Fri, 17 Dec 2021 07:16:44 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 1BH7Gg3s001497 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 17 Dec 2021 08:16:43 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 1BH7GgXY001496; Fri, 17 Dec 2021 08:16:42 +0100 Date: Fri, 17 Dec 2021 08:16:42 +0100 To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++, v2: Add %j, %U, %w, %W time_get support, fix %y, %Y, %C, %p [PR77760] Message-ID: <20211217071642.GD2646553@tucnak> References: <20211216144647.GU2646553@tucnak> MIME-Version: 1.0 In-Reply-To: <20211216144647.GU2646553@tucnak> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org 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-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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. 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. Jakub --- 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; +}