re PR libstdc++/26701 (std::time_get parses only 2 digits of year, in en_GB locale.)

2010-01-06  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/26701
	* include/bits/locale_facets_nonio.tcc (time_get<>::_M_extract_num):
	Encode short two digits over four parsings to negative numbers.
	(time_get<>::_M_extract_via_format): Adjust, accept both two digits
	and four digits for both 'y' and 'Y'.
	(time_get<>::do_get_year): Call time_get<>::_M_extract_num.
	* doc/xml/manual/prerequisites.xml: Add en_GB.
	* testsuite/lib/libstdc++.exp: Adjust
	* testsuite/22_locale/time_get/get_date/char/26701.cc: New.
	* testsuite/22_locale/time_get/get_date/wchar_t/26701.cc: Likewise.

From-SVN: r155685
This commit is contained in:
Paolo Carlini 2010-01-07 00:22:51 +00:00 committed by Paolo Carlini
parent 83c3322912
commit 2e8e6a99ee
6 changed files with 158 additions and 18 deletions

View File

@ -1,3 +1,16 @@
2010-01-06 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/26701
* include/bits/locale_facets_nonio.tcc (time_get<>::_M_extract_num):
Encode short two digits over four parsings to negative numbers.
(time_get<>::_M_extract_via_format): Adjust, accept both two digits
and four digits for both 'y' and 'Y'.
(time_get<>::do_get_year): Call time_get<>::_M_extract_num.
* doc/xml/manual/prerequisites.xml: Add en_GB.
* testsuite/lib/libstdc++.exp: Adjust
* testsuite/22_locale/time_get/get_date/char/26701.cc: New.
* testsuite/22_locale/time_get/get_date/wchar_t/26701.cc: Likewise.
2010-01-06 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/42491

View File

@ -73,6 +73,7 @@
<programlisting>
de_DE ISO-8859-1
de_DE@euro ISO-8859-15
en_GB ISO-8859-1
en_HK ISO-8859-1
en_PH ISO-8859-1
en_US ISO-8859-1

View File

@ -778,16 +778,16 @@ _GLIBCXX_END_LDBL_NAMESPACE
break;
case 'y':
case 'C': // C99
// Two digit year. [tm_year]
__beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
__io, __tmperr);
break;
// Two digit year.
case 'Y':
// Year [1900). [tm_year]
// 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.
__beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
__io, __tmperr);
if (!__tmperr)
__tm->tm_year = __mem - 1900;
__tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
break;
case 'Z':
// Timezone info.
@ -865,6 +865,9 @@ _GLIBCXX_END_LDBL_NAMESPACE
}
if (__i == __len)
__member = __value;
// Special encoding for do_get_year, 'y', and 'Y' above.
else if (__len == 4 && __i == 2)
__member = __value - 100;
else
__err |= ios_base::failbit;
@ -1116,19 +1119,13 @@ _GLIBCXX_END_LDBL_NAMESPACE
{
const locale& __loc = __io._M_getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
int __tmpyear;
ios_base::iostate __tmperr = ios_base::goodbit;
size_t __i = 0;
int __value = 0;
for (; __beg != __end && __i < 4; ++__beg, ++__i)
{
const char __c = __ctype.narrow(*__beg, '*');
if (__c >= '0' && __c <= '9')
__value = __value * 10 + (__c - '0');
else
break;
}
if (__i == 2 || __i == 4)
__tm->tm_year = __i == 2 ? __value : __value - 1900;
__beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
__io, __tmperr);
if (!__tmperr)
__tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
else
__err |= ios_base::failbit;

View File

@ -0,0 +1,64 @@
// { dg-require-namedlocale "" }
// 2010-01-06 Paolo Carlini <paolo.carlini@oracle.com>
// Copyright (C) 2010 Free Software Foundation
//
// 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/>.
// 22.2.5.1.1 time_get members
#include <locale>
#include <sstream>
#include <testsuite_hooks.h>
// libstdc++/26701
void test01()
{
using namespace std;
bool test __attribute__((unused)) = true;
typedef istreambuf_iterator<char> iterator_type;
locale loc_en = locale("en_GB");
tm tm0 = __gnu_test::test_tm(0, 0, 0, 0, 0, 0, 0, 0, 0);
iterator_type end;
istringstream iss;
iss.imbue(loc_en);
const time_get<char>& tg = use_facet<time_get<char> >(iss.getloc());
const ios_base::iostate good = ios_base::goodbit;
ios_base::iostate errorstate = good;
iss.str("01/02/2003");
iterator_type is_it0(iss);
errorstate = good;
tg.get_date(is_it0, end, iss, errorstate, &tm0);
VERIFY( errorstate == ios_base::eofbit );
VERIFY( tm0.tm_year + 1900 == 2003 );
VERIFY( tm0.tm_mon + 1 == 2 );
VERIFY( tm0.tm_mday == 1 );
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,64 @@
// { dg-require-namedlocale "" }
// 2010-01-06 Paolo Carlini <paolo.carlini@oracle.com>
// Copyright (C) 2010 Free Software Foundation
//
// 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/>.
// 22.2.5.1.1 time_get members
#include <locale>
#include <sstream>
#include <testsuite_hooks.h>
// libstdc++/26701
void test01()
{
using namespace std;
bool test __attribute__((unused)) = true;
typedef istreambuf_iterator<wchar_t> iterator_type;
locale loc_en = locale("en_GB");
tm tm0 = __gnu_test::test_tm(0, 0, 0, 0, 0, 0, 0, 0, 0);
iterator_type end;
wistringstream iss;
iss.imbue(loc_en);
const time_get<wchar_t>& tg = use_facet<time_get<wchar_t> >(iss.getloc());
const ios_base::iostate good = ios_base::goodbit;
ios_base::iostate errorstate = good;
iss.str(L"01/02/2003");
iterator_type is_it0(iss);
errorstate = good;
tg.get_date(is_it0, end, iss, errorstate, &tm0);
VERIFY( errorstate == ios_base::eofbit );
VERIFY( tm0.tm_year + 1900 == 2003 );
VERIFY( tm0.tm_mon + 1 == 2 );
VERIFY( tm0.tm_mday == 1 );
}
int main()
{
test01();
return 0;
}

View File

@ -869,6 +869,7 @@ proc check_v3_target_namedlocale { } {
puts $f " locale(\"de_DE\");"
puts $f " locale(\"de_DE.ISO-8859-15@euro\");"
puts $f " locale(\"de_DE@euro\");"
puts $f " locale(\"en_GB\");"
puts $f " locale(\"en_HK\");"
puts $f " locale(\"en_PH\");"
puts $f " locale(\"en_US\");"