638 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			638 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
 | 
						|
//  chrono_io
 | 
						|
//
 | 
						|
//  (C) Copyright Howard Hinnant
 | 
						|
//  (C) Copyright 2010 Vicente J. Botet Escriba
 | 
						|
//  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).
 | 
						|
//
 | 
						|
// This code was adapted by Vicente from Howard Hinnant's experimental work
 | 
						|
// on chrono i/o under lvm/libc++  to Boost
 | 
						|
 | 
						|
#ifndef BOOST_CHRONO_IO_V1_CHRONO_IO_HPP
 | 
						|
#define BOOST_CHRONO_IO_V1_CHRONO_IO_HPP
 | 
						|
 | 
						|
#include <boost/chrono/chrono.hpp>
 | 
						|
#include <boost/chrono/process_cpu_clocks.hpp>
 | 
						|
#include <boost/chrono/thread_clock.hpp>
 | 
						|
#include <boost/chrono/clock_string.hpp>
 | 
						|
#include <boost/ratio/ratio_io.hpp>
 | 
						|
#include <locale>
 | 
						|
#include <boost/type_traits/is_scalar.hpp>
 | 
						|
#include <boost/type_traits/is_signed.hpp>
 | 
						|
#include <boost/mpl/if.hpp>
 | 
						|
#include <boost/integer/common_factor_rt.hpp>
 | 
						|
#include <boost/chrono/detail/scan_keyword.hpp>
 | 
						|
#include <boost/utility/enable_if.hpp>
 | 
						|
#include <boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp>
 | 
						|
 | 
						|
namespace boost
 | 
						|
{
 | 
						|
 | 
						|
namespace chrono
 | 
						|
{
 | 
						|
 | 
						|
template <class CharT>
 | 
						|
class duration_punct
 | 
						|
    : public std::locale::facet
 | 
						|
{
 | 
						|
public:
 | 
						|
    typedef std::basic_string<CharT> string_type;
 | 
						|
    enum {use_long, use_short};
 | 
						|
 | 
						|
private:
 | 
						|
    bool use_short_;
 | 
						|
    string_type long_seconds_;
 | 
						|
    string_type long_minutes_;
 | 
						|
    string_type long_hours_;
 | 
						|
    string_type short_seconds_;
 | 
						|
    string_type short_minutes_;
 | 
						|
    string_type short_hours_;
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type short_name(Period) const
 | 
						|
            {return ::boost::ratio_string<Period, CharT>::short_name() + short_seconds_;}
 | 
						|
 | 
						|
    string_type short_name(ratio<1>) const    {return short_seconds_;}
 | 
						|
    string_type short_name(ratio<60>) const   {return short_minutes_;}
 | 
						|
    string_type short_name(ratio<3600>) const {return short_hours_;}
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type long_name(Period) const
 | 
						|
            {return ::boost::ratio_string<Period, CharT>::long_name() + long_seconds_;}
 | 
						|
 | 
						|
    string_type long_name(ratio<1>) const    {return long_seconds_;}
 | 
						|
    string_type long_name(ratio<60>) const   {return long_minutes_;}
 | 
						|
    string_type long_name(ratio<3600>) const {return long_hours_;}
 | 
						|
 | 
						|
    void init_C();
 | 
						|
public:
 | 
						|
    static std::locale::id id;
 | 
						|
 | 
						|
    explicit duration_punct(int use = use_long)
 | 
						|
        : use_short_(use==use_short) {init_C();}
 | 
						|
 | 
						|
    duration_punct(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);
 | 
						|
 | 
						|
    duration_punct(int use, const duration_punct& d);
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type short_name() const
 | 
						|
            {return short_name(typename Period::type());}
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type long_name() const
 | 
						|
            {return long_name(typename Period::type());}
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type plural() const
 | 
						|
            {return long_name(typename Period::type());}
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type singular() const
 | 
						|
    {
 | 
						|
      return string_type(long_name(typename Period::type()), 0, long_name(typename Period::type()).size()-1);
 | 
						|
    }
 | 
						|
 | 
						|
    template <class Period>
 | 
						|
        string_type name() const
 | 
						|
    {
 | 
						|
      if (use_short_) return short_name<Period>();
 | 
						|
      else {
 | 
						|
        return long_name<Period>();
 | 
						|
      }
 | 
						|
    }
 | 
						|
    template <class Period, class D>
 | 
						|
      string_type name(D v) const
 | 
						|
      {
 | 
						|
        if (use_short_) return short_name<Period>();
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (v==-1 || v==1)
 | 
						|
            return singular<Period>();
 | 
						|
          else
 | 
						|
            return plural<Period>();
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
    bool is_short_name() const {return use_short_;}
 | 
						|
    bool is_long_name() const {return !use_short_;}
 | 
						|
};
 | 
						|
 | 
						|
template <class CharT>
 | 
						|
std::locale::id
 | 
						|
duration_punct<CharT>::id;
 | 
						|
 | 
						|
template <class CharT>
 | 
						|
void
 | 
						|
duration_punct<CharT>::init_C()
 | 
						|
{
 | 
						|
    short_seconds_ = CharT('s');
 | 
						|
    short_minutes_ = CharT('m');
 | 
						|
    short_hours_ = CharT('h');
 | 
						|
    const CharT s[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
 | 
						|
    const CharT m[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
 | 
						|
    const CharT h[] = {'h', 'o', 'u', 'r', 's'};
 | 
						|
    long_seconds_.assign(s, s + sizeof(s)/sizeof(s[0]));
 | 
						|
    long_minutes_.assign(m, m + sizeof(m)/sizeof(m[0]));
 | 
						|
    long_hours_.assign(h, h + sizeof(h)/sizeof(h[0]));
 | 
						|
}
 | 
						|
 | 
						|
template <class CharT>
 | 
						|
duration_punct<CharT>::duration_punct(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)
 | 
						|
    : use_short_(use==use_short),
 | 
						|
      long_seconds_(long_seconds),
 | 
						|
      long_minutes_(long_minutes),
 | 
						|
      long_hours_(long_hours),
 | 
						|
      short_seconds_(short_seconds),
 | 
						|
      short_minutes_(short_minutes),
 | 
						|
      short_hours_(short_hours)
 | 
						|
{}
 | 
						|
 | 
						|
template <class CharT>
 | 
						|
duration_punct<CharT>::duration_punct(int use, const duration_punct& d)
 | 
						|
    : use_short_(use==use_short),
 | 
						|
      long_seconds_(d.long_seconds_),
 | 
						|
      long_minutes_(d.long_minutes_),
 | 
						|
      long_hours_(d.long_hours_),
 | 
						|
      short_seconds_(d.short_seconds_),
 | 
						|
      short_minutes_(d.short_minutes_),
 | 
						|
      short_hours_(d.short_hours_)
 | 
						|
{}
 | 
						|
 | 
						|
template <class CharT, class Traits>
 | 
						|
std::basic_ostream<CharT, Traits>&
 | 
						|
duration_short(std::basic_ostream<CharT, Traits>& os)
 | 
						|
{
 | 
						|
    typedef duration_punct<CharT> Facet;
 | 
						|
    std::locale loc = os.getloc();
 | 
						|
    if (std::has_facet<Facet>(loc))
 | 
						|
    {
 | 
						|
        const Facet& f = std::use_facet<Facet>(loc);
 | 
						|
        if (f.is_long_name())
 | 
						|
            os.imbue(std::locale(loc, new Facet(Facet::use_short, f)));
 | 
						|
    }
 | 
						|
    else
 | 
						|
        os.imbue(std::locale(loc, new Facet(Facet::use_short)));
 | 
						|
    return os;
 | 
						|
}
 | 
						|
 | 
						|
template <class CharT, class Traits>
 | 
						|
std::basic_ostream<CharT, Traits>&
 | 
						|
duration_long(std::basic_ostream<CharT, Traits>& os)
 | 
						|
{
 | 
						|
    typedef duration_punct<CharT> Facet;
 | 
						|
    std::locale loc = os.getloc();
 | 
						|
    if (std::has_facet<Facet>(loc))
 | 
						|
    {
 | 
						|
        const Facet& f = std::use_facet<Facet>(loc);
 | 
						|
        if (f.is_short_name())
 | 
						|
            os.imbue(std::locale(loc, new Facet(Facet::use_long, f)));
 | 
						|
    }
 | 
						|
    return os;
 | 
						|
}
 | 
						|
 | 
						|
template <class CharT, class Traits, class Rep, class Period>
 | 
						|
std::basic_ostream<CharT, Traits>&
 | 
						|
operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d)
 | 
						|
{
 | 
						|
    typedef duration_punct<CharT> Facet;
 | 
						|
    std::locale loc = os.getloc();
 | 
						|
    if (!std::has_facet<Facet>(loc))
 | 
						|
        os.imbue(std::locale(loc, new Facet));
 | 
						|
    const Facet& f = std::use_facet<Facet>(os.getloc());
 | 
						|
    return os << d.count() << ' ' << f.template name<Period>(d.count());
 | 
						|
}
 | 
						|
 | 
						|
namespace chrono_detail {
 | 
						|
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 mpl::if_c
 | 
						|
    <
 | 
						|
        is_floating_point<Rep>::value,
 | 
						|
            long double,
 | 
						|
            typename mpl::if_c
 | 
						|
            <
 | 
						|
                is_signed<Rep>::value,
 | 
						|
                    long long,
 | 
						|
                    unsigned long long
 | 
						|
            >::type
 | 
						|
    >::type type;
 | 
						|
};
 | 
						|
 | 
						|
template <typename intermediate_type>
 | 
						|
typename enable_if<is_integral<intermediate_type>, bool>::type
 | 
						|
reduce(intermediate_type& r, unsigned long long& den, std::ios_base::iostate& err)
 | 
						|
{
 | 
						|
  typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
 | 
						|
 | 
						|
    // Reduce r * num / den
 | 
						|
  common_type_t t = integer::gcd<common_type_t>(common_type_t(r), common_type_t(den));
 | 
						|
  r /= t;
 | 
						|
  den /= t;
 | 
						|
  if (den != 1)
 | 
						|
  {
 | 
						|
    // Conversion to Period is integral and not exact
 | 
						|
    err |= std::ios_base::failbit;
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
template <typename intermediate_type>
 | 
						|
typename disable_if<is_integral<intermediate_type>, bool>::type
 | 
						|
reduce(intermediate_type& , unsigned long long& , std::ios_base::iostate& )
 | 
						|
{
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
template <class CharT, class Traits, class Rep, class Period>
 | 
						|
std::basic_istream<CharT, Traits>&
 | 
						|
operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d)
 | 
						|
{
 | 
						|
  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
    typedef duration_punct<CharT> Facet;
 | 
						|
    std::locale loc = is.getloc();
 | 
						|
    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
    if (!std::has_facet<Facet>(loc)) {
 | 
						|
      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
        is.imbue(std::locale(loc, new Facet));
 | 
						|
    }
 | 
						|
    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
    loc = is.getloc();
 | 
						|
    const Facet& f = std::use_facet<Facet>(loc);
 | 
						|
    typedef typename chrono_detail::duration_io_intermediate<Rep>::type intermediate_type;
 | 
						|
    intermediate_type r;
 | 
						|
    std::ios_base::iostate err = std::ios_base::goodbit;
 | 
						|
    // read value into r
 | 
						|
    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
    is >> r;
 | 
						|
    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
    if (is.good())
 | 
						|
    {
 | 
						|
      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
        // now determine unit
 | 
						|
        typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
 | 
						|
        in_iterator i(is);
 | 
						|
        in_iterator e;
 | 
						|
        //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
        if (i != e && *i == ' ')  // mandatory ' ' after value
 | 
						|
        {
 | 
						|
          //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
            ++i;
 | 
						|
            if (i != e)
 | 
						|
            {
 | 
						|
              //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                // unit is num / den (yet to be determined)
 | 
						|
                unsigned long long num = 0;
 | 
						|
                unsigned long long den = 0;
 | 
						|
                if (*i == '[')
 | 
						|
                {
 | 
						|
                  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    // parse [N/D]s or [N/D]seconds format
 | 
						|
                    ++i;
 | 
						|
                    CharT x;
 | 
						|
                    is >> num >> x >> den;
 | 
						|
                    if (!is.good() || (x != '/'))
 | 
						|
                    {
 | 
						|
                      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                        is.setstate(is.failbit);
 | 
						|
                        return is;
 | 
						|
                    }
 | 
						|
                    i = in_iterator(is);
 | 
						|
                    if (*i != ']')
 | 
						|
                    {
 | 
						|
                      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                        is.setstate(is.failbit);
 | 
						|
                        return is;
 | 
						|
                    }
 | 
						|
                    ++i;
 | 
						|
                    const std::basic_string<CharT> units[] =
 | 
						|
                    {
 | 
						|
                        f.template singular<ratio<1> >(),
 | 
						|
                        f.template plural<ratio<1> >(),
 | 
						|
                        f.template short_name<ratio<1> >()
 | 
						|
                    };
 | 
						|
                    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
 | 
						|
                                  units, units + sizeof(units)/sizeof(units[0]),
 | 
						|
                                  //~ std::use_facet<std::ctype<CharT> >(loc),
 | 
						|
                                  err);
 | 
						|
                    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    is.setstate(err);
 | 
						|
                    switch ((k - units) / 3)
 | 
						|
                    {
 | 
						|
                    case 0:
 | 
						|
                      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                        break;
 | 
						|
                    default:
 | 
						|
                        is.setstate(err);
 | 
						|
                        //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                        return is;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    // parse SI name, short or long
 | 
						|
                    const std::basic_string<CharT> units[] =
 | 
						|
                    {
 | 
						|
                        f.template singular<atto>(),
 | 
						|
                        f.template plural<atto>(),
 | 
						|
                        f.template short_name<atto>(),
 | 
						|
                        f.template singular<femto>(),
 | 
						|
                        f.template plural<femto>(),
 | 
						|
                        f.template short_name<femto>(),
 | 
						|
                        f.template singular<pico>(),
 | 
						|
                        f.template plural<pico>(),
 | 
						|
                        f.template short_name<pico>(),
 | 
						|
                        f.template singular<nano>(),
 | 
						|
                        f.template plural<nano>(),
 | 
						|
                        f.template short_name<nano>(),
 | 
						|
                        f.template singular<micro>(),
 | 
						|
                        f.template plural<micro>(),
 | 
						|
                        f.template short_name<micro>(),
 | 
						|
                        f.template singular<milli>(),
 | 
						|
                        f.template plural<milli>(),
 | 
						|
                        f.template short_name<milli>(),
 | 
						|
                        f.template singular<centi>(),
 | 
						|
                        f.template plural<centi>(),
 | 
						|
                        f.template short_name<centi>(),
 | 
						|
                        f.template singular<deci>(),
 | 
						|
                        f.template plural<deci>(),
 | 
						|
                        f.template short_name<deci>(),
 | 
						|
                        f.template singular<deca>(),
 | 
						|
                        f.template plural<deca>(),
 | 
						|
                        f.template short_name<deca>(),
 | 
						|
                        f.template singular<hecto>(),
 | 
						|
                        f.template plural<hecto>(),
 | 
						|
                        f.template short_name<hecto>(),
 | 
						|
                        f.template singular<kilo>(),
 | 
						|
                        f.template plural<kilo>(),
 | 
						|
                        f.template short_name<kilo>(),
 | 
						|
                        f.template singular<mega>(),
 | 
						|
                        f.template plural<mega>(),
 | 
						|
                        f.template short_name<mega>(),
 | 
						|
                        f.template singular<giga>(),
 | 
						|
                        f.template plural<giga>(),
 | 
						|
                        f.template short_name<giga>(),
 | 
						|
                        f.template singular<tera>(),
 | 
						|
                        f.template plural<tera>(),
 | 
						|
                        f.template short_name<tera>(),
 | 
						|
                        f.template singular<peta>(),
 | 
						|
                        f.template plural<peta>(),
 | 
						|
                        f.template short_name<peta>(),
 | 
						|
                        f.template singular<exa>(),
 | 
						|
                        f.template plural<exa>(),
 | 
						|
                        f.template short_name<exa>(),
 | 
						|
                        f.template singular<ratio<1> >(),
 | 
						|
                        f.template plural<ratio<1> >(),
 | 
						|
                        f.template short_name<ratio<1> >(),
 | 
						|
                        f.template singular<ratio<60> >(),
 | 
						|
                        f.template plural<ratio<60> >(),
 | 
						|
                        f.template short_name<ratio<60> >(),
 | 
						|
                        f.template singular<ratio<3600> >(),
 | 
						|
                        f.template plural<ratio<3600> >(),
 | 
						|
                        f.template short_name<ratio<3600> >()
 | 
						|
                    };
 | 
						|
                    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
 | 
						|
                                  units, units + sizeof(units)/sizeof(units[0]),
 | 
						|
                                  //~ std::use_facet<std::ctype<CharT> >(loc),
 | 
						|
                                  err);
 | 
						|
                    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    switch ((k - units) / 3)
 | 
						|
                    {
 | 
						|
                    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:
 | 
						|
                      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                        is.setstate(err|is.failbit);
 | 
						|
                        return is;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                // 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 = integer::gcd<unsigned long long>(num, Period::num);
 | 
						|
                unsigned long long gcd_d1_d2 = integer::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 > (std::numeric_limits<unsigned long long>::max)() / d2 ||
 | 
						|
                    den > (std::numeric_limits<unsigned long long>::max)() / n2)
 | 
						|
                {
 | 
						|
                  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    // (num/den) / Period overflows
 | 
						|
                    is.setstate(err|is.failbit);
 | 
						|
                    return is;
 | 
						|
                }
 | 
						|
                num *= d2;
 | 
						|
                den *= n2;
 | 
						|
 | 
						|
                typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
 | 
						|
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                // num / den is now factor to multiply by r
 | 
						|
                if (!chrono_detail::reduce(r, den, err))
 | 
						|
                {
 | 
						|
                  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                  is.setstate(err|is.failbit);
 | 
						|
                  return is;
 | 
						|
                }
 | 
						|
 | 
						|
                //if (r > ((duration_values<common_type_t>::max)() / num))
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                if (chrono::detail::gt(r,((duration_values<common_type_t>::max)() / num)))
 | 
						|
                {
 | 
						|
                    // Conversion to Period overflowed
 | 
						|
                  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    is.setstate(err|is.failbit);
 | 
						|
                    return is;
 | 
						|
                }
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                common_type_t t = r * num;
 | 
						|
                t /= den;
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
 | 
						|
                if (t > duration_values<common_type_t>::zero())
 | 
						|
                {
 | 
						|
                  //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                  Rep pt = t;
 | 
						|
                  if ( (duration_values<Rep>::max)() < pt)
 | 
						|
                  {
 | 
						|
                    //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                    // Conversion to Period overflowed
 | 
						|
                    is.setstate(err|is.failbit);
 | 
						|
                    return is;
 | 
						|
                  }
 | 
						|
                }
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                // Success!  Store it.
 | 
						|
                r = Rep(t);
 | 
						|
                d = duration<Rep, Period>(r);
 | 
						|
                is.setstate(err);
 | 
						|
                //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                return is;
 | 
						|
            }
 | 
						|
            else {
 | 
						|
              //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
                is.setstate(is.failbit | is.eofbit);
 | 
						|
                return is;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
            if (i == e)
 | 
						|
              is.setstate(is.failbit|is.eofbit);
 | 
						|
            else
 | 
						|
              is.setstate(is.failbit);
 | 
						|
            //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
            return is;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
 | 
						|
        //is.setstate(is.failbit);
 | 
						|
      return is;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <class CharT, class Traits, class Clock, class Duration>
 | 
						|
std::basic_ostream<CharT, Traits>&
 | 
						|
operator<<(std::basic_ostream<CharT, Traits>& os,
 | 
						|
           const time_point<Clock, Duration>& tp)
 | 
						|
{
 | 
						|
    return os << tp.time_since_epoch() << clock_string<Clock, CharT>::since();
 | 
						|
}
 | 
						|
 | 
						|
template <class CharT, class Traits, class Clock, class Duration>
 | 
						|
std::basic_istream<CharT, Traits>&
 | 
						|
operator>>(std::basic_istream<CharT, Traits>& is,
 | 
						|
           time_point<Clock, Duration>& tp)
 | 
						|
{
 | 
						|
    Duration d;
 | 
						|
    is >> d;
 | 
						|
    if (is.good())
 | 
						|
    {
 | 
						|
        const std::basic_string<CharT> units=clock_string<Clock, CharT>::since();
 | 
						|
        std::ios_base::iostate err = std::ios_base::goodbit;
 | 
						|
        typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
 | 
						|
        in_iterator i(is);
 | 
						|
        in_iterator e;
 | 
						|
        std::ptrdiff_t k = chrono_detail::scan_keyword(i, e,
 | 
						|
                      &units, &units + 1,
 | 
						|
                      //~ std::use_facet<std::ctype<CharT> >(is.getloc()),
 | 
						|
                      err) - &units;
 | 
						|
        is.setstate(err);
 | 
						|
        if (k == 1)
 | 
						|
        {
 | 
						|
          is.setstate(err | is.failbit);
 | 
						|
            // failed to read epoch string
 | 
						|
            return is;
 | 
						|
        }
 | 
						|
        tp = time_point<Clock, Duration>(d);
 | 
						|
    }
 | 
						|
    else
 | 
						|
        is.setstate(is.failbit);
 | 
						|
    return is;
 | 
						|
}
 | 
						|
}  // chrono
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#endif  // BOOST_CHRONO_CHRONO_IO_HPP
 |