Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81044 - in trunk: boost/chrono/io libs/chrono/test/io
From: vicente.botet_at_[hidden]
Date: 2012-10-21 21:06:58


Author: viboes
Date: 2012-10-21 21:06:57 EDT (Sun, 21 Oct 2012)
New Revision: 81044
URL: http://svn.boost.org/trac/boost/changeset/81044

Log:
Chrono: Added internal time_get::get() + fixed some issues in test time_point_input
Text files modified:
   trunk/boost/chrono/io/time_point_io.hpp | 348 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/chrono/test/io/time_point_input.cpp | 7
   2 files changed, 347 insertions(+), 8 deletions(-)

Modified: trunk/boost/chrono/io/time_point_io.hpp
==============================================================================
--- trunk/boost/chrono/io/time_point_io.hpp (original)
+++ trunk/boost/chrono/io/time_point_io.hpp 2012-10-21 21:06:57 EDT (Sun, 21 Oct 2012)
@@ -3,9 +3,18 @@
 // Use, modification and distribution are subject to the Boost Software License,
 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt).
+
+//===-------------------------- locale ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
 //
+//===----------------------------------------------------------------------===//
+
 // This code was adapted by Vicente from Howard Hinnant's experimental work
-// on chrono i/o to Boost
+// on chrono i/o to Boost and some functions from libc++/locale to emulate the missing time_get::get()
 
 #ifndef BOOST_CHRONO_IO_TIME_POINT_IO_HPP
 #define BOOST_CHRONO_IO_TIME_POINT_IO_HPP
@@ -25,7 +34,9 @@
 #include <string.h>
 
 #define BOOST_CHRONO_INTERNAL_TIMEGM defined BOOST_WINDOWS && ! defined(__CYGWIN__)
-//#define BOOST_CHRONO_INTERNAL_TIMEGM
+//#define BOOST_CHRONO_INTERNAL_TIMEGM 1
+
+#define BOOST_CHRONO_USES_INTERNAL_TIME_GET
 
 namespace boost
 {
@@ -34,6 +45,309 @@
     namespace detail
     {
 
+ template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> >
+ struct time_get
+ {
+ std::time_get<CharT> const &that_;
+ time_get(std::time_get<CharT> const& that) : that_(that) {}
+
+ typedef std::time_get<CharT> facet;
+ typedef typename facet::iter_type iter_type;
+ typedef typename facet::char_type char_type;
+ typedef std::basic_string<char_type> string_type;
+
+ static int
+ get_up_to_n_digits(
+ InputIterator& b, InputIterator e,
+ std::ios_base::iostate& err,
+ const std::ctype<CharT>& ct,
+ int n)
+ {
+ // Precondition: n >= 1
+ if (b == e)
+ {
+ err |= std::ios_base::eofbit | std::ios_base::failbit;
+ return 0;
+ }
+ // get first digit
+ CharT c = *b;
+ if (!ct.is(std::ctype_base::digit, c))
+ {
+ err |= std::ios_base::failbit;
+ return 0;
+ }
+ int r = ct.narrow(c, 0) - '0';
+ for (++b, --n; b != e && n > 0; ++b, --n)
+ {
+ // get next digit
+ c = *b;
+ if (!ct.is(std::ctype_base::digit, c))
+ return r;
+ r = r * 10 + ct.narrow(c, 0) - '0';
+ }
+ if (b == e)
+ err |= std::ios_base::eofbit;
+ return r;
+ }
+
+
+ void get_day(
+ int& d,
+ iter_type& b, iter_type e,
+ std::ios_base::iostate& err,
+ const std::ctype<char_type>& ct) const
+ {
+ int t = get_up_to_n_digits(b, e, err, ct, 2);
+ if (!(err & std::ios_base::failbit) && 1 <= t && t <= 31)
+ d = t;
+ else
+ err |= std::ios_base::failbit;
+ }
+
+ void get_month(
+ int& m,
+ iter_type& b, iter_type e,
+ std::ios_base::iostate& err,
+ const std::ctype<char_type>& ct) const
+ {
+ int t = get_up_to_n_digits(b, e, err, ct, 2) - 1;
+ if (!(err & std::ios_base::failbit) && t <= 11)
+ m = t;
+ else
+ err |= std::ios_base::failbit;
+ }
+
+
+ void get_year4(int& y,
+ iter_type& b, iter_type e,
+ std::ios_base::iostate& err,
+ const std::ctype<char_type>& ct) const
+ {
+ int t = get_up_to_n_digits(b, e, err, ct, 4);
+ if (!(err & std::ios_base::failbit))
+ y = t - 1900;
+ }
+
+ void
+ get_hour(int& h,
+ iter_type& b, iter_type e,
+ std::ios_base::iostate& err,
+ const std::ctype<char_type>& ct) const
+ {
+ int t = get_up_to_n_digits(b, e, err, ct, 2);
+ if (!(err & std::ios_base::failbit) && t <= 23)
+ h = t;
+ else
+ err |= std::ios_base::failbit;
+ }
+
+ void
+ get_minute(int& m,
+ iter_type& b, iter_type e,
+ std::ios_base::iostate& err,
+ const std::ctype<char_type>& ct) const
+ {
+ int t = get_up_to_n_digits(b, e, err, ct, 2);
+ if (!(err & std::ios_base::failbit) && t <= 59)
+ m = t;
+ else
+ err |= std::ios_base::failbit;
+ }
+
+ void
+ get_second(int& s,
+ iter_type& b, iter_type e,
+ std::ios_base::iostate& err,
+ const std::ctype<char_type>& ct) const
+ {
+ int t = get_up_to_n_digits(b, e, err, ct, 2);
+ if (!(err & std::ios_base::failbit) && t <= 60)
+ s = t;
+ else
+ err |= std::ios_base::failbit;
+ }
+
+
+
+ InputIterator get(
+ iter_type b, iter_type e,
+ std::ios_base& iob,
+ std::ios_base::iostate& err,
+ std::tm* tm,
+ char fmt, char) const
+ {
+ err = std::ios_base::goodbit;
+ const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc());
+
+ switch (fmt)
+ {
+// case 'a':
+// case 'A':
+// that_.get_weekdayname(tm->tm_wday, b, e, err, ct);
+// break;
+// case 'b':
+// case 'B':
+// case 'h':
+// that_.get_monthname(tm->tm_mon, b, e, err, ct);
+// break;
+// case 'c':
+// {
+// const string_type& fm = this->c();
+// b = that_.get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size());
+// }
+// break;
+ case 'd':
+ case 'e':
+ get_day(tm->tm_mday, b, e, err, ct);
+ //std::cerr << "tm_mday= "<< tm->tm_mday << std::endl;
+
+ break;
+// case 'D':
+// {
+// const char_type fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
+// b = that_.get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
+// }
+// break;
+// case 'F':
+// {
+// const char_type fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
+// b = that_.get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
+// }
+// break;
+ case 'H':
+ get_hour(tm->tm_hour, b, e, err, ct);
+ //std::cerr << "tm_hour= "<< tm->tm_hour << std::endl;
+ break;
+// case 'I':
+// that_.get_12_hour(tm->tm_hour, b, e, err, ct);
+// break;
+// case 'j':
+// that_.get_day_year_num(tm->tm_yday, b, e, err, ct);
+// break;
+ case 'm':
+ get_month(tm->tm_mon, b, e, err, ct);
+ //std::cerr << "tm_mon= "<< tm->tm_mon << std::endl;
+ break;
+ case 'M':
+ get_minute(tm->tm_min, b, e, err, ct);
+ //std::cerr << "tm_min= "<< tm->tm_min << std::endl;
+ break;
+// case 'n':
+// case 't':
+// that_.get_white_space(b, e, err, ct);
+// break;
+// case 'p':
+// that_.get_am_pm(tm->tm_hour, b, e, err, ct);
+// break;
+// case 'r':
+// {
+// const char_type fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
+// b = that_.get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
+// }
+// break;
+// case 'R':
+// {
+// const char_type fm[] = {'%', 'H', ':', '%', 'M'};
+// b = that_.get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
+// }
+// break;
+// case 'S':
+// that_.get_second(tm->tm_sec, b, e, err, ct);
+// break;
+// case 'T':
+// {
+// const char_type fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
+// b = that_.get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
+// }
+// break;
+// case 'w':
+// that_.get_weekday(tm->tm_wday, b, e, err, ct);
+// break;
+// case 'x':
+// return that_.get_date(b, e, iob, err, tm);
+// case 'X':
+// {
+// const string_type& fm = this->X();
+// b = that_.get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size());
+// }
+// break;
+// case 'y':
+// that_.get_year(tm->tm_year, b, e, err, ct);
+ break;
+ case 'Y':
+ get_year4(tm->tm_year, b, e, err, ct);
+ //std::cerr << "tm_year= "<< tm->tm_year << std::endl;
+ break;
+// case '%':
+// that_.get_percent(b, e, err, ct);
+// break;
+ default:
+ err |= std::ios_base::failbit;
+ }
+ return b;
+ }
+
+
+ InputIterator get(
+ iter_type b, iter_type e,
+ std::ios_base& iob,
+ std::ios_base::iostate& err, std::tm* tm,
+ const char_type* fmtb, const char_type* fmte) const
+ {
+ const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc());
+ err = std::ios_base::goodbit;
+ while (fmtb != fmte && err == std::ios_base::goodbit)
+ {
+ if (b == e)
+ {
+ err = std::ios_base::failbit;
+ break;
+ }
+ if (ct.narrow(*fmtb, 0) == '%')
+ {
+ if (++fmtb == fmte)
+ {
+ err = std::ios_base::failbit;
+ break;
+ }
+ char cmd = ct.narrow(*fmtb, 0);
+ char opt = '\0';
+ if (cmd == 'E' || cmd == '0')
+ {
+ if (++fmtb == fmte)
+ {
+ err = std::ios_base::failbit;
+ break;
+ }
+ opt = cmd;
+ cmd = ct.narrow(*fmtb, 0);
+ }
+ b = get(b, e, iob, err, tm, cmd, opt);
+ ++fmtb;
+ }
+ else if (ct.is(std::ctype_base::space, *fmtb))
+ {
+ for (++fmtb; fmtb != fmte && ct.is(std::ctype_base::space, *fmtb); ++fmtb)
+ ;
+ for ( ; b != e && ct.is(std::ctype_base::space, *b); ++b)
+ ;
+ }
+ else if (ct.toupper(*b) == ct.toupper(*fmtb))
+ {
+ ++b;
+ ++fmtb;
+ }
+ else
+ err = std::ios_base::failbit;
+ }
+ if (b == e)
+ err |= std::ios_base::eofbit;
+ return b;
+ }
+
+ };
+
+
       template <class CharT>
       class time_manip: public manip<time_manip<CharT> >
       {
@@ -335,7 +649,7 @@
 
     namespace detail
     {
-#if defined BOOST_CHRONO_INTERNAL_TIMEGM
+#if BOOST_CHRONO_INTERNAL_TIMEGM
     int is_leap(int year)
     {
       if(year % 400 == 0)
@@ -572,12 +886,16 @@
             }
             min = min * 10 + cn - '0';
           }
- if (++b == e) err |= std::ios_base::eofbit;
+ if (++b == e) {
+ err |= std::ios_base::eofbit;
+ }
           min += hr * 60;
           min *= sn;
         }
         else
+ {
           err |= std::ios_base::eofbit | std::ios_base::failbit;
+ }
         return minutes(min);
       }
 
@@ -611,7 +929,12 @@
             { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' };
             pb = pattern;
             pe = pb + sizeof (pattern) / sizeof(CharT);
+#if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
+ const detail::time_get<CharT>& dtg(tg);
+ dtg.get(is, 0, is, err, &tm, pb, pe);
+#else
             tg.get(is, 0, is, err, &tm, pb, pe);
+#endif
             if (err & std::ios_base::failbit) goto exit;
             double sec;
             CharT c = CharT();
@@ -621,6 +944,7 @@
               err |= std::ios_base::failbit;
               goto exit;
             }
+ //std::cerr << "sec= "<< sec << std::endl;
             It i(is);
             It eof;
             c = *i;
@@ -630,9 +954,11 @@
               goto exit;
             }
             minutes min = detail::extract_z(i, eof, err, ct);
+ //std::cerr << "min= "<< min.count() << std::endl;
+
             if (err & std::ios_base::failbit) goto exit;
             time_t t;
-#if defined BOOST_CHRONO_INTERNAL_TIMEGM
+#if BOOST_CHRONO_INTERNAL_TIMEGM
             t = detail::internal_timegm(&tm);
 #else
             t = timegm(&tm);
@@ -646,7 +972,12 @@
             const CharT z[2] =
             { '%', 'z' };
             const CharT* fz = std::search(pb, pe, z, z + 2);
+#if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
+ const detail::time_get<CharT>& dtg(tg);
+ dtg.get(is, 0, is, err, &tm, pb, fz);
+#else
             tg.get(is, 0, is, err, &tm, pb, fz);
+#endif
             minutes minu(0);
             if (fz != pe)
             {
@@ -666,7 +997,12 @@
                   err |= std::ios_base::failbit;
                   goto exit;
                 }
+#if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
+ const detail::time_get<CharT>& dtg(tg);
+ dtg.get(is, 0, is, err, &tm, fz + 2, pe);
+#else
                 tg.get(is, 0, is, err, &tm, fz + 2, pe);
+#endif
                 if (err & std::ios_base::failbit) goto exit;
               }
             }
@@ -674,7 +1010,7 @@
             time_t t;
             if (tz == timezone::utc || fz != pe)
             {
-#if defined BOOST_CHRONO_INTERNAL_TIMEGM
+#if BOOST_CHRONO_INTERNAL_TIMEGM
               t = detail::internal_timegm(&tm);
 #else
               t = timegm(&tm);

Modified: trunk/libs/chrono/test/io/time_point_input.cpp
==============================================================================
--- trunk/libs/chrono/test/io/time_point_input.cpp (original)
+++ trunk/libs/chrono/test/io/time_point_input.cpp 2012-10-21 21:06:57 EDT (Sun, 21 Oct 2012)
@@ -26,13 +26,16 @@
 {
   typedef boost::chrono::system_clock Clock;
 
- std::istringstream in(str + boost::chrono::clock_string<Clock, char>::since());
+ std::istringstream in(str);
   boost::chrono::time_point<Clock, D> tp;
   in >> tp;
   BOOST_TEST(in.eof());
   BOOST_TEST(!in.fail());
+ std::cout << "Input= " << str << std::endl;
   std::cout << "Expected= " << boost::chrono::time_point<Clock, D>(res) << std::endl;
   std::cout << "Obtained= " << tp << std::endl;
+ std::cout << "Expected= " << boost::chrono::duration_cast<boost::chrono::nanoseconds>(boost::chrono::time_point<Clock, D>(res).time_since_epoch()).count() << std::endl;
+ std::cout << "Obtained= " << boost::chrono::duration_cast<boost::chrono::nanoseconds>(tp.time_since_epoch()).count() << std::endl;
   BOOST_TEST( (tp == boost::chrono::time_point<Clock, D>(res)));
 }
 #endif
@@ -143,7 +146,7 @@
   std::cout << "steady_clock=" << std::endl;
   check_all<boost::chrono::steady_clock> ();
 #endif
- std::cout << "system_clock=";
+ std::cout << "system_clock=" << std::endl;
 #if BOOST_CHRONO_VERSION >= 2
   check_all_system_clock();
 #else


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk