diff options
9 files changed, 860 insertions, 84 deletions
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 51c23d8003a..3456ee1dd6a 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -684,7 +684,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 time_get<_CharT, _InIter>::do_date_order() const { return time_base::no_order; } - // Expand a strftime format string and parse it. E.g., do_get_date() may + // Expand a strptime format string and parse it. E.g., do_get_date() may // pass %m/%d/%Y => extracted characters. template<typename _CharT, typename _InIter> _InIter @@ -714,41 +714,27 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 const char* __cs; _CharT __wcs[10]; case 'a': - // Abbreviated weekday name [tm_wday] - const char_type* __days1[7]; - __tp._M_days_abbreviated(__days1); - __beg = _M_extract_name(__beg, __end, __mem, __days1, - 7, __io, __tmperr); - if (!__tmperr) - __tm->tm_wday = __mem; - break; case 'A': - // Weekday name [tm_wday]. - const char_type* __days2[7]; - __tp._M_days(__days2); - __beg = _M_extract_name(__beg, __end, __mem, __days2, - 7, __io, __tmperr); + // Weekday name (possibly abbreviated) [tm_wday] + const char_type* __days[14]; + __tp._M_days(&__days[0]); + __tp._M_days_abbreviated(&__days[7]); + __beg = _M_extract_name(__beg, __end, __mem, __days, + 14, __io, __tmperr); if (!__tmperr) - __tm->tm_wday = __mem; + __tm->tm_wday = __mem % 7; break; case 'h': case 'b': - // Abbreviated month name [tm_mon] - const char_type* __months1[12]; - __tp._M_months_abbreviated(__months1); - __beg = _M_extract_name(__beg, __end, __mem, - __months1, 12, __io, __tmperr); - if (!__tmperr) - __tm->tm_mon = __mem; - break; case 'B': - // Month name [tm_mon]. - const char_type* __months2[12]; - __tp._M_months(__months2); + // Month name (possibly abbreviated) [tm_mon] + const char_type* __months[24]; + __tp._M_months(&__months[0]); + __tp._M_months_abbreviated(&__months[12]); __beg = _M_extract_name(__beg, __end, __mem, - __months2, 12, __io, __tmperr); + __months, 24, __io, __tmperr); if (!__tmperr) - __tm->tm_mon = __mem; + __tm->tm_mon = __mem % 12; break; case 'c': // Default time and date representation. @@ -758,21 +744,12 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 __tm, __dt[0]); break; case 'd': - // Day [01, 31]. [tm_mday] - __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, - __io, __tmperr); - if (!__tmperr) - __tm->tm_mday = __mem; - break; case 'e': - // Day [1, 31], with single digits preceded by - // space. [tm_mday] + // Day [1, 31]. [tm_mday] if (__ctype.is(ctype_base::space, *__beg)) - __beg = _M_extract_num(++__beg, __end, __mem, 1, 9, - 1, __io, __tmperr); - else - __beg = _M_extract_num(__beg, __end, __mem, 10, 31, - 2, __io, __tmperr); + ++__beg; + __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, + __io, __tmperr); if (!__tmperr) __tm->tm_mday = __mem; break; @@ -795,7 +772,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, __io, __tmperr); if (!__tmperr) - __tm->tm_hour = __mem; + __tm->tm_hour = __mem % 12; break; case 'm': // Month [01, 12]. [tm_mon] @@ -812,10 +789,22 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 __tm->tm_min = __mem; break; case 'n': - if (__ctype.narrow(*__beg, 0) == '\n') + case 't': + while (__beg != __end + && __ctype.is(ctype_base::space, *__beg)) ++__beg; - else - __tmperr |= ios_base::failbit; + break; + case 'p': + // Locale's a.m. or p.m. + const char_type* __ampm[2]; + __tp._M_am_pm(&__ampm[0]); + if (!__ampm[0][0] || !__ampm[1][0]) + 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; break; case 'R': // Equivalent to (%H:%M). @@ -836,12 +825,6 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 if (!__tmperr) __tm->tm_sec = __mem; break; - case 't': - if (__ctype.narrow(*__beg, 0) == '\t') - ++__beg; - else - __tmperr |= ios_base::failbit; - break; case 'T': // Equivalent to (%H:%M:%S). __cs = "%H:%M:%S"; @@ -899,11 +882,24 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 else __tmperr |= ios_base::failbit; break; + case '%': + if (*__beg == __ctype.widen('%')) + ++__beg; + else + __tmperr |= ios_base::failbit; + break; default: // Not recognized. __tmperr |= ios_base::failbit; } } + else if (__ctype.is(ctype_base::space, __format[__i])) + { + // Skip any whitespace. + while (__beg != __end + && __ctype.is(ctype_base::space, *__beg)) + ++__beg; + } else { // Verify format and input match, extract and discard. @@ -930,10 +926,6 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 const locale& __loc = __io._M_getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - // As-is works for __len = 1, 2, 4, the values actually used. - int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); - - ++__min; size_t __i = 0; int __value = 0; for (; __beg != __end && __i < __len; ++__beg, (void)++__i) @@ -942,19 +934,20 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 if (__c >= '0' && __c <= '9') { __value = __value * 10 + (__c - '0'); - const int __valuec = __value * __mult; - if (__valuec > __max || __valuec + __mult < __min) + if (__value > __max) break; - __mult /= 10; } else break; } - if (__i == __len) - __member = __value; // Special encoding for do_get_year, 'y', and 'Y' above. - else if (__len == 4 && __i == 2) + 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) + __member = __value; else __err |= ios_base::failbit; @@ -962,7 +955,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 } // Assumptions: - // All elements in __names are unique. + // All elements in __names are unique, except if __indexlen is + // even __names in the first half could be the same as corresponding + // __names in the second half (May is abbreviated as May). Some __names + // elements could be prefixes of other __names elements. template<typename _CharT, typename _InIter> _InIter time_get<_CharT, _InIter>:: @@ -974,12 +970,15 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 const locale& __loc = __io._M_getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) - * __indexlen)); + size_t* __matches + = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t) + * __indexlen)); + size_t* __lengths = __matches + __indexlen; size_t __nmatches = 0; size_t __pos = 0; bool __testvalid = true; const char_type* __name; + bool __begupdated = false; // Look for initial matches. // NB: Some of the locale data is in the form of all lowercase @@ -991,26 +990,88 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) if (__c == __names[__i1][0] || __c == __ctype.toupper(__names[__i1][0])) - __matches[__nmatches++] = __i1; + { + __lengths[__nmatches] + = __traits_type::length(__names[__i1]); + __matches[__nmatches++] = __i1; + } } while (__nmatches > 1) { // Find smallest matching string. - size_t __minlen = __traits_type::length(__names[__matches[0]]); + size_t __minlen = __lengths[0]; for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) - __minlen = std::min(__minlen, - __traits_type::length(__names[__matches[__i2]])); - ++__beg; + __minlen = std::min(__minlen, __lengths[__i2]); ++__pos; + ++__beg; + if (__pos == __minlen) + { + // If some match has remaining length of 0, + // need to decide if any match with remaining + // length non-zero matches the next character. + // If so, remove all matches with remaining length + // 0 from consideration, otherwise keep only matches + // with remaining length 0. + bool __match_longer = false; + + if (__beg != __end) + for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) + { + __name = __names[__matches[__i3]]; + if (__lengths[__i3] > __pos && (__name[__pos] == *__beg)) + { + __match_longer = true; + break; + } + } + for (size_t __i4 = 0; __i4 < __nmatches;) + if (__match_longer == (__lengths[__i4] == __pos)) + { + __matches[__i4] = __matches[--__nmatches]; + __lengths[__i4] = __lengths[__nmatches]; + } + else + ++__i4; + if (__match_longer) + { + __minlen = __lengths[0]; + for (size_t __i5 = 1; __i5 < __nmatches; ++__i5) + __minlen = std::min(__minlen, __lengths[__i5]); + } + else + { + // Deal with May being full as well as abbreviated month + // name. Pick the smaller index. + if (__nmatches == 2 && (__indexlen & 1) == 0) + { + if (__matches[0] < __indexlen / 2) + { + if (__matches[1] == __matches[0] + __indexlen / 2) + __nmatches = 1; + } + else if (__matches[1] == __matches[0] - __indexlen / 2) + { + __matches[0] = __matches[1]; + __lengths[0] = __lengths[1]; + __nmatches = 1; + } + } + __begupdated = true; + break; + } + } if (__pos < __minlen && __beg != __end) - for (size_t __i3 = 0; __i3 < __nmatches;) + for (size_t __i6 = 0; __i6 < __nmatches;) { - __name = __names[__matches[__i3]]; + __name = __names[__matches[__i6]]; if (!(__name[__pos] == *__beg)) - __matches[__i3] = __matches[--__nmatches]; + { + __matches[__i6] = __matches[--__nmatches]; + __lengths[__i6] = __lengths[__nmatches]; + } else - ++__i3; + ++__i6; } else break; @@ -1019,10 +1080,13 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 if (__nmatches == 1) { // Make sure found name is completely extracted. - ++__beg; - ++__pos; + if (!__begupdated) + { + ++__beg; + ++__pos; + } __name = __names[__matches[0]]; - const size_t __len = __traits_type::length(__name); + const size_t __len = __lengths[0]; while (__pos < __len && __beg != __end && __name[__pos] == *__beg) ++__beg, (void)++__pos; diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get/char/3.cc b/libstdc++-v3/testsuite/22_locale/time_get/get/char/3.cc new file mode 100644 index 00000000000..524c1c5a97f --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/time_get/get/char/3.cc @@ -0,0 +1,356 @@ +// { 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 +// <http://www.gnu.org/licenses/>. + +#include <locale> +#include <sstream> +#include <iterator> +#include <testsuite_hooks.h> + +void +test01() +{ + using namespace std; + + locale loc_c = locale::classic(); + + istringstream iss; + iss.imbue(loc_c); + const time_get<char>& tget = use_facet<time_get<char>>(iss.getloc()); + typedef istreambuf_iterator<char> iter; + const iter end; + + tm time; + ios_base::iostate err = ios_base::badbit; + + // PR78714 tests + iss.str("Mon"); + string format = "%a"; + 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_wday == 1 ); + + iss.str("Tue "); + format = "%a"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == ' ' ); + VERIFY( time.tm_wday == 2 ); + + iss.str("Wednesday"); + format = "%a"; + 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_wday == 3 ); + + iss.str("Thu"); + format = "%A"; + 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_wday == 4 ); + + iss.str("Fri "); + format = "%A"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == ' ' ); + VERIFY( time.tm_wday == 5 ); + + iss.str("Saturday"); + format = "%A"; + 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_wday == 6 ); + + iss.str("Feb"); + format = "%b"; + 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_mon == 1 ); + + iss.str("Mar "); + format = "%b"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == ' ' ); + VERIFY( time.tm_mon == 2 ); + + iss.str("April"); + format = "%b"; + 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_mon == 3 ); + + iss.str("May"); + format = "%B"; + 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_mon == 4 ); + + iss.str("Jun "); + format = "%B"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == ' ' ); + VERIFY( time.tm_mon == 5 ); + + iss.str("July"); + format = "%B"; + 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_mon == 6 ); + + iss.str("Aug"); + format = "%h"; + 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_mon == 7 ); + + iss.str("May "); + format = "%h"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == ' ' ); + VERIFY( time.tm_mon == 4 ); + + iss.str("October"); + format = "%h"; + 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_mon == 9 ); + + // Other tests. + iss.str(" 1."); + format = "%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 1 ); + + iss.str("2."); + format = "%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 2 ); + + iss.str("03."); + format = "%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 3 ); + + iss.str("0."); + format = "%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == '.' ); + + iss.str("32."); + format = "%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == '2' ); + + iss.str(" 4."); + format = "%e."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 4 ); + + iss.str("5."); + format = "%e."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 5 ); + + iss.str("06."); + format = "%e."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 6 ); + + iss.str("0"); + format = "%e"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit|ios_base::eofbit ); + VERIFY( ret == end ); + + iss.str("35"); + format = "%e"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == '5' ); + + iss.str(" \t\t 02"); + format = "%t%m"; + 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_mon == 1 ); + + iss.str(" \t \t 03"); + format = "%n%m"; + 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_mon == 2 ); + + iss.str(" \t \t 4"); + format = " %m"; + 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_mon == 3 ); + + iss.str(" \t \t 5"); + format = "\t%m"; + 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_mon == 4 ); + + iss.str("12:00AM"); + format = "%I:%M%p"; + 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 == 0 ); + VERIFY( time.tm_min == 0 ); + + iss.str("12:37AM"); + format = "%I:%M%p"; + 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 == 0 ); + VERIFY( time.tm_min == 37 ); + + iss.str("01:25AM"); + format = "%I:%M%p"; + 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 == 1 ); + VERIFY( time.tm_min == 25 ); + + iss.str("12:00PM"); + format = "%I:%M%p"; + 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 == 12 ); + VERIFY( time.tm_min == 0 ); + + iss.str("12:42PM"); + format = "%I:%M%p"; + 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 == 12 ); + VERIFY( time.tm_min == 42 ); + + iss.str("07:23PM"); + format = "%I:%M%p"; + 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 == 19 ); + VERIFY( time.tm_min == 23 ); + + iss.str("17%20"); + format = "%H%%%M"; + 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 == 17 ); + VERIFY( time.tm_min == 20 ); + + iss.str("24:30"); + format = "%H:%M"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == '4' ); + + // This one behaves differently from strptime, in a single + // pass scaning we can't go back. + iss.str("Novembur"); + format = "%bembur"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == 'u' ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/3.cc b/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/3.cc new file mode 100644 index 00000000000..cbc31445677 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/3.cc @@ -0,0 +1,356 @@ +// { 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 +// <http://www.gnu.org/licenses/>. + +#include <locale> +#include <sstream> +#include <iterator> +#include <testsuite_hooks.h> + +void +test01() +{ + using namespace std; + + locale loc_c = locale::classic(); + + wistringstream iss; + iss.imbue(loc_c); + const time_get<wchar_t>& tget = use_facet<time_get<wchar_t>>(iss.getloc()); + typedef istreambuf_iterator<wchar_t> iter; + const iter end; + + tm time; + ios_base::iostate err = ios_base::badbit; + + // PR78714 tests + iss.str(L"Mon"); + wstring format = L"%a"; + 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_wday == 1 ); + + iss.str(L"Tue L"); + format = L"%a"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == L' ' ); + VERIFY( time.tm_wday == 2 ); + + iss.str(L"Wednesday"); + format = L"%a"; + 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_wday == 3 ); + + iss.str(L"Thu"); + format = L"%A"; + 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_wday == 4 ); + + iss.str(L"Fri L"); + format = L"%A"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == L' ' ); + VERIFY( time.tm_wday == 5 ); + + iss.str(L"Saturday"); + format = L"%A"; + 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_wday == 6 ); + + iss.str(L"Feb"); + format = L"%b"; + 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_mon == 1 ); + + iss.str(L"Mar L"); + format = L"%b"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == L' ' ); + VERIFY( time.tm_mon == 2 ); + + iss.str(L"April"); + format = L"%b"; + 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_mon == 3 ); + + iss.str(L"May"); + format = L"%B"; + 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_mon == 4 ); + + iss.str(L"Jun L"); + format = L"%B"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == L' ' ); + VERIFY( time.tm_mon == 5 ); + + iss.str(L"July"); + format = L"%B"; + 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_mon == 6 ); + + iss.str(L"Aug"); + format = L"%h"; + 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_mon == 7 ); + + iss.str(L"May L"); + format = L"%h"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret != end && *ret == L' ' ); + VERIFY( time.tm_mon == 4 ); + + iss.str(L"October"); + format = L"%h"; + 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_mon == 9 ); + + // Other tests. + iss.str(L" 1."); + format = L"%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 1 ); + + iss.str(L"2."); + format = L"%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 2 ); + + iss.str(L"03."); + format = L"%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 3 ); + + iss.str(L"0."); + format = L"%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == L'.' ); + + iss.str(L"32."); + format = L"%d."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == L'2' ); + + iss.str(L" 4."); + format = L"%e."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 4 ); + + iss.str(L"5."); + format = L"%e."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 5 ); + + iss.str(L"06."); + format = L"%e."; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::goodbit ); + VERIFY( ret == end ); + VERIFY( time.tm_mday == 6 ); + + iss.str(L"0"); + format = L"%e"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit|ios_base::eofbit ); + VERIFY( ret == end ); + + iss.str(L"35"); + format = L"%e"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == L'5' ); + + iss.str(L" \t\t 02"); + format = L"%t%m"; + 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_mon == 1 ); + + iss.str(L" \t \t 03"); + format = L"%n%m"; + 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_mon == 2 ); + + iss.str(L" \t \t 4"); + format = L" %m"; + 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_mon == 3 ); + + iss.str(L" \t \t 5"); + format = L"\t%m"; + 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_mon == 4 ); + + iss.str(L"12:00AM"); + format = L"%I:%M%p"; + 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 == 0 ); + VERIFY( time.tm_min == 0 ); + + iss.str(L"12:37AM"); + format = L"%I:%M%p"; + 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 == 0 ); + VERIFY( time.tm_min == 37 ); + + iss.str(L"01:25AM"); + format = L"%I:%M%p"; + 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 == 1 ); + VERIFY( time.tm_min == 25 ); + + iss.str(L"12:00PM"); + format = L"%I:%M%p"; + 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 == 12 ); + VERIFY( time.tm_min == 0 ); + + iss.str(L"12:42PM"); + format = L"%I:%M%p"; + 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 == 12 ); + VERIFY( time.tm_min == 42 ); + + iss.str(L"07:23PM"); + format = L"%I:%M%p"; + 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 == 19 ); + VERIFY( time.tm_min == 23 ); + + iss.str(L"17%20"); + format = L"%H%%%M"; + 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 == 17 ); + VERIFY( time.tm_min == 20 ); + + iss.str(L"24:30"); + format = L"%H:%M"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == L'4' ); + + // This one behaves differently from strptime, in a single + // pass scaning we can't go back. + iss.str(L"Novembur"); + format = L"%bembur"; + ret = tget.get(iter(iss), end, iss, err, &time, + format.data(), format.data()+format.size()); + VERIFY( err == ios_base::failbit ); + VERIFY( ret != end && *ret == L'u' ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/12791.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/12791.cc index 07b655c0fdc..958a8f196bb 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/12791.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/12791.cc @@ -39,14 +39,14 @@ void test01() const ios_base::iostate good = ios_base::goodbit; ios_base::iostate errorstate = good; - iss.str("60/04/71"); + iss.str("62/04/71"); iterator_type is_it01(iss); tm time01; errorstate = good; iterator_type ret01 = tim_get.get_date(is_it01, end, iss, errorstate, &time01); VERIFY( errorstate == ios_base::failbit ); - VERIFY( *ret01 == '6' ); + VERIFY( *ret01 == '2' ); iss.str("04/38/71"); iterator_type is_it02(iss); diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/12791.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/12791.cc index a33d695825d..0cf8f67ccd2 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/12791.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/12791.cc @@ -40,14 +40,14 @@ void test01() const ios_base::iostate good = ios_base::goodbit; ios_base::iostate errorstate = good; - iss.str(L"60/04/71"); + iss.str(L"62/04/71"); iterator_type is_it01(iss); tm time01; errorstate = good; iterator_type ret01 = tim_get.get_date(is_it01, end, iss, errorstate, &time01); VERIFY( errorstate == ios_base::failbit ); - VERIFY( *ret01 == L'6' ); + VERIFY( *ret01 == L'2' ); iss.str(L"04/38/71"); iterator_type is_it02(iss); diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/2.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/2.cc index 79f921d1cf6..a847748dc27 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/2.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/2.cc @@ -48,7 +48,7 @@ void test02() // inspection of named locales, en_HK iss.imbue(loc_hk); - iss.str("12:00:00 PST"); + iss.str("12:00:00 PM PST"); // Hong Kong in California! Well, they have Paris in Vegas... this // is all a little disney-esque anyway. Besides, you can get decent // Dim Sum in San Francisco. diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/5.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/5.cc index c7777962b46..a9bb79ce453 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/5.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_time/char/5.cc @@ -52,7 +52,7 @@ void test01() VERIFY( err == (failbit | eofbit) ); VERIFY( tm0.tm_sec == 0 ); VERIFY( tm0.tm_min == 0 ); - VERIFY( tm0.tm_hour == 0 ); + VERIFY( tm0.tm_hour == 1 ); const string str1 = "12:00:00 "; iter_type end1 = tg.get_time(str1.begin(), str1.end(), iss, err, &tm1); diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/2.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/2.cc index 6c3f5c2215d..b5d61e1afdb 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/2.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/2.cc @@ -48,7 +48,7 @@ void test02() // inspection of named locales, en_HK iss.imbue(loc_hk); - iss.str(L"12:00:00 PST"); + iss.str(L"12:00:00 PM PST"); // Hong Kong in California! Well, they have Paris in Vegas... this // is all a little disney-esque anyway. Besides, you can get decent // Dim Sum in San Francisco. diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/5.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/5.cc index 8fda7fb28ef..db25046d33d 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/5.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_time/wchar_t/5.cc @@ -52,7 +52,7 @@ void test01() VERIFY( err == (failbit | eofbit) ); VERIFY( tm0.tm_sec == 0 ); VERIFY( tm0.tm_min == 0 ); - VERIFY( tm0.tm_hour == 0 ); + VERIFY( tm0.tm_hour == 1 ); const wstring str1 = L"12:00:00 "; iter_type end1 = tg.get_time(str1.begin(), str1.end(), iss, err, &tm1); |