chrono_io.hpp 23 KB

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