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