File indexing completed on 2025-01-18 09:29:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
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
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
0269 typedef duration_punct<CharT> Facet;
0270 std::locale loc = is.getloc();
0271
0272 if (!std::has_facet<Facet>(loc)) {
0273
0274 is.imbue(std::locale(loc, new Facet));
0275 }
0276
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
0283
0284 is >> r;
0285
0286 if (is.good())
0287 {
0288
0289
0290 typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
0291 in_iterator i(is);
0292 in_iterator e;
0293
0294 if (i != e && *i == ' ')
0295 {
0296
0297 ++i;
0298 if (i != e)
0299 {
0300
0301
0302 unsigned long long num = 0;
0303 unsigned long long den = 0;
0304 if (*i == '[')
0305 {
0306
0307
0308 ++i;
0309 CharT x;
0310 is >> num >> x >> den;
0311 if (!is.good() || (x != '/'))
0312 {
0313
0314 is.setstate(is.failbit);
0315 return is;
0316 }
0317 i = in_iterator(is);
0318 if (*i != ']')
0319 {
0320
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
0332 const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
0333 units, units + sizeof(units)/sizeof(units[0]),
0334
0335 err);
0336
0337 is.setstate(err);
0338 switch ((k - units) / 3)
0339 {
0340 case 0:
0341
0342 break;
0343 default:
0344 is.setstate(err);
0345
0346 return is;
0347 }
0348 }
0349 else
0350 {
0351
0352
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
0414 const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
0415 units, units + sizeof(units)/sizeof(units[0]),
0416
0417 err);
0418
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
0499 is.setstate(err|is.failbit);
0500 return is;
0501 }
0502 }
0503
0504
0505
0506
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
0517
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
0527
0528 if (!chrono_detail::reduce(r, den, err))
0529 {
0530
0531 is.setstate(err|is.failbit);
0532 return is;
0533 }
0534
0535
0536
0537 if (chrono::detail::gt(r,((duration_values<common_type_t>::max)() / num)))
0538 {
0539
0540
0541 is.setstate(err|is.failbit);
0542 return is;
0543 }
0544
0545 common_type_t t = r * num;
0546 t /= den;
0547
0548
0549 if (t > duration_values<common_type_t>::zero())
0550 {
0551
0552 if ( (duration_values<Rep>::max)() < Rep(t))
0553 {
0554
0555
0556 is.setstate(err|is.failbit);
0557 return is;
0558 }
0559 }
0560
0561
0562 d = duration<Rep, Period>(Rep(t));
0563 is.setstate(err);
0564
0565 return is;
0566 }
0567 else {
0568
0569 is.setstate(is.failbit | is.eofbit);
0570 return is;
0571 }
0572 }
0573 else
0574 {
0575
0576 if (i == e)
0577 is.setstate(is.failbit|is.eofbit);
0578 else
0579 is.setstate(is.failbit);
0580
0581 return is;
0582 }
0583 }
0584 else {
0585
0586
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
0617 err) - &units;
0618 is.setstate(err);
0619 if (k == 1)
0620 {
0621 is.setstate(err | is.failbit);
0622
0623 return is;
0624 }
0625 tp = time_point<Clock, Duration>(d);
0626 }
0627 else
0628 is.setstate(is.failbit);
0629 return is;
0630 }
0631 }
0632
0633 }
0634
0635 #endif