On Tue, 14 Dec 2021 at 13:50, Jakub Jelinek via Libstdc++ <
libstd...@gcc.gnu.org> wrote:

> Hi!
>
> This patch uses the same not completely correct case insensitive
> comparisons
> as used elsewhere in the same header.  Proper comparisons that would handle
> even multi-byte characters would be harder, but I don't see them
> implemented
> in __ctype's methods.
>
> Tested on x86_64-linux, ok for trunk?
>

OK, thanks.



>
> 2021-12-14  Jakub Jelinek  <ja...@redhat.com>
>
>         PR libstdc++/71557
>         * include/bits/locale_facets_nonio.tcc (_M_extract_via_format):
>         Compare characters other than format specifiers and whitespace
>         case insensitively.
>         (_M_extract_name): Compare characters case insensitively.
>         * testsuite/22_locale/time_get/get/char/71557.cc: New test.
>         * testsuite/22_locale/time_get/get/wchar_t/71557.cc: New test.
>
> --- libstdc++-v3/include/bits/locale_facets_nonio.tcc.jj        2021-12-10
> 17:04:35.224563127 +0100
> +++ libstdc++-v3/include/bits/locale_facets_nonio.tcc   2021-12-14
> 13:10:40.845984740 +0100
> @@ -910,7 +910,9 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
>           else
>             {
>               // Verify format and input match, extract and discard.
> -             if (__format[__i] == *__beg)
> +             // TODO real case-insensitive comparison
> +             if (__ctype.tolower(__format[__i]) == __ctype.tolower(*__beg)
> +                 || __ctype.toupper(__format[__i]) ==
> __ctype.toupper(*__beg))
>                 ++__beg;
>               else
>                 __tmperr |= ios_base::failbit;
> @@ -988,15 +990,15 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
>        bool __begupdated = false;
>
>        // Look for initial matches.
> -      // NB: Some of the locale data is in the form of all lowercase
> -      // names, and some is in the form of initially-capitalized
> -      // names. Look for both.
>        if (__beg != __end)
>         {
>           const char_type __c = *__beg;
> +         // TODO real case-insensitive comparison
> +         const char_type __cl = __ctype.tolower(__c);
> +         const char_type __cu = __ctype.toupper(__c);
>           for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
> -           if (__c == __names[__i1][0]
> -               || __c == __ctype.toupper(__names[__i1][0]))
> +           if (__cl == __ctype.tolower(__names[__i1][0])
> +               || __cu == __ctype.toupper(__names[__i1][0]))
>               {
>                 __lengths[__nmatches]
>                   = __traits_type::length(__names[__i1]);
> @@ -1023,15 +1025,22 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
>               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;
> -                     }
> -                 }
> +               {
> +                 // TODO real case-insensitive comparison
> +                 const char_type __cl = __ctype.tolower(*__beg);
> +                 const char_type __cu = __ctype.toupper(*__beg);
> +                 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
> +                   {
> +                     __name = __names[__matches[__i3]];
> +                     if (__lengths[__i3] > __pos
> +                         && (__ctype.tolower(__name[__pos]) == __cl
> +                             || __ctype.toupper(__name[__pos]) == __cu))
> +                       {
> +                         __match_longer = true;
> +                         break;
> +                       }
> +                   }
> +               }
>               for (size_t __i4 = 0; __i4 < __nmatches;)
>                 if (__match_longer == (__lengths[__i4] == __pos))
>                   {
> @@ -1069,17 +1078,23 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
>                 }
>             }
>           if (__pos < __minlen && __beg != __end)
> -           for (size_t __i6 = 0; __i6 < __nmatches;)
> -             {
> -               __name = __names[__matches[__i6]];
> -               if (!(__name[__pos] == *__beg))
> -                 {
> -                   __matches[__i6] = __matches[--__nmatches];
> -                   __lengths[__i6] = __lengths[__nmatches];
> -                 }
> -               else
> -                 ++__i6;
> -             }
> +           {
> +             // TODO real case-insensitive comparison
> +             const char_type __cl = __ctype.tolower(*__beg);
> +             const char_type __cu = __ctype.toupper(*__beg);
> +             for (size_t __i6 = 0; __i6 < __nmatches;)
> +               {
> +                 __name = __names[__matches[__i6]];
> +                 if (__ctype.tolower(__name[__pos]) != __cl
> +                     && __ctype.toupper(__name[__pos]) != __cu)
> +                   {
> +                     __matches[__i6] = __matches[--__nmatches];
> +                     __lengths[__i6] = __lengths[__nmatches];
> +                   }
> +                 else
> +                   ++__i6;
> +               }
> +           }
>           else
>             break;
>         }
> @@ -1094,7 +1109,12 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
>             }
>           __name = __names[__matches[0]];
>           const size_t __len = __lengths[0];
> -         while (__pos < __len && __beg != __end && __name[__pos] ==
> *__beg)
> +         while (__pos < __len
> +                && __beg != __end
> +                // TODO real case-insensitive comparison
> +                && (__ctype.tolower(__name[__pos]) ==
> __ctype.tolower(*__beg)
> +                    || (__ctype.toupper(__name[__pos])
> +                        == __ctype.toupper(*__beg))))
>             ++__beg, (void)++__pos;
>
>           if (__len == __pos)
> --- libstdc++-v3/testsuite/22_locale/time_get/get/char/71557.cc.jj
> 2021-12-14 13:16:25.956027379 +0100
> +++ libstdc++-v3/testsuite/22_locale/time_get/get/char/71557.cc 2021-12-14
> 13:20:30.628512769 +0100
> @@ -0,0 +1,96 @@
> +// { 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;
> +
> +  iss.str("20:48:01 MAR 31 2016");
> +  string format = "%H:%M:%S %b %d %Y";
> +  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_year == 2016 - 1900 );
> +  VERIFY( time.tm_mon == 2 );
> +  VERIFY( time.tm_mday == 31 );
> +  VERIFY( time.tm_hour == 20 );
> +  VERIFY( time.tm_min == 48 );
> +  VERIFY( time.tm_sec == 01 );
> +
> +  iss.str("21:38:11 apr 30 2017");
> +  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 == 2017 - 1900 );
> +  VERIFY( time.tm_mon == 3 );
> +  VERIFY( time.tm_mday == 30 );
> +  VERIFY( time.tm_hour == 21 );
> +  VERIFY( time.tm_min == 38 );
> +  VERIFY( time.tm_sec == 11 );
> +
> +  iss.str("22:28:21 mAy 29 2018");
> +  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 == 2018 - 1900 );
> +  VERIFY( time.tm_mon == 4 );
> +  VERIFY( time.tm_mday == 29 );
> +  VERIFY( time.tm_hour == 22 );
> +  VERIFY( time.tm_min == 28 );
> +  VERIFY( time.tm_sec == 21 );
> +
> +  iss.str("23:18:31 JuN 28 2019");
> +  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 == 2019 - 1900 );
> +  VERIFY( time.tm_mon == 5 );
> +  VERIFY( time.tm_mday == 28 );
> +  VERIFY( time.tm_hour == 23 );
> +  VERIFY( time.tm_min == 18 );
> +  VERIFY( time.tm_sec == 31 );
> +}
> +
> +int
> +main()
> +{
> +  test01();
> +  return 0;
> +}
> --- libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/71557.cc.jj
>  2021-12-14 13:20:51.981206044 +0100
> +++ libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/71557.cc
> 2021-12-14 13:21:45.263440673 +0100
> @@ -0,0 +1,96 @@
> +// { 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;
> +
> +  iss.str(L"20:48:01 MAR 31 2016");
> +  wstring format = L"%H:%M:%S %b %d %Y";
> +  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_year == 2016 - 1900 );
> +  VERIFY( time.tm_mon == 2 );
> +  VERIFY( time.tm_mday == 31 );
> +  VERIFY( time.tm_hour == 20 );
> +  VERIFY( time.tm_min == 48 );
> +  VERIFY( time.tm_sec == 01 );
> +
> +  iss.str(L"21:38:11 apr 30 2017");
> +  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 == 2017 - 1900 );
> +  VERIFY( time.tm_mon == 3 );
> +  VERIFY( time.tm_mday == 30 );
> +  VERIFY( time.tm_hour == 21 );
> +  VERIFY( time.tm_min == 38 );
> +  VERIFY( time.tm_sec == 11 );
> +
> +  iss.str(L"22:28:21 mAy 29 2018");
> +  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 == 2018 - 1900 );
> +  VERIFY( time.tm_mon == 4 );
> +  VERIFY( time.tm_mday == 29 );
> +  VERIFY( time.tm_hour == 22 );
> +  VERIFY( time.tm_min == 28 );
> +  VERIFY( time.tm_sec == 21 );
> +
> +  iss.str(L"23:18:31 JuN 28 2019");
> +  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 == 2019 - 1900 );
> +  VERIFY( time.tm_mon == 5 );
> +  VERIFY( time.tm_mday == 28 );
> +  VERIFY( time.tm_hour == 23 );
> +  VERIFY( time.tm_min == 18 );
> +  VERIFY( time.tm_sec == 31 );
> +}
> +
> +int
> +main()
> +{
> +  test01();
> +  return 0;
> +}
>
>         Jakub
>
>

Reply via email to