This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/3] libstdc++: Add time_get::get support.


On 20/12/14 13:07 +0000, Jonathan Wakely wrote:
On 15/04/14 23:19 +0200, Rüdiger Sonderfeld wrote:
This patch adds support for std::time_get::get and std::time_get::do_get
[locale.time.get].  Currently do_get is not virtual because this caused
segfault errors for me.

Hi Rüdiger, I'm trying to apply this patch and the tests don't work.

There also seem to be some problems in the new functions.

* libstdc++-v3/include/bits/locale_facets_nonio.h (time_get::get):
(time_get::do_get):  New method (C++11).
* libstdc++-v3/include/bits/locale_facets_nonio.tcc (time_get::get):
(time_get::do_get):  New method (C++11).
* libstdc++-v3/testsuite/22_locale/time_get/get/char/1.cc: New file.
* libstdc++-v3/testsuite/22_locale/time_get/get/char/2.cc: New file.
---
libstdc++-v3/include/bits/locale_facets_nonio.h    |  73 ++++++++++++
libstdc++-v3/include/bits/locale_facets_nonio.tcc  | 102 ++++++++++++++++
.../testsuite/22_locale/time_get/get/char/1.cc     | 129 ++++++++++++++++++++
.../testsuite/22_locale/time_get/get/char/2.cc     | 103 ++++++++++++++++
.../testsuite/22_locale/time_get/get/wchar_t/1.cc  | 130 +++++++++++++++++++++
.../testsuite/22_locale/time_get/get/wchar_t/2.cc  | 104 +++++++++++++++++
6 files changed, 641 insertions(+)
create mode 100644 libstdc++-v3/testsuite/22_locale/time_get/get/char/1.cc
create mode 100644 libstdc++-v3/testsuite/22_locale/time_get/get/char/2.cc
create mode 100644 libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/1.cc
create mode 100644 libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/2.cc

diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index 41d944d..93466b6 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -1137,6 +1137,108 @@ _GLIBCXX_END_NAMESPACE_LDBL
     return __beg;
   }

+#if __cplusplus >= 201103L
+  template<typename _CharT, typename _InIter>
+    inline
+    _InIter
+    time_get<_CharT, _InIter>::
+    get(iter_type __s, iter_type __end, ios_base& __io,
+        ios_base::iostate& __err, tm* __tm, const char_type *__fmt,
+        const char_type *__fmtend) const
+    {
+      const locale& __loc = __io._M_getloc();
+      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
+      __err = ios_base::goodbit;
+      while (__fmt != __fmtend &&
+             __err == ios_base::goodbit)
+        {
+          if (__s == __end)
+            {
+              __err = ios_base::eofbit | ios_base::failbit;
+              break;
+            }
+          else if (__ctype.narrow(*__fmt, 0) == '%')
+            {
+              char __format;
+              char __mod = 0;
+              if (++__fmt == __fmtend)
+                {
+                  __err = ios_base::failbit;
+                  break;
+                }
+              const char __c = __ctype.narrow(*__fmt, 0);
+              if (__c != 'E' && __c != 'O')
+                __format = __c;
+              else if (++__fmt != __fmtend)
+                {
+                  __mod = __c;
+                  __format = __ctype.narrow(*__fmt, 0);
+                }
+              else
+                {
+                  __err = ios_base::failbit;
+                  break;
+                }
+              __s = this->do_get(__s, __end, __io, __err, __tm, __format, __mod);
+              ++__fmt;
+            }
+          else if (__ctype.is(ctype_base::space, *__fmt))
+            {
+              ++__fmt;
+              while (__fmt != __fmtend &&
+                     __ctype.is(ctype_base::space, *__fmt))
+                ++__fmt;
+
+              while (__s != __end &&
+                     __ctype.is(ctype_base::space, *__s))
+                ++__s;
+            }
+          // TODO real case-insensitive comparison
+          else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
+                   __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
+            {
+              ++__s;
+              ++__fmt;
+            }
+          else
+            {
+              __err = ios_base::failbit;
+              break;
+            }
+        }
+      return __s;
+    }
+
+  template<typename _CharT, typename _InIter>
+    inline
+    _InIter
+    time_get<_CharT, _InIter>::
+    do_get(iter_type __beg, iter_type __end, ios_base& __io,
+           ios_base::iostate& __err, tm* __tm,
+           char __format, char __mod) const
+    {
+      const locale& __loc = __io._M_getloc();
+      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);

Shouldn't this set err = goodbit before doing anything?

"Effects: The function starts by evaluating err = ios_base::goodbit."

+      char_type __fmt[4];
+      __fmt[0] = __ctype.widen('%');
+      if (!__mod)
+        {
+          __fmt[1] = __format;
+          __fmt[2] = char_type();
+        }
+      else
+        {
+          __fmt[1] = __mod;
+          __fmt[2] = __format;
+          __fmt[3] = char_type();
+        }
+
+      return _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt);

It also doesn't seem to meet this requirement:

"When s == end evaluates to true after reading a character the
function evaluates err |= ios_base::eofbit.

+    }
+
+#endif // __cplusplus >= 201103L
+
 template<typename _CharT, typename _OutIter>
   _OutIter
   time_put<_CharT, _OutIter>::
diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get/char/1.cc b/libstdc++-v3/testsuite/22_locale/time_get/get/char/1.cc
new file mode 100644
index 0000000..1ad7822
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/time_get/get/char/1.cc
@@ -0,0 +1,129 @@
+// { dg-options " -std=gnu++11 " }
+
+// 2014-04-14 Rüdiger Sonderfeld  <ruediger@c-plusplus.de>
+
+// Copyright (C) 2014 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/>.
+
+// 22.4.5.1.1 (C++11) time_get members [locale.time.get.members]
+
+#include <locale>
+#include <sstream>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+#ifndef _GLIBCXX_ASSERT
+#  include <iostream>
+#  define PRINT(x) cout << #x << ": " << x << endl
+#  define TESTHEAD(x) cout << x << endl
+#else
+#  define PRINT(x) do {} while(false)
+#  define TESTHEAD(x) do {} while(false)
+#endif
+
+void test01()
+{
+  using namespace std;
+  bool test __attribute__((unused)) = true;
+
+  locale loc_c = locale::classic();
+
+  istringstream iss;
+  iss.imbue(loc_c);
+  const time_get<char>& tget = use_facet<time_get<char>>(iss.getloc());
+  const istreambuf_iterator<char> end;
+
+  tm time;
+  ios_base::iostate err;
+
+  // check regular operations with format string
+  TESTHEAD("regular operations");
+  iss.str("d 2014-04-14 01:09:35");
+  string format = "d %Y-%m-%d %H:%M:%S";
+  auto ret = tget.get(istreambuf_iterator<char>(iss), end, iss, err, &time,
+                      format.data(), format.data()+format.size());
+  PRINT(err);
+  VERIFY(err == ios_base::goodbit);

libc++ sets eofbit here.

+  VERIFY(ret == end);
+  PRINT(time.tm_year);
+  VERIFY(time.tm_year == 114);
+  PRINT(time.tm_mon);
+  VERIFY(time.tm_mon == 3);
+  PRINT(time.tm_mday);
+  VERIFY(time.tm_mday == 14);
+  PRINT(time.tm_hour);
+  VERIFY(time.tm_hour == 1);
+  PRINT(time.tm_min);
+  VERIFY(time.tm_min == 9);
+  PRINT(time.tm_sec);
+  VERIFY(time.tm_sec == 35);
+
+  TESTHEAD("check eof");
+  iss.str("2020");
+  ret = tget.get(istreambuf_iterator<char>(iss), end, iss, err, &time,
+                 format.data(), format.data()+format.size());
+  VERIFY(err == ios_base::eofbit | ios_base::failbit);

And this is always true, because == has higher precedence than |

+  VERIFY(ret == end);

How can this test pass?

Is there a format = "%Y" missing?

You cannot parse "2020" using the format "d %Y-%m-%d %H:%M:%S" so it
should not reach EOF and should not set ret = end.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]