Skip to content

Instantly share code, notes, and snippets.

@Nava2
Created March 7, 2016 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nava2/bdf4bb751be2953e3340 to your computer and use it in GitHub Desktop.
Save Nava2/bdf4bb751be2953e3340 to your computer and use it in GitHub Desktop.
IO for std::chrono that prints nice messages
// chrono_io
//
// (C) Copyright Howard Hinnant
// 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).
#ifndef _CHRONO_IO
#define _CHRONO_IO
/*
chrono_io synopsis
#include <chrono>
#include <ratio_io>
namespace std
{
namespace chrono
{
template <class CharT>
class durationpunct
: public locale::facet
{
public:
static locale::id id;
typedef basic_string<CharT> string_type;
enum {use_long, use_short};
explicit durationpunct(int use = use_long);
durationpunct(int use,
const string_type& long_seconds, const string_type& long_minutes,
const string_type& long_hours, const string_type& short_seconds,
const string_type& short_minutes, const string_type& short_hours);
durationpunct(int use, const durationpunct& d);
template <class Period> string_type short_name() const;
template <class Period> string_type long_name() const;
template <class Period> string_type name() const;
bool is_short_name() const;
bool is_long_name() const;
};
template <class CharT, class Traits>
basic_ostream<CharT, Traits>&
duration_short(basic_ostream<CharT, Traits>& os);
template <class CharT, class Traits>
basic_ostream<CharT, Traits>&
duration_long(basic_ostream<CharT, Traits>& os);
template <class CharT, class Traits, class Rep, class Period>
basic_ostream<CharT, Traits>&
operator<<(basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d);
template <class CharT, class Traits, class Rep, class Period>
basic_istream<CharT, Traits>&
operator>>(basic_istream<CharT, Traits>& is, duration<Rep, Period>& d);
template <class CharT, class Traits, class Duration>
basic_ostream<CharT, Traits>&
operator<<(basic_ostream<CharT, Traits>& os,
const time_point<steady_clock, Duration>& tp);
template <class CharT, class Traits, class Duration>
basic_ostream<CharT, Traits>&
operator<<(basic_ostream<CharT, Traits>& os,
const time_point<high_resolution_clock, Duration>& tp);
template <class CharT, class Traits, class Duration>
basic_ostream<CharT, Traits>&
operator<<(basic_ostream<CharT, Traits>& os,
const time_point<system_clock, Duration>& tp);
template <class CharT, class Traits, class Duration>
basic_istream<CharT, Traits>&
operator>>(basic_istream<CharT, Traits>& is,
time_point<steady_clock, Duration>& tp);
template <class CharT, class Traits, class Duration>
basic_istream<CharT, Traits>&
operator>>(basic_istream<CharT, Traits>& is,
time_point<high_resolution_clock, Duration>& tp);
template <class CharT, class Traits, class Duration>
basic_istream<CharT, Traits>&
operator>>(basic_istream<CharT, Traits>& is,
time_point<system_clock, Duration>& tp);
template <class CharT>
class timepunct
: public std::locale::facet
{
public:
typedef std::basic_string<CharT> string_type;
static std::locale::id id;
explicit timepunct(std::size_t refs = 0,
const string_type& fmt = string_type(),
bool local = false);
explicit timepunct(std::size_t refs,
string_type&& fmt,
bool local = false);
const string_type& fmt() const {return fmt_;}
bool local() const {return local_;}
};
template<class CharT>
unspecfiied
local_fmt(std::basic_string<CharT> fmt = std::basic_string<CharT>());
template<class CharT>
unspecfiied
local_fmt(const CharT* fmt);
template<class CharT>
unspecfiied
utc_fmt(std::basic_string<CharT> fmt = std::basic_string<CharT>());
template<class CharT>
unspecfiied
utc_fmt(const CharT* fmt);
} // chrono
} // std
*/
#include <chrono>
#include <locale>
#include "ratio_io"
namespace std
{
namespace chrono
{
template <class To, class Rep, class Period>
To
round(const duration<Rep, Period>& d)
{
To t0 = duration_cast<To>(d);
To t1 = t0;
++t1;
typedef typename common_type<To, duration<Rep, Period> >::type _D;
_D diff0 = d - t0;
_D diff1 = t1 - d;
if (diff0 == diff1)
{
if (t0.count() & 1)
return t1;
return t0;
}
else if (diff0 < diff1)
return t0;
return t1;
}
template <class _CharT>
class durationpunct
: public locale::facet
{
public:
typedef basic_string<_CharT> string_type;
enum {use_long, use_short};
private:
bool __use_short_;
string_type __seconds_;
string_type __minutes_;
string_type __hours_;
public:
static locale::id id;
explicit durationpunct(size_t refs = 0,
int __use = use_long)
: locale::facet(refs), __use_short_(__use) {}
durationpunct(size_t refs, int __use,
string_type __seconds, string_type __minutes,
string_type __hours)
: locale::facet(refs), __use_short_(__use),
__seconds_(std::move(__seconds)),
__minutes_(std::move(__minutes)),
__hours_(std::move(__hours)) {}
bool is_short_name() const {return __use_short_;}
bool is_long_name() const {return !__use_short_;}
string_type seconds() const {return __seconds_;}
string_type minutes() const {return __minutes_;}
string_type hours() const {return __hours_;}
};
template <class _CharT>
locale::id
durationpunct<_CharT>::id;
enum {prefix, symbol};
enum {utc, local};
template<class _CharT>
struct __duration_manip
{
bool __use_short_;
basic_string<_CharT> __seconds_;
basic_string<_CharT> __minutes_;
basic_string<_CharT> __hours_;
__duration_manip(bool __use_short, basic_string<_CharT> __seconds,
basic_string<_CharT> __minutes, basic_string<_CharT> __hours)
: __use_short_(__use_short),
__seconds_(std::move(__seconds)),
__minutes_(std::move(__minutes)),
__hours_(std::move(__hours)) {}
};
class duration_fmt
{
int form_;
public:
explicit duration_fmt(int f) : form_(f) {}
// explicit
operator int() const {return form_;}
};
template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, duration_fmt d)
{
os.imbue(std::locale(os.getloc(), new durationpunct<charT>(0, d == symbol)));
return os;
}
template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, duration_fmt d)
{
is.imbue(std::locale(is.getloc(), new durationpunct<charT>(0, d == symbol)));
return is;
}
template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, __duration_manip<charT> m)
{
os.imbue(std::locale(os.getloc(), new durationpunct<charT>(0, m.__use_short_,
std::move(m.__seconds_), std::move(m.__minutes_), std::move(m.__hours_))));
return os;
}
template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, __duration_manip<charT> m)
{
is.imbue(std::locale(is.getloc(), new durationpunct<charT>(0, m.__use_short_,
std::move(m.__seconds_), std::move(m.__minutes_), std::move(m.__hours_))));
return is;
}
inline
__duration_manip<char>
duration_short()
{
return __duration_manip<char>(durationpunct<char>::use_short, "", "", "");
}
template <class _CharT>
inline
__duration_manip<_CharT>
duration_short(basic_string<_CharT> __seconds,
basic_string<_CharT> __minutes,
basic_string<_CharT> __hours)
{
return __duration_manip<_CharT>(durationpunct<_CharT>::use_short,
std::move(__seconds), std::move(__minutes),
std::move(__hours));
}
inline
__duration_manip<char>
duration_long()
{
return __duration_manip<char>(durationpunct<char>::use_long, "", "", "");
}
template <class _CharT, class _T2, class _T3>
inline
typename enable_if
<
is_convertible<_T2, basic_string<_CharT> >::value &&
is_convertible<_T3, basic_string<_CharT> >::value,
__duration_manip<_CharT>
>::type
duration_long(basic_string<_CharT> __seconds,
_T2 __minutes,
_T3 __hours)
{
typedef basic_string<_CharT> string_type;
return __duration_manip<_CharT>(durationpunct<_CharT>::use_long,
std::move(__seconds),
string_type(std::move(__minutes)),
string_type(std::move(__hours)));
}
template <class _CharT, class _T2, class _T3>
inline
typename enable_if
<
is_convertible<_T2, basic_string<_CharT> >::value &&
is_convertible<_T3, basic_string<_CharT> >::value,
__duration_manip<_CharT>
>::type
duration_long(const _CharT* __seconds,
_T2 __minutes,
_T3 __hours)
{
typedef basic_string<_CharT> string_type;
return __duration_manip<_CharT>(durationpunct<_CharT>::use_long,
string_type(__seconds),
string_type(std::move(__minutes)),
string_type(std::move(__hours)));
}
template <class _CharT, class _Period>
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>& __seconds,
const basic_string<_CharT>&, const basic_string<_CharT>&, _Period)
{
if (__is_long)
{
if (__seconds.empty())
{
_CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's', 0};
return ratio_string<_Period, _CharT>::prefix() + __p;
}
return ratio_string<_Period, _CharT>::prefix() + __seconds;
}
if (__seconds.empty())
return ratio_string<_Period, _CharT>::symbol() + 's';
return ratio_string<_Period, _CharT>::symbol() + __seconds;
}
template <class _CharT>
inline
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>& __seconds,
const basic_string<_CharT>&, const basic_string<_CharT>&, ratio<1>)
{
if (__seconds.empty())
{
if (__is_long)
{
_CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
}
else
return basic_string<_CharT>(1, 's');
}
return __seconds;
}
template <class _CharT>
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>&,
const basic_string<_CharT>& __minutes,
const basic_string<_CharT>&, ratio<60>)
{
if (__minutes.empty())
{
if (__is_long)
{
_CharT __p[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
}
else
return basic_string<_CharT>(1, 'm');
}
return __minutes;
}
template <class _CharT>
inline
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>&,
const basic_string<_CharT>&,
const basic_string<_CharT>& __hours, ratio<3600>)
{
if (__hours.empty())
{
if (__is_long)
{
_CharT __p[] = {'h', 'o', 'u', 'r', 's'};
return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
}
else
return basic_string<_CharT>(1, 'h');
}
return __hours;
}
template <class _CharT, class _Traits, class _Rep, class _Period>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d)
{
typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
if (ok)
{
typedef durationpunct<_CharT> _F;
typedef basic_string<_CharT> string_type;
bool failed = false;
try
{
bool __is_long = true;
string_type __seconds;
string_type __minutes;
string_type __hours;
locale __loc = __os.getloc();
if (has_facet<_F>(__loc))
{
const _F& f = use_facet<_F>(__loc);
__is_long = f.is_long_name();
__seconds = f.seconds();
__minutes = f.minutes();
__hours = f.hours();
}
string_type __unit = __get_unit(__is_long, __seconds, __minutes,
__hours, typename _Period::type());
__os << __d.count() << ' ' << __unit;
}
catch (...)
{
failed = true;
}
if (failed)
__os.setstate(ios_base::failbit | ios_base::badbit);
}
return __os;
}
template <class _Rep, bool = is_scalar<_Rep>::value>
struct __duration_io_intermediate
{
typedef _Rep type;
};
template <class _Rep>
struct __duration_io_intermediate<_Rep, true>
{
typedef typename conditional
<
is_floating_point<_Rep>::value,
long double,
typename conditional
<
is_signed<_Rep>::value,
long long,
unsigned long long
>::type
>::type type;
};
template <class T>
T
__gcd(T x, T y)
{
while (y != 0)
{
T old_x = x;
x = y;
y = old_x % y;
}
return x;
}
template <>
long double
inline
__gcd(long double x, long double y)
{
return 1;
}
template <class _CharT, class _Traits, class _Rep, class _Period>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, duration<_Rep, _Period>& __d)
{
typedef basic_string<_CharT> string_type;
typedef durationpunct<_CharT> _F;
typedef typename __duration_io_intermediate<_Rep>::type _IR;
_IR __r;
// read value into __r
__is >> __r;
if (__is.good())
{
// now determine unit
typedef istreambuf_iterator<_CharT, _Traits> _I;
_I __i(__is);
_I __e;
if (__i != __e && *__i == ' ') // mandatory ' ' after value
{
++__i;
if (__i != __e)
{
string_type __seconds;
string_type __minutes;
string_type __hours;
locale __loc = __is.getloc();
if (has_facet<_F>(__loc))
{
const _F& f = use_facet<_F>(__loc);
__seconds = f.seconds();
__minutes = f.minutes();
__hours = f.hours();
}
// unit is num / den (yet to be determined)
unsigned long long num = 0;
unsigned long long den = 0;
if (*__i == '[')
{
// parse [N/D]s or [N/D]seconds format
++__i;
_CharT __x;
__is >> num >> __x >> den;
if (!__is.good() || __x != '/')
{
__is.setstate(__is.failbit);
return __is;
}
__i = _I(__is);
if (*__i != ']')
{
__is.setstate(__is.failbit);
return __is;
}
++__i;
const basic_string<_CharT> __units[] =
{
__get_unit(true, __seconds, __minutes, __hours, ratio<1>()),
__get_unit(false, __seconds, __minutes, __hours, ratio<1>())
};
ios_base::iostate __err = ios_base::goodbit;
const basic_string<_CharT>* __k = __scan_keyword(__i, __e,
__units, __units + sizeof(__units)/sizeof(__units[0]),
use_facet<ctype<_CharT> >(__loc),
__err);
switch ((__k - __units) / 2)
{
case 0:
break;
default:
__is.setstate(__err);
return __is;
}
}
else
{
// parse SI name, short or long
const basic_string<_CharT> __units[] =
{
__get_unit(true, __seconds, __minutes, __hours, atto()),
__get_unit(false, __seconds, __minutes, __hours, atto()),
__get_unit(true, __seconds, __minutes, __hours, femto()),
__get_unit(false, __seconds, __minutes, __hours, femto()),
__get_unit(true, __seconds, __minutes, __hours, pico()),
__get_unit(false, __seconds, __minutes, __hours, pico()),
__get_unit(true, __seconds, __minutes, __hours, nano()),
__get_unit(false, __seconds, __minutes, __hours, nano()),
__get_unit(true, __seconds, __minutes, __hours, micro()),
__get_unit(false, __seconds, __minutes, __hours, micro()),
__get_unit(true, __seconds, __minutes, __hours, milli()),
__get_unit(false, __seconds, __minutes, __hours, milli()),
__get_unit(true, __seconds, __minutes, __hours, centi()),
__get_unit(false, __seconds, __minutes, __hours, centi()),
__get_unit(true, __seconds, __minutes, __hours, deci()),
__get_unit(false, __seconds, __minutes, __hours, deci()),
__get_unit(true, __seconds, __minutes, __hours, deca()),
__get_unit(false, __seconds, __minutes, __hours, deca()),
__get_unit(true, __seconds, __minutes, __hours, hecto()),
__get_unit(false, __seconds, __minutes, __hours, hecto()),
__get_unit(true, __seconds, __minutes, __hours, kilo()),
__get_unit(false, __seconds, __minutes, __hours, kilo()),
__get_unit(true, __seconds, __minutes, __hours, mega()),
__get_unit(false, __seconds, __minutes, __hours, mega()),
__get_unit(true, __seconds, __minutes, __hours, giga()),
__get_unit(false, __seconds, __minutes, __hours, giga()),
__get_unit(true, __seconds, __minutes, __hours, tera()),
__get_unit(false, __seconds, __minutes, __hours, tera()),
__get_unit(true, __seconds, __minutes, __hours, peta()),
__get_unit(false, __seconds, __minutes, __hours, peta()),
__get_unit(true, __seconds, __minutes, __hours, exa()),
__get_unit(false, __seconds, __minutes, __hours, exa()),
__get_unit(true, __seconds, __minutes, __hours, ratio<1>()),
__get_unit(false, __seconds, __minutes, __hours, ratio<1>()),
__get_unit(true, __seconds, __minutes, __hours, ratio<60>()),
__get_unit(false, __seconds, __minutes, __hours, ratio<60>()),
__get_unit(true, __seconds, __minutes, __hours, ratio<3600>()),
__get_unit(false, __seconds, __minutes, __hours, ratio<3600>())
};
ios_base::iostate __err = ios_base::goodbit;
const basic_string<_CharT>* __k = __scan_keyword(__i, __e,
__units, __units + sizeof(__units)/sizeof(__units[0]),
use_facet<ctype<_CharT> >(__loc),
__err);
switch ((__k - __units) / 2)
{
case 0:
num = 1ULL;
den = 1000000000000000000ULL;
break;
case 1:
num = 1ULL;
den = 1000000000000000ULL;
break;
case 2:
num = 1ULL;
den = 1000000000000ULL;
break;
case 3:
num = 1ULL;
den = 1000000000ULL;
break;
case 4:
num = 1ULL;
den = 1000000ULL;
break;
case 5:
num = 1ULL;
den = 1000ULL;
break;
case 6:
num = 1ULL;
den = 100ULL;
break;
case 7:
num = 1ULL;
den = 10ULL;
break;
case 8:
num = 10ULL;
den = 1ULL;
break;
case 9:
num = 100ULL;
den = 1ULL;
break;
case 10:
num = 1000ULL;
den = 1ULL;
break;
case 11:
num = 1000000ULL;
den = 1ULL;
break;
case 12:
num = 1000000000ULL;
den = 1ULL;
break;
case 13:
num = 1000000000000ULL;
den = 1ULL;
break;
case 14:
num = 1000000000000000ULL;
den = 1ULL;
break;
case 15:
num = 1000000000000000000ULL;
den = 1ULL;
break;
case 16:
num = 1;
den = 1;
break;
case 17:
num = 60;
den = 1;
break;
case 18:
num = 3600;
den = 1;
break;
default:
__is.setstate(__err);
return __is;
}
}
// unit is num/den
// __r should be multiplied by (num/den) / _Period
// Reduce (num/den) / _Period to lowest terms
unsigned long long __gcd_n1_n2 = __gcd<unsigned long long>(num, _Period::num);
unsigned long long __gcd_d1_d2 = __gcd<unsigned long long>(den, _Period::den);
num /= __gcd_n1_n2;
den /= __gcd_d1_d2;
unsigned long long __n2 = _Period::num / __gcd_n1_n2;
unsigned long long __d2 = _Period::den / __gcd_d1_d2;
if (num > numeric_limits<unsigned long long>::max() / __d2 ||
den > numeric_limits<unsigned long long>::max() / __n2)
{
// (num/den) / _Period overflows
__is.setstate(__is.failbit);
return __is;
}
num *= __d2;
den *= __n2;
// num / den is now factor to multiply by __r
typedef typename common_type<_IR, unsigned long long>::type _CT;
if (is_integral<_IR>::value)
{
// Reduce __r * num / den
_CT __t = __gcd<_CT>(__r, den);
__r /= __t;
den /= __t;
if (den != 1)
{
// Conversion to _Period is integral and not exact
__is.setstate(__is.failbit);
return __is;
}
}
if (__r > duration_values<_CT>::max() / num)
{
// Conversion to _Period overflowed
__is.setstate(__is.failbit);
return __is;
}
_CT __t = __r * num;
__t /= den;
if (duration_values<_Rep>::max() < __t)
{
// Conversion to _Period overflowed
__is.setstate(__is.failbit);
return __is;
}
// Success! Store it.
__r = _Rep(__t);
__d = duration<_Rep, _Period>(__r);
}
else
__is.setstate(__is.failbit | __is.eofbit);
}
else
{
if (__i == __e)
__is.setstate(__is.eofbit);
__is.setstate(__is.failbit);
}
}
else
__is.setstate(__is.failbit);
return __is;
}
template <class charT>
class timepunct
: public std::locale::facet
{
public:
typedef std::basic_string<charT> string_type;
private:
string_type fmt_;
bool local_;
public:
static std::locale::id id;
explicit timepunct(std::size_t refs = 0,
const string_type& fmt = string_type(),
bool local = false)
: std::locale::facet(refs),
fmt_(fmt),
local_(local) {}
explicit timepunct(std::size_t refs,
string_type&& fmt,
bool local = false)
: std::locale::facet(refs),
fmt_(std::move(fmt)),
local_(local) {}
const string_type& fmt() const {return fmt_;}
bool local() const {return local_;}
};
template <class CharT>
std::locale::id
timepunct<CharT>::id;
template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
const time_point<steady_clock, _Duration>& __tp)
{
return __os << __tp.time_since_epoch() << " since boot";
}
template<class charT>
struct __time_manip
{
std::basic_string<charT> fmt_;
bool local_;
__time_manip(std::basic_string<charT> fmt, bool local)
: fmt_(std::move(fmt)),
local_(local) {}
};
template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, __time_manip<charT> m)
{
os.imbue(std::locale(os.getloc(), new timepunct<charT>(0, std::move(m.fmt_), m.local_)));
return os;
}
template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, __time_manip<charT> m)
{
is.imbue(std::locale(is.getloc(), new timepunct<charT>(0, std::move(m.fmt_), m.local_)));
return is;
}
template<class charT>
inline
__time_manip<charT>
local_fmt(std::basic_string<charT> fmt)
{
return __time_manip<charT>(std::move(fmt), true);
}
template<class charT>
inline
__time_manip<charT>
local_fmt(const charT* fmt)
{
return __time_manip<charT>(fmt, true);
}
inline
__time_manip<char>
local_fmt()
{
return __time_manip<char>("", true);
}
template<class charT>
inline
__time_manip<charT>
utc_fmt(std::basic_string<charT> fmt)
{
return __time_manip<charT>(std::move(fmt), false);
}
template<class charT>
inline
__time_manip<charT>
utc_fmt(const charT* fmt)
{
return __time_manip<charT>(fmt, false);
}
inline
__time_manip<char>
utc_fmt()
{
return __time_manip<char>("", false);
}
class __time_man
{
int form_;
public:
explicit __time_man(int f) : form_(f) {}
// explicit
operator int() const {return form_;}
};
template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, __time_man m)
{
os.imbue(std::locale(os.getloc(), new timepunct<charT>(0, basic_string<charT>(), m == local)));
return os;
}
template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, __time_man m)
{
is.imbue(std::locale(is.getloc(), new timepunct<charT>(0, basic_string<charT>(), m == local)));
return is;
}
inline
__time_man
time_fmt(int f)
{
return __time_man(f);
}
template <class _CharT, class _Traits, class _Duration>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
time_point<steady_clock, _Duration>& __tp)
{
_Duration __d;
__is >> __d;
if (__is.good())
{
const _CharT __u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't'};
const basic_string<_CharT> __units(__u, __u + sizeof(__u)/sizeof(__u[0]));
ios_base::iostate __err = ios_base::goodbit;
typedef istreambuf_iterator<_CharT, _Traits> _I;
_I __i(__is);
_I __e;
ptrdiff_t __k = __scan_keyword(__i, __e,
&__units, &__units + 1,
use_facet<ctype<_CharT> >(__is.getloc()),
__err) - &__units;
if (__k == 1)
{
// failed to read epoch string
__is.setstate(__err);
return __is;
}
__tp = time_point<steady_clock, _Duration>(__d);
}
else
__is.setstate(__is.failbit);
return __is;
}
template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
const time_point<system_clock, _Duration>& __tp)
{
typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
if (ok)
{
bool failed = false;
try
{
const _CharT* pb = nullptr;
const _CharT* pe = pb;
bool __local = false;
typedef timepunct<_CharT> F;
locale loc = __os.getloc();
if (has_facet<F>(loc))
{
const F& f = use_facet<F>(loc);
pb = f.fmt().data();
pe = pb + f.fmt().size();
__local = f.local();
}
time_t __t = system_clock::to_time_t(__tp);
tm __tm;
if (__local)
{
if (localtime_r(&__t, &__tm) == 0)
failed = true;
}
else
{
if (gmtime_r(&__t, &__tm) == 0)
failed = true;
}
if (!failed)
{
const time_put<_CharT>& tp = use_facet<time_put<_CharT> >(loc);
if (pb == pe)
{
_CharT pattern[] = {'%', 'F', ' ', '%', 'H', ':', '%', 'M', ':'};
pb = pattern;
pe = pb + sizeof(pattern) / sizeof(_CharT);
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
if (!failed)
{
duration<double> __d = __tp - system_clock::from_time_t(__t) +
seconds(__tm.tm_sec);
if (__d.count() < 10)
__os << _CharT('0');
ios::fmtflags __flgs = __os.flags();
__os.setf(ios::fixed, ios::floatfield);
__os << __d.count();
__os.flags(__flgs);
if (__local)
{
_CharT sub_pattern[] = {' ', '%', 'z'};
pb = sub_pattern;
pe = pb + + sizeof(sub_pattern) / sizeof(_CharT);
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
}
else
{
_CharT sub_pattern[] = {' ', '+', '0', '0', '0', '0', 0};
__os << sub_pattern;
}
}
}
else
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
}
}
catch (...)
{
failed = true;
}
if (failed)
__os.setstate(ios_base::failbit | ios_base::badbit);
}
return __os;
}
template <class _CharT, class _Traits, class _Duration>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
time_point<system_clock, _Duration>& __tp)
{
typename basic_istream<_CharT,_Traits>::sentry ok(__is);
if (ok)
{
ios_base::iostate err = ios_base::goodbit;
try
{
const _CharT* pb = nullptr;
const _CharT* pe = pb;
bool __local = false;
typedef timepunct<_CharT> F;
locale loc = __is.getloc();
if (has_facet<F>(loc))
{
const F& f = use_facet<F>(loc);
pb = f.fmt().data();
pe = pb + f.fmt().size();
__local = f.local();
}
const time_get<_CharT>& tg = use_facet<time_get<_CharT> >(loc);
tm __tm = {0};
if (pb == pe)
{
_CharT pattern[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd',
' ', '%', 'H', ':', '%', 'M', ':'};
pb = pattern;
pe = pb + sizeof(pattern) / sizeof(_CharT);
tg.get(__is, 0, __is, err, &__tm, pb, pe);
if (err & ios_base::failbit)
goto __exit;
typedef istreambuf_iterator<_CharT, _Traits> _I;
double __sec;
_CharT __c = _CharT();
__is >> __sec;
if (__is.fail())
{
err |= ios_base::failbit;
goto __exit;
}
_I __i(__is);
_I __eof;
__c = *__i;
if (++__i == __eof || __c != ' ')
{
err |= ios_base::failbit;
goto __exit;
}
__c = *__i;
if (++__i == __eof || (__c != '+' && __c != '-'))
{
err |= ios_base::failbit;
goto __exit;
}
int __n = __c == '-' ? 1 : -1;
__c = *__i;
if (++__i == __eof || !isdigit(__c))
{
err |= ios_base::failbit;
goto __exit;
}
int __min = (__c - '0') * 600;
__c = *__i;
if (++__i == __eof || !isdigit(__c))
{
err |= ios_base::failbit;
goto __exit;
}
__min += (__c - '0') * 60;
__c = *__i;
if (++__i == __eof || !isdigit(__c))
{
err |= ios_base::failbit;
goto __exit;
}
__min += (__c - '0') * 10;
__c = *__i;
if (!isdigit(__c))
{
err |= ios_base::failbit;
goto __exit;
}
++__i;
__min += __c - '0';
__min *= __n;
time_t __t;
__t = timegm(&__tm);
__tp = system_clock::from_time_t(__t) + minutes(__min)
+ round<microseconds>(duration<double>(__sec));
}
else
{
tg.get(__is, 0, __is, err, &__tm, pb, pe);
}
}
catch (...)
{
err |= ios_base::badbit | ios_base::failbit;
}
__exit:
__is.setstate(err);
}
return __is;
}
} // chrono
} // std
#endif // _CHRONO_IO
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment