[PATCH 1/3] libstdc++: Add time_get::get support.
Jonathan Wakely
jwakely@redhat.com
Sat Dec 20 13:43:00 GMT 2014
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.
More information about the Libstdc++
mailing list