annotate DEPENDENCIES/generic/include/boost/chrono/io_v1/chrono_io.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1
Chris@16 2 // chrono_io
Chris@16 3 //
Chris@16 4 // (C) Copyright Howard Hinnant
Chris@16 5 // (C) Copyright 2010 Vicente J. Botet Escriba
Chris@16 6 // Use, modification and distribution are subject to the Boost Software License,
Chris@16 7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 8 // http://www.boost.org/LICENSE_1_0.txt).
Chris@16 9 //
Chris@16 10 // This code was adapted by Vicente from Howard Hinnant's experimental work
Chris@16 11 // on chrono i/o under lvm/libc++ to Boost
Chris@16 12
Chris@16 13 #ifndef BOOST_CHRONO_IO_V1_CHRONO_IO_HPP
Chris@16 14 #define BOOST_CHRONO_IO_V1_CHRONO_IO_HPP
Chris@16 15
Chris@16 16 #include <boost/chrono/chrono.hpp>
Chris@16 17 #include <boost/chrono/process_cpu_clocks.hpp>
Chris@16 18 #include <boost/chrono/thread_clock.hpp>
Chris@16 19 #include <boost/chrono/clock_string.hpp>
Chris@16 20 #include <boost/ratio/ratio_io.hpp>
Chris@16 21 #include <locale>
Chris@16 22 #include <boost/type_traits/is_scalar.hpp>
Chris@16 23 #include <boost/type_traits/is_signed.hpp>
Chris@16 24 #include <boost/mpl/if.hpp>
Chris@101 25 #include <boost/integer/common_factor_rt.hpp>
Chris@16 26 #include <boost/chrono/detail/scan_keyword.hpp>
Chris@16 27 #include <boost/utility/enable_if.hpp>
Chris@16 28 #include <boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp>
Chris@16 29
Chris@16 30 namespace boost
Chris@16 31 {
Chris@16 32
Chris@16 33 namespace chrono
Chris@16 34 {
Chris@16 35
Chris@16 36 template <class CharT>
Chris@16 37 class duration_punct
Chris@16 38 : public std::locale::facet
Chris@16 39 {
Chris@16 40 public:
Chris@16 41 typedef std::basic_string<CharT> string_type;
Chris@16 42 enum {use_long, use_short};
Chris@16 43
Chris@16 44 private:
Chris@16 45 bool use_short_;
Chris@16 46 string_type long_seconds_;
Chris@16 47 string_type long_minutes_;
Chris@16 48 string_type long_hours_;
Chris@16 49 string_type short_seconds_;
Chris@16 50 string_type short_minutes_;
Chris@16 51 string_type short_hours_;
Chris@16 52
Chris@16 53 template <class Period>
Chris@16 54 string_type short_name(Period) const
Chris@16 55 {return ::boost::ratio_string<Period, CharT>::short_name() + short_seconds_;}
Chris@16 56
Chris@16 57 string_type short_name(ratio<1>) const {return short_seconds_;}
Chris@16 58 string_type short_name(ratio<60>) const {return short_minutes_;}
Chris@16 59 string_type short_name(ratio<3600>) const {return short_hours_;}
Chris@16 60
Chris@16 61 template <class Period>
Chris@16 62 string_type long_name(Period) const
Chris@16 63 {return ::boost::ratio_string<Period, CharT>::long_name() + long_seconds_;}
Chris@16 64
Chris@16 65 string_type long_name(ratio<1>) const {return long_seconds_;}
Chris@16 66 string_type long_name(ratio<60>) const {return long_minutes_;}
Chris@16 67 string_type long_name(ratio<3600>) const {return long_hours_;}
Chris@16 68
Chris@16 69 void init_C();
Chris@16 70 public:
Chris@16 71 static std::locale::id id;
Chris@16 72
Chris@16 73 explicit duration_punct(int use = use_long)
Chris@16 74 : use_short_(use==use_short) {init_C();}
Chris@16 75
Chris@16 76 duration_punct(int use,
Chris@16 77 const string_type& long_seconds, const string_type& long_minutes,
Chris@16 78 const string_type& long_hours, const string_type& short_seconds,
Chris@16 79 const string_type& short_minutes, const string_type& short_hours);
Chris@16 80
Chris@16 81 duration_punct(int use, const duration_punct& d);
Chris@16 82
Chris@16 83 template <class Period>
Chris@16 84 string_type short_name() const
Chris@16 85 {return short_name(typename Period::type());}
Chris@16 86
Chris@16 87 template <class Period>
Chris@16 88 string_type long_name() const
Chris@16 89 {return long_name(typename Period::type());}
Chris@16 90
Chris@16 91 template <class Period>
Chris@16 92 string_type plural() const
Chris@16 93 {return long_name(typename Period::type());}
Chris@16 94
Chris@16 95 template <class Period>
Chris@16 96 string_type singular() const
Chris@16 97 {
Chris@16 98 return string_type(long_name(typename Period::type()), 0, long_name(typename Period::type()).size()-1);
Chris@16 99 }
Chris@16 100
Chris@16 101 template <class Period>
Chris@16 102 string_type name() const
Chris@16 103 {
Chris@16 104 if (use_short_) return short_name<Period>();
Chris@16 105 else {
Chris@16 106 return long_name<Period>();
Chris@16 107 }
Chris@16 108 }
Chris@16 109 template <class Period, class D>
Chris@16 110 string_type name(D v) const
Chris@16 111 {
Chris@16 112 if (use_short_) return short_name<Period>();
Chris@16 113 else
Chris@16 114 {
Chris@16 115 if (v==-1 || v==1)
Chris@16 116 return singular<Period>();
Chris@16 117 else
Chris@16 118 return plural<Period>();
Chris@16 119 }
Chris@16 120 }
Chris@16 121
Chris@16 122 bool is_short_name() const {return use_short_;}
Chris@16 123 bool is_long_name() const {return !use_short_;}
Chris@16 124 };
Chris@16 125
Chris@16 126 template <class CharT>
Chris@16 127 std::locale::id
Chris@16 128 duration_punct<CharT>::id;
Chris@16 129
Chris@16 130 template <class CharT>
Chris@16 131 void
Chris@16 132 duration_punct<CharT>::init_C()
Chris@16 133 {
Chris@16 134 short_seconds_ = CharT('s');
Chris@16 135 short_minutes_ = CharT('m');
Chris@16 136 short_hours_ = CharT('h');
Chris@16 137 const CharT s[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
Chris@16 138 const CharT m[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
Chris@16 139 const CharT h[] = {'h', 'o', 'u', 'r', 's'};
Chris@16 140 long_seconds_.assign(s, s + sizeof(s)/sizeof(s[0]));
Chris@16 141 long_minutes_.assign(m, m + sizeof(m)/sizeof(m[0]));
Chris@16 142 long_hours_.assign(h, h + sizeof(h)/sizeof(h[0]));
Chris@16 143 }
Chris@16 144
Chris@16 145 template <class CharT>
Chris@16 146 duration_punct<CharT>::duration_punct(int use,
Chris@16 147 const string_type& long_seconds, const string_type& long_minutes,
Chris@16 148 const string_type& long_hours, const string_type& short_seconds,
Chris@16 149 const string_type& short_minutes, const string_type& short_hours)
Chris@16 150 : use_short_(use==use_short),
Chris@16 151 long_seconds_(long_seconds),
Chris@16 152 long_minutes_(long_minutes),
Chris@16 153 long_hours_(long_hours),
Chris@16 154 short_seconds_(short_seconds),
Chris@16 155 short_minutes_(short_minutes),
Chris@16 156 short_hours_(short_hours)
Chris@16 157 {}
Chris@16 158
Chris@16 159 template <class CharT>
Chris@16 160 duration_punct<CharT>::duration_punct(int use, const duration_punct& d)
Chris@16 161 : use_short_(use==use_short),
Chris@16 162 long_seconds_(d.long_seconds_),
Chris@16 163 long_minutes_(d.long_minutes_),
Chris@16 164 long_hours_(d.long_hours_),
Chris@16 165 short_seconds_(d.short_seconds_),
Chris@16 166 short_minutes_(d.short_minutes_),
Chris@16 167 short_hours_(d.short_hours_)
Chris@16 168 {}
Chris@16 169
Chris@16 170 template <class CharT, class Traits>
Chris@16 171 std::basic_ostream<CharT, Traits>&
Chris@16 172 duration_short(std::basic_ostream<CharT, Traits>& os)
Chris@16 173 {
Chris@16 174 typedef duration_punct<CharT> Facet;
Chris@16 175 std::locale loc = os.getloc();
Chris@16 176 if (std::has_facet<Facet>(loc))
Chris@16 177 {
Chris@16 178 const Facet& f = std::use_facet<Facet>(loc);
Chris@16 179 if (f.is_long_name())
Chris@16 180 os.imbue(std::locale(loc, new Facet(Facet::use_short, f)));
Chris@16 181 }
Chris@16 182 else
Chris@16 183 os.imbue(std::locale(loc, new Facet(Facet::use_short)));
Chris@16 184 return os;
Chris@16 185 }
Chris@16 186
Chris@16 187 template <class CharT, class Traits>
Chris@16 188 std::basic_ostream<CharT, Traits>&
Chris@16 189 duration_long(std::basic_ostream<CharT, Traits>& os)
Chris@16 190 {
Chris@16 191 typedef duration_punct<CharT> Facet;
Chris@16 192 std::locale loc = os.getloc();
Chris@16 193 if (std::has_facet<Facet>(loc))
Chris@16 194 {
Chris@16 195 const Facet& f = std::use_facet<Facet>(loc);
Chris@16 196 if (f.is_short_name())
Chris@16 197 os.imbue(std::locale(loc, new Facet(Facet::use_long, f)));
Chris@16 198 }
Chris@16 199 return os;
Chris@16 200 }
Chris@16 201
Chris@16 202 template <class CharT, class Traits, class Rep, class Period>
Chris@16 203 std::basic_ostream<CharT, Traits>&
Chris@16 204 operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d)
Chris@16 205 {
Chris@16 206 typedef duration_punct<CharT> Facet;
Chris@16 207 std::locale loc = os.getloc();
Chris@16 208 if (!std::has_facet<Facet>(loc))
Chris@16 209 os.imbue(std::locale(loc, new Facet));
Chris@16 210 const Facet& f = std::use_facet<Facet>(os.getloc());
Chris@16 211 return os << d.count() << ' ' << f.template name<Period>(d.count());
Chris@16 212 }
Chris@16 213
Chris@16 214 namespace chrono_detail {
Chris@16 215 template <class Rep, bool = is_scalar<Rep>::value>
Chris@16 216 struct duration_io_intermediate
Chris@16 217 {
Chris@16 218 typedef Rep type;
Chris@16 219 };
Chris@16 220
Chris@16 221 template <class Rep>
Chris@16 222 struct duration_io_intermediate<Rep, true>
Chris@16 223 {
Chris@16 224 typedef typename mpl::if_c
Chris@16 225 <
Chris@16 226 is_floating_point<Rep>::value,
Chris@16 227 long double,
Chris@16 228 typename mpl::if_c
Chris@16 229 <
Chris@16 230 is_signed<Rep>::value,
Chris@16 231 long long,
Chris@16 232 unsigned long long
Chris@16 233 >::type
Chris@16 234 >::type type;
Chris@16 235 };
Chris@16 236
Chris@16 237 template <typename intermediate_type>
Chris@16 238 typename enable_if<is_integral<intermediate_type>, bool>::type
Chris@16 239 reduce(intermediate_type& r, unsigned long long& den, std::ios_base::iostate& err)
Chris@16 240 {
Chris@16 241 typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
Chris@16 242
Chris@16 243 // Reduce r * num / den
Chris@101 244 common_type_t t = integer::gcd<common_type_t>(common_type_t(r), common_type_t(den));
Chris@16 245 r /= t;
Chris@16 246 den /= t;
Chris@16 247 if (den != 1)
Chris@16 248 {
Chris@16 249 // Conversion to Period is integral and not exact
Chris@16 250 err |= std::ios_base::failbit;
Chris@16 251 return false;
Chris@16 252 }
Chris@16 253 return true;
Chris@16 254 }
Chris@16 255 template <typename intermediate_type>
Chris@16 256 typename disable_if<is_integral<intermediate_type>, bool>::type
Chris@16 257 reduce(intermediate_type& , unsigned long long& , std::ios_base::iostate& )
Chris@16 258 {
Chris@16 259 return true;
Chris@16 260 }
Chris@16 261
Chris@16 262 }
Chris@16 263
Chris@16 264 template <class CharT, class Traits, class Rep, class Period>
Chris@16 265 std::basic_istream<CharT, Traits>&
Chris@16 266 operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d)
Chris@16 267 {
Chris@16 268 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 269 typedef duration_punct<CharT> Facet;
Chris@16 270 std::locale loc = is.getloc();
Chris@16 271 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 272 if (!std::has_facet<Facet>(loc)) {
Chris@16 273 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 274 is.imbue(std::locale(loc, new Facet));
Chris@16 275 }
Chris@16 276 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 277 loc = is.getloc();
Chris@16 278 const Facet& f = std::use_facet<Facet>(loc);
Chris@16 279 typedef typename chrono_detail::duration_io_intermediate<Rep>::type intermediate_type;
Chris@16 280 intermediate_type r;
Chris@16 281 std::ios_base::iostate err = std::ios_base::goodbit;
Chris@16 282 // read value into r
Chris@16 283 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 284 is >> r;
Chris@16 285 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 286 if (is.good())
Chris@16 287 {
Chris@16 288 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 289 // now determine unit
Chris@16 290 typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
Chris@16 291 in_iterator i(is);
Chris@16 292 in_iterator e;
Chris@16 293 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 294 if (i != e && *i == ' ') // mandatory ' ' after value
Chris@16 295 {
Chris@16 296 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 297 ++i;
Chris@16 298 if (i != e)
Chris@16 299 {
Chris@16 300 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 301 // unit is num / den (yet to be determined)
Chris@16 302 unsigned long long num = 0;
Chris@16 303 unsigned long long den = 0;
Chris@16 304 if (*i == '[')
Chris@16 305 {
Chris@16 306 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 307 // parse [N/D]s or [N/D]seconds format
Chris@16 308 ++i;
Chris@16 309 CharT x;
Chris@16 310 is >> num >> x >> den;
Chris@16 311 if (!is.good() || (x != '/'))
Chris@16 312 {
Chris@16 313 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 314 is.setstate(is.failbit);
Chris@16 315 return is;
Chris@16 316 }
Chris@16 317 i = in_iterator(is);
Chris@16 318 if (*i != ']')
Chris@16 319 {
Chris@16 320 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 321 is.setstate(is.failbit);
Chris@16 322 return is;
Chris@16 323 }
Chris@16 324 ++i;
Chris@16 325 const std::basic_string<CharT> units[] =
Chris@16 326 {
Chris@16 327 f.template singular<ratio<1> >(),
Chris@16 328 f.template plural<ratio<1> >(),
Chris@16 329 f.template short_name<ratio<1> >()
Chris@16 330 };
Chris@16 331 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 332 const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
Chris@16 333 units, units + sizeof(units)/sizeof(units[0]),
Chris@16 334 //~ std::use_facet<std::ctype<CharT> >(loc),
Chris@16 335 err);
Chris@16 336 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 337 is.setstate(err);
Chris@16 338 switch ((k - units) / 3)
Chris@16 339 {
Chris@16 340 case 0:
Chris@16 341 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 342 break;
Chris@16 343 default:
Chris@16 344 is.setstate(err);
Chris@16 345 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 346 return is;
Chris@16 347 }
Chris@16 348 }
Chris@16 349 else
Chris@16 350 {
Chris@16 351 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 352 // parse SI name, short or long
Chris@16 353 const std::basic_string<CharT> units[] =
Chris@16 354 {
Chris@16 355 f.template singular<atto>(),
Chris@16 356 f.template plural<atto>(),
Chris@16 357 f.template short_name<atto>(),
Chris@16 358 f.template singular<femto>(),
Chris@16 359 f.template plural<femto>(),
Chris@16 360 f.template short_name<femto>(),
Chris@16 361 f.template singular<pico>(),
Chris@16 362 f.template plural<pico>(),
Chris@16 363 f.template short_name<pico>(),
Chris@16 364 f.template singular<nano>(),
Chris@16 365 f.template plural<nano>(),
Chris@16 366 f.template short_name<nano>(),
Chris@16 367 f.template singular<micro>(),
Chris@16 368 f.template plural<micro>(),
Chris@16 369 f.template short_name<micro>(),
Chris@16 370 f.template singular<milli>(),
Chris@16 371 f.template plural<milli>(),
Chris@16 372 f.template short_name<milli>(),
Chris@16 373 f.template singular<centi>(),
Chris@16 374 f.template plural<centi>(),
Chris@16 375 f.template short_name<centi>(),
Chris@16 376 f.template singular<deci>(),
Chris@16 377 f.template plural<deci>(),
Chris@16 378 f.template short_name<deci>(),
Chris@16 379 f.template singular<deca>(),
Chris@16 380 f.template plural<deca>(),
Chris@16 381 f.template short_name<deca>(),
Chris@16 382 f.template singular<hecto>(),
Chris@16 383 f.template plural<hecto>(),
Chris@16 384 f.template short_name<hecto>(),
Chris@16 385 f.template singular<kilo>(),
Chris@16 386 f.template plural<kilo>(),
Chris@16 387 f.template short_name<kilo>(),
Chris@16 388 f.template singular<mega>(),
Chris@16 389 f.template plural<mega>(),
Chris@16 390 f.template short_name<mega>(),
Chris@16 391 f.template singular<giga>(),
Chris@16 392 f.template plural<giga>(),
Chris@16 393 f.template short_name<giga>(),
Chris@16 394 f.template singular<tera>(),
Chris@16 395 f.template plural<tera>(),
Chris@16 396 f.template short_name<tera>(),
Chris@16 397 f.template singular<peta>(),
Chris@16 398 f.template plural<peta>(),
Chris@16 399 f.template short_name<peta>(),
Chris@16 400 f.template singular<exa>(),
Chris@16 401 f.template plural<exa>(),
Chris@16 402 f.template short_name<exa>(),
Chris@16 403 f.template singular<ratio<1> >(),
Chris@16 404 f.template plural<ratio<1> >(),
Chris@16 405 f.template short_name<ratio<1> >(),
Chris@16 406 f.template singular<ratio<60> >(),
Chris@16 407 f.template plural<ratio<60> >(),
Chris@16 408 f.template short_name<ratio<60> >(),
Chris@16 409 f.template singular<ratio<3600> >(),
Chris@16 410 f.template plural<ratio<3600> >(),
Chris@16 411 f.template short_name<ratio<3600> >()
Chris@16 412 };
Chris@16 413 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 414 const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
Chris@16 415 units, units + sizeof(units)/sizeof(units[0]),
Chris@16 416 //~ std::use_facet<std::ctype<CharT> >(loc),
Chris@16 417 err);
Chris@16 418 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 419 switch ((k - units) / 3)
Chris@16 420 {
Chris@16 421 case 0:
Chris@16 422 num = 1ULL;
Chris@16 423 den = 1000000000000000000ULL;
Chris@16 424 break;
Chris@16 425 case 1:
Chris@16 426 num = 1ULL;
Chris@16 427 den = 1000000000000000ULL;
Chris@16 428 break;
Chris@16 429 case 2:
Chris@16 430 num = 1ULL;
Chris@16 431 den = 1000000000000ULL;
Chris@16 432 break;
Chris@16 433 case 3:
Chris@16 434 num = 1ULL;
Chris@16 435 den = 1000000000ULL;
Chris@16 436 break;
Chris@16 437 case 4:
Chris@16 438 num = 1ULL;
Chris@16 439 den = 1000000ULL;
Chris@16 440 break;
Chris@16 441 case 5:
Chris@16 442 num = 1ULL;
Chris@16 443 den = 1000ULL;
Chris@16 444 break;
Chris@16 445 case 6:
Chris@16 446 num = 1ULL;
Chris@16 447 den = 100ULL;
Chris@16 448 break;
Chris@16 449 case 7:
Chris@16 450 num = 1ULL;
Chris@16 451 den = 10ULL;
Chris@16 452 break;
Chris@16 453 case 8:
Chris@16 454 num = 10ULL;
Chris@16 455 den = 1ULL;
Chris@16 456 break;
Chris@16 457 case 9:
Chris@16 458 num = 100ULL;
Chris@16 459 den = 1ULL;
Chris@16 460 break;
Chris@16 461 case 10:
Chris@16 462 num = 1000ULL;
Chris@16 463 den = 1ULL;
Chris@16 464 break;
Chris@16 465 case 11:
Chris@16 466 num = 1000000ULL;
Chris@16 467 den = 1ULL;
Chris@16 468 break;
Chris@16 469 case 12:
Chris@16 470 num = 1000000000ULL;
Chris@16 471 den = 1ULL;
Chris@16 472 break;
Chris@16 473 case 13:
Chris@16 474 num = 1000000000000ULL;
Chris@16 475 den = 1ULL;
Chris@16 476 break;
Chris@16 477 case 14:
Chris@16 478 num = 1000000000000000ULL;
Chris@16 479 den = 1ULL;
Chris@16 480 break;
Chris@16 481 case 15:
Chris@16 482 num = 1000000000000000000ULL;
Chris@16 483 den = 1ULL;
Chris@16 484 break;
Chris@16 485 case 16:
Chris@16 486 num = 1;
Chris@16 487 den = 1;
Chris@16 488 break;
Chris@16 489 case 17:
Chris@16 490 num = 60;
Chris@16 491 den = 1;
Chris@16 492 break;
Chris@16 493 case 18:
Chris@16 494 num = 3600;
Chris@16 495 den = 1;
Chris@16 496 break;
Chris@16 497 default:
Chris@16 498 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 499 is.setstate(err|is.failbit);
Chris@16 500 return is;
Chris@16 501 }
Chris@16 502 }
Chris@16 503 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 504 // unit is num/den
Chris@16 505 // r should be multiplied by (num/den) / Period
Chris@16 506 // Reduce (num/den) / Period to lowest terms
Chris@101 507 unsigned long long gcd_n1_n2 = integer::gcd<unsigned long long>(num, Period::num);
Chris@101 508 unsigned long long gcd_d1_d2 = integer::gcd<unsigned long long>(den, Period::den);
Chris@16 509 num /= gcd_n1_n2;
Chris@16 510 den /= gcd_d1_d2;
Chris@16 511 unsigned long long n2 = Period::num / gcd_n1_n2;
Chris@16 512 unsigned long long d2 = Period::den / gcd_d1_d2;
Chris@16 513 if (num > (std::numeric_limits<unsigned long long>::max)() / d2 ||
Chris@16 514 den > (std::numeric_limits<unsigned long long>::max)() / n2)
Chris@16 515 {
Chris@16 516 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 517 // (num/den) / Period overflows
Chris@16 518 is.setstate(err|is.failbit);
Chris@16 519 return is;
Chris@16 520 }
Chris@16 521 num *= d2;
Chris@16 522 den *= n2;
Chris@16 523
Chris@16 524 typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
Chris@16 525
Chris@16 526 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 527 // num / den is now factor to multiply by r
Chris@16 528 if (!chrono_detail::reduce(r, den, err))
Chris@16 529 {
Chris@16 530 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 531 is.setstate(err|is.failbit);
Chris@16 532 return is;
Chris@16 533 }
Chris@16 534
Chris@16 535 //if (r > ((duration_values<common_type_t>::max)() / num))
Chris@16 536 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 537 if (chrono::detail::gt(r,((duration_values<common_type_t>::max)() / num)))
Chris@16 538 {
Chris@16 539 // Conversion to Period overflowed
Chris@16 540 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 541 is.setstate(err|is.failbit);
Chris@16 542 return is;
Chris@16 543 }
Chris@16 544 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 545 common_type_t t = r * num;
Chris@16 546 t /= den;
Chris@16 547 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 548
Chris@101 549 if (t > duration_values<common_type_t>::zero())
Chris@16 550 {
Chris@16 551 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 552 Rep pt = t;
Chris@16 553 if ( (duration_values<Rep>::max)() < pt)
Chris@16 554 {
Chris@16 555 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 556 // Conversion to Period overflowed
Chris@16 557 is.setstate(err|is.failbit);
Chris@16 558 return is;
Chris@16 559 }
Chris@16 560 }
Chris@16 561 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 562 // Success! Store it.
Chris@16 563 r = Rep(t);
Chris@16 564 d = duration<Rep, Period>(r);
Chris@16 565 is.setstate(err);
Chris@16 566 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 567 return is;
Chris@16 568 }
Chris@16 569 else {
Chris@16 570 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 571 is.setstate(is.failbit | is.eofbit);
Chris@16 572 return is;
Chris@16 573 }
Chris@16 574 }
Chris@16 575 else
Chris@16 576 {
Chris@16 577 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 578 if (i == e)
Chris@16 579 is.setstate(is.failbit|is.eofbit);
Chris@16 580 else
Chris@16 581 is.setstate(is.failbit);
Chris@16 582 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 583 return is;
Chris@16 584 }
Chris@16 585 }
Chris@16 586 else {
Chris@16 587 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
Chris@16 588 //is.setstate(is.failbit);
Chris@16 589 return is;
Chris@16 590 }
Chris@16 591 }
Chris@16 592
Chris@16 593
Chris@16 594 template <class CharT, class Traits, class Clock, class Duration>
Chris@16 595 std::basic_ostream<CharT, Traits>&
Chris@16 596 operator<<(std::basic_ostream<CharT, Traits>& os,
Chris@16 597 const time_point<Clock, Duration>& tp)
Chris@16 598 {
Chris@16 599 return os << tp.time_since_epoch() << clock_string<Clock, CharT>::since();
Chris@16 600 }
Chris@16 601
Chris@16 602 template <class CharT, class Traits, class Clock, class Duration>
Chris@16 603 std::basic_istream<CharT, Traits>&
Chris@16 604 operator>>(std::basic_istream<CharT, Traits>& is,
Chris@16 605 time_point<Clock, Duration>& tp)
Chris@16 606 {
Chris@16 607 Duration d;
Chris@16 608 is >> d;
Chris@16 609 if (is.good())
Chris@16 610 {
Chris@16 611 const std::basic_string<CharT> units=clock_string<Clock, CharT>::since();
Chris@16 612 std::ios_base::iostate err = std::ios_base::goodbit;
Chris@16 613 typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
Chris@16 614 in_iterator i(is);
Chris@16 615 in_iterator e;
Chris@16 616 std::ptrdiff_t k = chrono_detail::scan_keyword(i, e,
Chris@16 617 &units, &units + 1,
Chris@16 618 //~ std::use_facet<std::ctype<CharT> >(is.getloc()),
Chris@16 619 err) - &units;
Chris@16 620 is.setstate(err);
Chris@16 621 if (k == 1)
Chris@16 622 {
Chris@16 623 is.setstate(err | is.failbit);
Chris@16 624 // failed to read epoch string
Chris@16 625 return is;
Chris@16 626 }
Chris@16 627 tp = time_point<Clock, Duration>(d);
Chris@16 628 }
Chris@16 629 else
Chris@16 630 is.setstate(is.failbit);
Chris@16 631 return is;
Chris@16 632 }
Chris@16 633 } // chrono
Chris@16 634
Chris@16 635 }
Chris@16 636
Chris@16 637 #endif // BOOST_CHRONO_CHRONO_IO_HPP