[PATCH 1/3] libstdc++: Add time_get::get support.
Jonathan Wakely
jwakely@redhat.com
Sat Dec 20 13:07:00 GMT 2014
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);
>+ 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.
>+
>+ TESTHEAD("check broken format");
>+ iss.str("2014-04-14 01:09:35");
>+ format = "%";
>+ ret = tget.get(istreambuf_iterator<char>(iss), end, iss, err, &time,
>+ format.data(), format.data()+format.size());
>+ VERIFY(err == ios_base::failbit);
>+
>+ TESTHEAD("check single format letter version");
>+ iss.str("2020");
>+ ret = tget.get(istreambuf_iterator<char>(iss), end, iss, err, &time, 'Y');
>+ VERIFY(err == ios_base::goodbit);
>+ VERIFY(time.tm_year == 120);
>+ VERIFY(ret == end);
Shouldn't this set err == eofbit too?
The 1.cc tests seem like they can never pass.
More information about the Libstdc++
mailing list