Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:48

0001 
0002 //  chrono_io
0003 //
0004 //  (C) Copyright Howard Hinnant
0005 //  (C) Copyright 2010 Vicente J. Botet Escriba
0006 //  Use, modification and distribution are subject to the Boost Software License,
0007 //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0008 //  http://www.boost.org/LICENSE_1_0.txt).
0009 //
0010 // This code was adapted by Vicente from Howard Hinnant's experimental work
0011 // on chrono i/o under lvm/libc++  to Boost
0012 
0013 #ifndef BOOST_CHRONO_IO_V1_CHRONO_IO_HPP
0014 #define BOOST_CHRONO_IO_V1_CHRONO_IO_HPP
0015 
0016 #include <boost/chrono/chrono.hpp>
0017 #include <boost/chrono/process_cpu_clocks.hpp>
0018 #include <boost/chrono/thread_clock.hpp>
0019 #include <boost/chrono/clock_string.hpp>
0020 #include <boost/ratio/ratio_io.hpp>
0021 #include <locale>
0022 #include <boost/type_traits/is_scalar.hpp>
0023 #include <boost/type_traits/is_signed.hpp>
0024 #include <boost/mpl/if.hpp>
0025 #include <boost/integer/common_factor_rt.hpp>
0026 #include <boost/chrono/detail/scan_keyword.hpp>
0027 #include <boost/core/enable_if.hpp>
0028 #include <boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp>
0029 
0030 namespace boost
0031 {
0032 
0033 namespace chrono
0034 {
0035 
0036 template <class CharT>
0037 class duration_punct
0038     : public std::locale::facet
0039 {
0040 public:
0041     typedef std::basic_string<CharT> string_type;
0042     enum {use_long, use_short};
0043 
0044 private:
0045     bool use_short_;
0046     string_type long_seconds_;
0047     string_type long_minutes_;
0048     string_type long_hours_;
0049     string_type short_seconds_;
0050     string_type short_minutes_;
0051     string_type short_hours_;
0052 
0053     template <class Period>
0054         string_type short_name(Period) const
0055             {return ::boost::ratio_string<Period, CharT>::symbol() + short_seconds_;}
0056 
0057     string_type short_name(ratio<1>) const    {return short_seconds_;}
0058     string_type short_name(ratio<60>) const   {return short_minutes_;}
0059     string_type short_name(ratio<3600>) const {return short_hours_;}
0060 
0061     template <class Period>
0062         string_type long_name(Period) const
0063             {return ::boost::ratio_string<Period, CharT>::prefix() + long_seconds_;}
0064 
0065     string_type long_name(ratio<1>) const    {return long_seconds_;}
0066     string_type long_name(ratio<60>) const   {return long_minutes_;}
0067     string_type long_name(ratio<3600>) const {return long_hours_;}
0068 
0069     void init_C();
0070 public:
0071     static std::locale::id id;
0072 
0073     explicit duration_punct(int use = use_long)
0074         : use_short_(use==use_short) {init_C();}
0075 
0076     duration_punct(int use,
0077         const string_type& long_seconds, const string_type& long_minutes,
0078         const string_type& long_hours, const string_type& short_seconds,
0079         const string_type& short_minutes, const string_type& short_hours);
0080 
0081     duration_punct(int use, const duration_punct& d);
0082 
0083     template <class Period>
0084         string_type short_name() const
0085             {return short_name(typename Period::type());}
0086 
0087     template <class Period>
0088         string_type long_name() const
0089             {return long_name(typename Period::type());}
0090 
0091     template <class Period>
0092         string_type plural() const
0093             {return long_name(typename Period::type());}
0094 
0095     template <class Period>
0096         string_type singular() const
0097     {
0098       return string_type(long_name(typename Period::type()), 0, long_name(typename Period::type()).size()-1);
0099     }
0100 
0101     template <class Period>
0102         string_type name() const
0103     {
0104       if (use_short_) return short_name<Period>();
0105       else {
0106         return long_name<Period>();
0107       }
0108     }
0109     template <class Period, class D>
0110       string_type name(D v) const
0111       {
0112         if (use_short_) return short_name<Period>();
0113         else
0114         {
0115           if (v==-1 || v==1)
0116             return singular<Period>();
0117           else
0118             return plural<Period>();
0119         }
0120       }
0121 
0122     bool is_short_name() const {return use_short_;}
0123     bool is_long_name() const {return !use_short_;}
0124 };
0125 
0126 template <class CharT>
0127 std::locale::id
0128 duration_punct<CharT>::id;
0129 
0130 template <class CharT>
0131 void
0132 duration_punct<CharT>::init_C()
0133 {
0134     short_seconds_ = CharT('s');
0135     short_minutes_ = CharT('m');
0136     short_hours_ = CharT('h');
0137     const CharT s[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
0138     const CharT m[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
0139     const CharT h[] = {'h', 'o', 'u', 'r', 's'};
0140     long_seconds_.assign(s, s + sizeof(s)/sizeof(s[0]));
0141     long_minutes_.assign(m, m + sizeof(m)/sizeof(m[0]));
0142     long_hours_.assign(h, h + sizeof(h)/sizeof(h[0]));
0143 }
0144 
0145 template <class CharT>
0146 duration_punct<CharT>::duration_punct(int use,
0147         const string_type& long_seconds, const string_type& long_minutes,
0148         const string_type& long_hours, const string_type& short_seconds,
0149         const string_type& short_minutes, const string_type& short_hours)
0150     : use_short_(use==use_short),
0151       long_seconds_(long_seconds),
0152       long_minutes_(long_minutes),
0153       long_hours_(long_hours),
0154       short_seconds_(short_seconds),
0155       short_minutes_(short_minutes),
0156       short_hours_(short_hours)
0157 {}
0158 
0159 template <class CharT>
0160 duration_punct<CharT>::duration_punct(int use, const duration_punct& d)
0161     : use_short_(use==use_short),
0162       long_seconds_(d.long_seconds_),
0163       long_minutes_(d.long_minutes_),
0164       long_hours_(d.long_hours_),
0165       short_seconds_(d.short_seconds_),
0166       short_minutes_(d.short_minutes_),
0167       short_hours_(d.short_hours_)
0168 {}
0169 
0170 template <class CharT, class Traits>
0171 std::basic_ostream<CharT, Traits>&
0172 duration_short(std::basic_ostream<CharT, Traits>& os)
0173 {
0174     typedef duration_punct<CharT> Facet;
0175     std::locale loc = os.getloc();
0176     if (std::has_facet<Facet>(loc))
0177     {
0178         const Facet& f = std::use_facet<Facet>(loc);
0179         if (f.is_long_name())
0180             os.imbue(std::locale(loc, new Facet(Facet::use_short, f)));
0181     }
0182     else
0183         os.imbue(std::locale(loc, new Facet(Facet::use_short)));
0184     return os;
0185 }
0186 
0187 template <class CharT, class Traits>
0188 std::basic_ostream<CharT, Traits>&
0189 duration_long(std::basic_ostream<CharT, Traits>& os)
0190 {
0191     typedef duration_punct<CharT> Facet;
0192     std::locale loc = os.getloc();
0193     if (std::has_facet<Facet>(loc))
0194     {
0195         const Facet& f = std::use_facet<Facet>(loc);
0196         if (f.is_short_name())
0197             os.imbue(std::locale(loc, new Facet(Facet::use_long, f)));
0198     }
0199     return os;
0200 }
0201 
0202 template <class CharT, class Traits, class Rep, class Period>
0203 std::basic_ostream<CharT, Traits>&
0204 operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d)
0205 {
0206     typedef duration_punct<CharT> Facet;
0207     std::locale loc = os.getloc();
0208     if (!std::has_facet<Facet>(loc))
0209         os.imbue(std::locale(loc, new Facet));
0210     const Facet& f = std::use_facet<Facet>(os.getloc());
0211     return os << d.count() << ' ' << f.template name<Period>(d.count());
0212 }
0213 
0214 namespace chrono_detail {
0215 template <class Rep, bool = is_scalar<Rep>::value>
0216 struct duration_io_intermediate
0217 {
0218     typedef Rep type;
0219 };
0220 
0221 template <class Rep>
0222 struct duration_io_intermediate<Rep, true>
0223 {
0224     typedef typename mpl::if_c
0225     <
0226         is_floating_point<Rep>::value,
0227             long double,
0228             typename mpl::if_c
0229             <
0230                 is_signed<Rep>::value,
0231                     long long,
0232                     unsigned long long
0233             >::type
0234     >::type type;
0235 };
0236 
0237 template <typename intermediate_type>
0238 typename enable_if<is_integral<intermediate_type>, bool>::type
0239 reduce(intermediate_type& r, unsigned long long& den, std::ios_base::iostate& err)
0240 {
0241   typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
0242 
0243     // Reduce r * num / den
0244   common_type_t t = integer::gcd<common_type_t>(common_type_t(r), common_type_t(den));
0245   r /= t;
0246   den /= t;
0247   if (den != 1)
0248   {
0249     // Conversion to Period is integral and not exact
0250     err |= std::ios_base::failbit;
0251     return false;
0252   }
0253   return true;
0254 }
0255 template <typename intermediate_type>
0256 typename disable_if<is_integral<intermediate_type>, bool>::type
0257 reduce(intermediate_type& , unsigned long long& , std::ios_base::iostate& )
0258 {
0259   return true;
0260 }
0261 
0262 }
0263 
0264 template <class CharT, class Traits, class Rep, class Period>
0265 std::basic_istream<CharT, Traits>&
0266 operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d)
0267 {
0268   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0269     typedef duration_punct<CharT> Facet;
0270     std::locale loc = is.getloc();
0271     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0272     if (!std::has_facet<Facet>(loc)) {
0273       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0274         is.imbue(std::locale(loc, new Facet));
0275     }
0276     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0277     loc = is.getloc();
0278     const Facet& f = std::use_facet<Facet>(loc);
0279     typedef typename chrono_detail::duration_io_intermediate<Rep>::type intermediate_type;
0280     intermediate_type r;
0281     std::ios_base::iostate err = std::ios_base::goodbit;
0282     // read value into r
0283     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0284     is >> r;
0285     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0286     if (is.good())
0287     {
0288       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0289         // now determine unit
0290         typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
0291         in_iterator i(is);
0292         in_iterator e;
0293         //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0294         if (i != e && *i == ' ')  // mandatory ' ' after value
0295         {
0296           //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0297             ++i;
0298             if (i != e)
0299             {
0300               //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0301                 // unit is num / den (yet to be determined)
0302                 unsigned long long num = 0;
0303                 unsigned long long den = 0;
0304                 if (*i == '[')
0305                 {
0306                   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0307                     // parse [N/D]s or [N/D]seconds format
0308                     ++i;
0309                     CharT x;
0310                     is >> num >> x >> den;
0311                     if (!is.good() || (x != '/'))
0312                     {
0313                       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0314                         is.setstate(is.failbit);
0315                         return is;
0316                     }
0317                     i = in_iterator(is);
0318                     if (*i != ']')
0319                     {
0320                       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0321                         is.setstate(is.failbit);
0322                         return is;
0323                     }
0324                     ++i;
0325                     const std::basic_string<CharT> units[] =
0326                     {
0327                         f.template singular<ratio<1> >(),
0328                         f.template plural<ratio<1> >(),
0329                         f.template short_name<ratio<1> >()
0330                     };
0331                     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0332                     const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
0333                                   units, units + sizeof(units)/sizeof(units[0]),
0334                                   //~ std::use_facet<std::ctype<CharT> >(loc),
0335                                   err);
0336                     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0337                     is.setstate(err);
0338                     switch ((k - units) / 3)
0339                     {
0340                     case 0:
0341                       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0342                         break;
0343                     default:
0344                         is.setstate(err);
0345                         //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0346                         return is;
0347                     }
0348                 }
0349                 else
0350                 {
0351                   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0352                     // parse SI name, short or long
0353                     const std::basic_string<CharT> units[] =
0354                     {
0355                         f.template singular<atto>(),
0356                         f.template plural<atto>(),
0357                         f.template short_name<atto>(),
0358                         f.template singular<femto>(),
0359                         f.template plural<femto>(),
0360                         f.template short_name<femto>(),
0361                         f.template singular<pico>(),
0362                         f.template plural<pico>(),
0363                         f.template short_name<pico>(),
0364                         f.template singular<nano>(),
0365                         f.template plural<nano>(),
0366                         f.template short_name<nano>(),
0367                         f.template singular<micro>(),
0368                         f.template plural<micro>(),
0369                         f.template short_name<micro>(),
0370                         f.template singular<milli>(),
0371                         f.template plural<milli>(),
0372                         f.template short_name<milli>(),
0373                         f.template singular<centi>(),
0374                         f.template plural<centi>(),
0375                         f.template short_name<centi>(),
0376                         f.template singular<deci>(),
0377                         f.template plural<deci>(),
0378                         f.template short_name<deci>(),
0379                         f.template singular<deca>(),
0380                         f.template plural<deca>(),
0381                         f.template short_name<deca>(),
0382                         f.template singular<hecto>(),
0383                         f.template plural<hecto>(),
0384                         f.template short_name<hecto>(),
0385                         f.template singular<kilo>(),
0386                         f.template plural<kilo>(),
0387                         f.template short_name<kilo>(),
0388                         f.template singular<mega>(),
0389                         f.template plural<mega>(),
0390                         f.template short_name<mega>(),
0391                         f.template singular<giga>(),
0392                         f.template plural<giga>(),
0393                         f.template short_name<giga>(),
0394                         f.template singular<tera>(),
0395                         f.template plural<tera>(),
0396                         f.template short_name<tera>(),
0397                         f.template singular<peta>(),
0398                         f.template plural<peta>(),
0399                         f.template short_name<peta>(),
0400                         f.template singular<exa>(),
0401                         f.template plural<exa>(),
0402                         f.template short_name<exa>(),
0403                         f.template singular<ratio<1> >(),
0404                         f.template plural<ratio<1> >(),
0405                         f.template short_name<ratio<1> >(),
0406                         f.template singular<ratio<60> >(),
0407                         f.template plural<ratio<60> >(),
0408                         f.template short_name<ratio<60> >(),
0409                         f.template singular<ratio<3600> >(),
0410                         f.template plural<ratio<3600> >(),
0411                         f.template short_name<ratio<3600> >()
0412                     };
0413                     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0414                     const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
0415                                   units, units + sizeof(units)/sizeof(units[0]),
0416                                   //~ std::use_facet<std::ctype<CharT> >(loc),
0417                                   err);
0418                     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0419                     switch ((k - units) / 3)
0420                     {
0421                     case 0:
0422                         num = 1ULL;
0423                         den = 1000000000000000000ULL;
0424                         break;
0425                     case 1:
0426                         num = 1ULL;
0427                         den = 1000000000000000ULL;
0428                         break;
0429                     case 2:
0430                         num = 1ULL;
0431                         den = 1000000000000ULL;
0432                         break;
0433                     case 3:
0434                         num = 1ULL;
0435                         den = 1000000000ULL;
0436                         break;
0437                     case 4:
0438                         num = 1ULL;
0439                         den = 1000000ULL;
0440                         break;
0441                     case 5:
0442                         num = 1ULL;
0443                         den = 1000ULL;
0444                         break;
0445                     case 6:
0446                         num = 1ULL;
0447                         den = 100ULL;
0448                         break;
0449                     case 7:
0450                         num = 1ULL;
0451                         den = 10ULL;
0452                         break;
0453                     case 8:
0454                         num = 10ULL;
0455                         den = 1ULL;
0456                         break;
0457                     case 9:
0458                         num = 100ULL;
0459                         den = 1ULL;
0460                         break;
0461                     case 10:
0462                         num = 1000ULL;
0463                         den = 1ULL;
0464                         break;
0465                     case 11:
0466                         num = 1000000ULL;
0467                         den = 1ULL;
0468                         break;
0469                     case 12:
0470                         num = 1000000000ULL;
0471                         den = 1ULL;
0472                         break;
0473                     case 13:
0474                         num = 1000000000000ULL;
0475                         den = 1ULL;
0476                         break;
0477                     case 14:
0478                         num = 1000000000000000ULL;
0479                         den = 1ULL;
0480                         break;
0481                     case 15:
0482                         num = 1000000000000000000ULL;
0483                         den = 1ULL;
0484                         break;
0485                     case 16:
0486                         num = 1;
0487                         den = 1;
0488                         break;
0489                     case 17:
0490                         num = 60;
0491                         den = 1;
0492                         break;
0493                     case 18:
0494                         num = 3600;
0495                         den = 1;
0496                         break;
0497                     default:
0498                       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0499                         is.setstate(err|is.failbit);
0500                         return is;
0501                     }
0502                 }
0503                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0504                 // unit is num/den
0505                 // r should be multiplied by (num/den) / Period
0506                 // Reduce (num/den) / Period to lowest terms
0507                 unsigned long long gcd_n1_n2 = integer::gcd<unsigned long long>(num, Period::num);
0508                 unsigned long long gcd_d1_d2 = integer::gcd<unsigned long long>(den, Period::den);
0509                 num /= gcd_n1_n2;
0510                 den /= gcd_d1_d2;
0511                 unsigned long long n2 = Period::num / gcd_n1_n2;
0512                 unsigned long long d2 = Period::den / gcd_d1_d2;
0513                 if (num > (std::numeric_limits<unsigned long long>::max)() / d2 ||
0514                     den > (std::numeric_limits<unsigned long long>::max)() / n2)
0515                 {
0516                   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0517                     // (num/den) / Period overflows
0518                     is.setstate(err|is.failbit);
0519                     return is;
0520                 }
0521                 num *= d2;
0522                 den *= n2;
0523 
0524                 typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
0525 
0526                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0527                 // num / den is now factor to multiply by r
0528                 if (!chrono_detail::reduce(r, den, err))
0529                 {
0530                   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0531                   is.setstate(err|is.failbit);
0532                   return is;
0533                 }
0534 
0535                 //if (r > ((duration_values<common_type_t>::max)() / num))
0536                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0537                 if (chrono::detail::gt(r,((duration_values<common_type_t>::max)() / num)))
0538                 {
0539                     // Conversion to Period overflowed
0540                   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0541                     is.setstate(err|is.failbit);
0542                     return is;
0543                 }
0544                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0545                 common_type_t t = r * num;
0546                 t /= den;
0547                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0548 
0549                 if (t > duration_values<common_type_t>::zero())
0550                 {
0551                   //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0552                   if ( (duration_values<Rep>::max)() < Rep(t))
0553                   {
0554                     //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0555                     // Conversion to Period overflowed
0556                     is.setstate(err|is.failbit);
0557                     return is;
0558                   }
0559                 }
0560                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0561                 // Success!  Store it.
0562                 d = duration<Rep, Period>(Rep(t));
0563                 is.setstate(err);
0564                 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0565                 return is;
0566             }
0567             else {
0568               //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0569                 is.setstate(is.failbit | is.eofbit);
0570                 return is;
0571             }
0572         }
0573         else
0574         {
0575           //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0576             if (i == e)
0577               is.setstate(is.failbit|is.eofbit);
0578             else
0579               is.setstate(is.failbit);
0580             //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0581             return is;
0582         }
0583     }
0584     else {
0585       //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
0586         //is.setstate(is.failbit);
0587       return is;
0588     }
0589 }
0590 
0591 
0592 template <class CharT, class Traits, class Clock, class Duration>
0593 std::basic_ostream<CharT, Traits>&
0594 operator<<(std::basic_ostream<CharT, Traits>& os,
0595            const time_point<Clock, Duration>& tp)
0596 {
0597     return os << tp.time_since_epoch() << clock_string<Clock, CharT>::since();
0598 }
0599 
0600 template <class CharT, class Traits, class Clock, class Duration>
0601 std::basic_istream<CharT, Traits>&
0602 operator>>(std::basic_istream<CharT, Traits>& is,
0603            time_point<Clock, Duration>& tp)
0604 {
0605     Duration d;
0606     is >> d;
0607     if (is.good())
0608     {
0609         const std::basic_string<CharT> units=clock_string<Clock, CharT>::since();
0610         std::ios_base::iostate err = std::ios_base::goodbit;
0611         typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
0612         in_iterator i(is);
0613         in_iterator e;
0614         std::ptrdiff_t k = chrono_detail::scan_keyword(i, e,
0615                       &units, &units + 1,
0616                       //~ std::use_facet<std::ctype<CharT> >(is.getloc()),
0617                       err) - &units;
0618         is.setstate(err);
0619         if (k == 1)
0620         {
0621           is.setstate(err | is.failbit);
0622             // failed to read epoch string
0623             return is;
0624         }
0625         tp = time_point<Clock, Duration>(d);
0626     }
0627     else
0628         is.setstate(is.failbit);
0629     return is;
0630 }
0631 }  // chrono
0632 
0633 }
0634 
0635 #endif  // BOOST_CHRONO_CHRONO_IO_HPP