re PR libstdc++/38081 (time_get<>::do_get_weekday does not always recognize full names of weekdays)

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

	PR libstdc++/38081
	* include/bits/locale_facets_nonio.h (time_get<>::
	_M_extract_wday_or_month): New, declare.
	* include/bits/locale_facets_nonio.tcc (time_get<>::
	_M_extract_wday_or_month): Define.
	(time_get<>::do_get_weekday, time_get<>::do_get_monthname): Use it.
	* config/abi/pre/gnu.ver: Export new symbols.
	* doc/xml/manual/prerequisites.xml: Add ru_RU.UTF-8 and
	ru_RU.ISO-8859-5.
	* testsuite/lib/libstdc++.exp: Adjust.
	* testsuite/22_locale/time_get/get_weekday/char/38081-1.cc: New.
	* testsuite/22_locale/time_get/get_weekday/char/38081-2.cc: Likewise.

From-SVN: r155659
This commit is contained in:
Paolo Carlini 2010-01-05 20:05:20 +00:00 committed by Paolo Carlini
parent 9bf4cdf575
commit ac2bb43770
8 changed files with 312 additions and 57 deletions

View File

@ -1,3 +1,18 @@
2010-01-05 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/38081
* include/bits/locale_facets_nonio.h (time_get<>::
_M_extract_wday_or_month): New, declare.
* include/bits/locale_facets_nonio.tcc (time_get<>::
_M_extract_wday_or_month): Define.
(time_get<>::do_get_weekday, time_get<>::do_get_monthname): Use it.
* config/abi/pre/gnu.ver: Export new symbols.
* doc/xml/manual/prerequisites.xml: Add ru_RU.UTF-8 and
ru_RU.ISO-8859-5.
* testsuite/lib/libstdc++.exp: Adjust.
* testsuite/22_locale/time_get/get_weekday/char/38081-1.cc: New.
* testsuite/22_locale/time_get/get_weekday/char/38081-2.cc: Likewise.
2010-01-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure: Regenerate.

View File

@ -1,6 +1,6 @@
## Linker script for GNU versioning (GNU ld 2.13.91+ only.)
##
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
## Free Software Foundation, Inc.
##
## This file is part of the GNU ISO C++ Library. This library is free
@ -149,7 +149,7 @@ GLIBCXX_3.4 {
std::th[a-h]*;
std::th[j-q]*;
std::th[s-z]*;
std::t[i-n]*;
# std::t[i-n]*;
std::tr1::h[^a]*;
std::t[s-z]*;
# std::[A-Zu-z]*;
@ -459,6 +459,21 @@ GLIBCXX_3.4 {
# std::money_put
_ZNKSt9money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE*;
# std::time_get
_ZNSt8time_get*;
_ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[0-9]*;
_ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE1[0-9]*;
# std::time_get_byname
_ZNSt15time_get_byname*;
# std::time_put
_ZNSt8time_put*;
_ZNKSt8time_put*;
# std::time_put_byname
_ZNSt15time_put_byname*;
# std::numeric_limits
_ZNSt14numeric_limitsI[^g]E*;
@ -1081,6 +1096,9 @@ GLIBCXX_3.4.14 {
_ZSt25__throw_bad_function_callv;
# std::time_get::_M_extract_wday_or_month
_ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE24_M_extract_wday_or_month*;
} GLIBCXX_3.4.13;
# Symbols in the support library (libsupc++) have their own tag.

View File

@ -86,6 +86,8 @@ fr_FR@euro ISO-8859-15
is_IS UTF-8
it_IT ISO-8859-1
ja_JP.eucjp EUC-JP
ru_RU.ISO-8859-5 ISO-8859-5
ru_RU.UTF-8 UTF-8
se_NO.UTF-8 UTF-8
ta_IN UTF-8
zh_TW BIG5

View File

@ -1,6 +1,6 @@
// Locale support -*- C++ -*-
// Copyright (C) 2007, 2009 Free Software Foundation, Inc.
// Copyright (C) 2007, 2008, 2009, 2010 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
@ -652,13 +652,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
int __min, int __max, size_t __len,
ios_base& __io, ios_base::iostate& __err) const;
// Extract day or month name, or any unique array of string
// literals in a const _CharT* array.
// Extract any unique array of string literals in a const _CharT* array.
iter_type
_M_extract_name(iter_type __beg, iter_type __end, int& __member,
const _CharT** __names, size_t __indexlen,
ios_base& __io, ios_base::iostate& __err) const;
// Extract day or month name in a const _CharT* array.
iter_type
_M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
const _CharT** __names, size_t __indexlen,
ios_base& __io, ios_base::iostate& __err) const;
// Extract on a component-by-component basis, via __format argument.
iter_type
_M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,

View File

@ -1,6 +1,6 @@
// Locale support -*- C++ -*-
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
// Copyright (C) 2007, 2008, 2009, 2010 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
@ -947,6 +947,77 @@ _GLIBCXX_END_LDBL_NAMESPACE
return __beg;
}
template<typename _CharT, typename _InIter>
_InIter
time_get<_CharT, _InIter>::
_M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
const _CharT** __names, size_t __indexlen,
ios_base& __io, ios_base::iostate& __err) const
{
typedef char_traits<_CharT> __traits_type;
const locale& __loc = __io._M_getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
* __indexlen));
size_t __nmatches = 0;
size_t* __matches_lengths = 0;
size_t __pos = 0;
if (__beg != __end)
{
const char_type __c = *__beg;
for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
if (__c == __names[__i][0]
|| __c == __ctype.toupper(__names[__i][0]))
__matches[__nmatches++] = __i;
}
if (__nmatches)
{
++__beg, ++__pos;
__matches_lengths
= static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
* __nmatches));
for (size_t __i = 0; __i < __nmatches; ++__i)
__matches_lengths[__i]
= __traits_type::length(__names[__matches[__i]]);
}
for (; __beg != __end; ++__beg, ++__pos)
{
size_t __nskipped = 0;
const char_type __c = *__beg;
for (size_t __i = 0; __i < __nmatches;)
{
const char_type* __name = __names[__matches[__i]];
if (__pos >= __matches_lengths[__i])
++__nskipped, ++__i;
else if (!(__name[__pos] == __c))
{
--__nmatches;
__matches[__i] = __matches[__nmatches];
__matches_lengths[__i] = __matches_lengths[__nmatches];
}
else
++__i;
}
if (__nskipped == __nmatches)
break;
}
if ((__nmatches == 1 && __matches_lengths[0] == __pos)
|| (__nmatches == 2 && (__matches_lengths[0] == __pos
|| __matches_lengths[1] == __pos)))
__member = (__matches[0] >= __indexlen
? __matches[0] - __indexlen : __matches[0]);
else
__err |= ios_base::failbit;
return __beg;
}
template<typename _CharT, typename _InIter>
_InIter
time_get<_CharT, _InIter>::
@ -991,35 +1062,14 @@ _GLIBCXX_END_LDBL_NAMESPACE
const locale& __loc = __io._M_getloc();
const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const char_type* __days[7];
const char_type* __days[14];
__tp._M_days_abbreviated(__days);
__tp._M_days(__days + 7);
int __tmpwday;
ios_base::iostate __tmperr = ios_base::goodbit;
__beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
__io, __tmperr);
// Check to see if non-abbreviated name exists, and extract.
// NB: Assumes both _M_days and _M_days_abbreviated organized in
// exact same order, first to last, such that the resulting
// __days array with the same index points to a day, and that
// day's abbreviated form.
// NB: Also assumes that an abbreviated name is a subset of the name.
if (!__tmperr && __beg != __end)
{
size_t __pos = __traits_type::length(__days[__tmpwday]);
__tp._M_days(__days);
const char_type* __name = __days[__tmpwday];
if (__name[__pos] == *__beg)
{
// Extract the rest of it.
const size_t __len = __traits_type::length(__name);
while (__pos < __len && __beg != __end
&& __name[__pos] == *__beg)
++__beg, ++__pos;
if (__len != __pos)
__tmperr |= ios_base::failbit;
}
}
__beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
__io, __tmperr);
if (!__tmperr)
__tm->tm_wday = __tmpwday;
else
@ -1040,35 +1090,14 @@ _GLIBCXX_END_LDBL_NAMESPACE
const locale& __loc = __io._M_getloc();
const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const char_type* __months[12];
const char_type* __months[24];
__tp._M_months_abbreviated(__months);
__tp._M_months(__months + 12);
int __tmpmon;
ios_base::iostate __tmperr = ios_base::goodbit;
__beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12,
__io, __tmperr);
// Check to see if non-abbreviated name exists, and extract.
// NB: Assumes both _M_months and _M_months_abbreviated organized in
// exact same order, first to last, such that the resulting
// __months array with the same index points to a month, and that
// month's abbreviated form.
// NB: Also assumes that an abbreviated name is a subset of the name.
if (!__tmperr && __beg != __end)
{
size_t __pos = __traits_type::length(__months[__tmpmon]);
__tp._M_months(__months);
const char_type* __name = __months[__tmpmon];
if (__name[__pos] == *__beg)
{
// Extract the rest of it.
const size_t __len = __traits_type::length(__name);
while (__pos < __len && __beg != __end
&& __name[__pos] == *__beg)
++__beg, ++__pos;
if (__len != __pos)
__tmperr |= ios_base::failbit;
}
}
__beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
__io, __tmperr);
if (!__tmperr)
__tm->tm_mon = __tmpmon;
else

View File

@ -0,0 +1,86 @@
// { dg-require-namedlocale "" }
// 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 <cstring>
#include <testsuite_hooks.h>
// libstdc++/38081
void test01()
{
using namespace std;
bool test __attribute__((unused)) = true;
typedef istreambuf_iterator<char> iterator_type;
// basic construction
locale loc("ru_RU.ISO-8859-5");
// create an ostream-derived object, cache the time_get facet
iterator_type end;
istringstream iss;
iss.imbue(loc);
const time_get<char>& tim_get = use_facet<time_get<char> >(iss.getloc());
const ios_base::iostate good = ios_base::goodbit;
ios_base::iostate errorstate = good;
// iter_type
// get_weekday(iter_type, iter_type, ios_base&,
// ios_base::iostate&, tm*) const
iss.str("\xbf\xdd\xd4");
iterator_type is_it01(iss);
tm time01;
memset(&time01, -1, sizeof(tm));
errorstate = good;
tim_get.get_weekday(is_it01, end, iss, errorstate, &time01);
VERIFY( time01.tm_wday == 1 );
VERIFY( errorstate == ios_base::eofbit );
iss.str("\xbf\xde\xdd\xd5\xd4\xd5\xdb\xec\xdd\xd8\xda");
iterator_type is_it02(iss);
tm time02;
memset(&time02, -1, sizeof(tm));
errorstate = good;
tim_get.get_weekday(is_it02, end, iss, errorstate, &time02);
VERIFY( time02.tm_wday == 1 );
VERIFY( errorstate == ios_base::eofbit );
iss.str("\xbf\xdd\xd4\xd5\xd4\xd5\xdb\xec\xdd\xd8\xda");
iterator_type is_it03(iss);
tm time03;
memset(&time03, -1, sizeof(tm));
errorstate = good;
iterator_type ret = tim_get.get_weekday(is_it03, end, iss,
errorstate, &time03);
VERIFY( time03.tm_wday == 1 );
VERIFY( errorstate == ios_base::goodbit );
VERIFY( *ret == '\xd5' );
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,98 @@
// 2010-01-05 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 <cstring>
#include <testsuite_hooks.h>
void test01()
{
using namespace std;
bool test __attribute__((unused)) = true;
typedef istreambuf_iterator<char> iterator_type;
// basic construction
locale loc("ru_RU.UTF8");
// create an ostream-derived object, cache the time_get facet
iterator_type end;
istringstream iss;
iss.imbue(loc);
const time_get<char>& tim_get = use_facet<time_get<char> >(iss.getloc());
const ios_base::iostate good = ios_base::goodbit;
ios_base::iostate errorstate = good;
// iter_type
// get_weekday(iter_type, iter_type, ios_base&,
// ios_base::iostate&, tm*) const
const char* awdays[7] = { "\u0412\u0441\u043A",
"\u041F\u043D\u0434",
"\u0412\u0442\u0440",
"\u0421\u0440\u0434",
"\u0427\u0442\u0432",
"\u041F\u0442\u043D",
"\u0421\u0431\u0442" };
for (unsigned i = 0; i < 7; ++i)
{
iss.str(awdays[i]);
iterator_type is_it01(iss);
tm time01;
memset(&time01, -1, sizeof(tm));
errorstate = good;
tim_get.get_weekday(is_it01, end, iss, errorstate, &time01);
VERIFY( time01.tm_wday == i );
VERIFY( errorstate == ios_base::eofbit );
}
const char* wdays[7] = { "\u0412\u043E\u0441\u043A\u0440\u0435"
"\u0441\u0435\u043D\u044C\u0435",
"\u041F\u043E\u043D\u0435\u0434\u0435"
"\u043B\u044C\u043D\u0438\u043A",
"\u0412\u0442\u043E\u0440\u043D\u0438\u043A",
"\u0421\u0440\u0435\u0434\u0430",
"\u0427\u0435\u0442\u0432\u0435\u0440\u0433",
"\u041F\u044F\u0442\u043D\u0438\u0446\u0430",
"\u0421\u0443\u0431\u0431\u043E\u0442\u0430" };
for (unsigned i = 0; i < 7; ++i)
{
iss.str(wdays[i]);
iterator_type is_it01(iss);
tm time01;
memset(&time01, -1, sizeof(tm));
errorstate = good;
tim_get.get_weekday(is_it01, end, iss, errorstate, &time01);
VERIFY( time01.tm_wday == i );
VERIFY( errorstate == ios_base::eofbit );
}
}
int main()
{
test01();
return 0;
}

View File

@ -1,6 +1,6 @@
# libstdc++ "tool init file" for DejaGNU
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
# Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
@ -883,6 +883,8 @@ proc check_v3_target_namedlocale { } {
puts $f " locale(\"is_IS.UTF-8\");"
puts $f " locale(\"it_IT\");"
puts $f " locale(\"ja_JP.eucjp\");"
puts $f " locale(\"ru_RU.ISO-8859-5\");"
puts $f " locale(\"ru_RU.UTF-8\");"
puts $f " locale(\"se_NO.UTF-8\");"
puts $f " locale(\"ta_IN\");"
puts $f " locale(\"zh_TW\");"