]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/chrono/include/boost/chrono/io_v1/chrono_io.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / chrono / include / boost / chrono / io_v1 / chrono_io.hpp
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;
552 Rep pt = t;
553 if ( (duration_values<Rep>::max)() < pt)
554 {
555 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
556 // Conversion to Period overflowed
557 is.setstate(err|is.failbit);
558 return is;
559 }
560 }
561 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
562 // Success! Store it.
563 r = Rep(t);
564 d = duration<Rep, Period>(r);
565 is.setstate(err);
566 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
567 return is;
568 }
569 else {
570 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
571 is.setstate(is.failbit | is.eofbit);
572 return is;
573 }
574 }
575 else
576 {
577 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
578 if (i == e)
579 is.setstate(is.failbit|is.eofbit);
580 else
581 is.setstate(is.failbit);
582 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
583 return is;
584 }
585 }
586 else {
587 //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl;
588 //is.setstate(is.failbit);
589 return is;
590 }
591 }
592
593
594 template <class CharT, class Traits, class Clock, class Duration>
595 std::basic_ostream<CharT, Traits>&
596 operator<<(std::basic_ostream<CharT, Traits>& os,
597 const time_point<Clock, Duration>& tp)
598 {
599 return os << tp.time_since_epoch() << clock_string<Clock, CharT>::since();
600 }
601
602 template <class CharT, class Traits, class Clock, class Duration>
603 std::basic_istream<CharT, Traits>&
604 operator>>(std::basic_istream<CharT, Traits>& is,
605 time_point<Clock, Duration>& tp)
606 {
607 Duration d;
608 is >> d;
609 if (is.good())
610 {
611 const std::basic_string<CharT> units=clock_string<Clock, CharT>::since();
612 std::ios_base::iostate err = std::ios_base::goodbit;
613 typedef std::istreambuf_iterator<CharT, Traits> in_iterator;
614 in_iterator i(is);
615 in_iterator e;
616 std::ptrdiff_t k = chrono_detail::scan_keyword(i, e,
617 &units, &units + 1,
618 //~ std::use_facet<std::ctype<CharT> >(is.getloc()),
619 err) - &units;
620 is.setstate(err);
621 if (k == 1)
622 {
623 is.setstate(err | is.failbit);
624 // failed to read epoch string
625 return is;
626 }
627 tp = time_point<Clock, Duration>(d);
628 }
629 else
630 is.setstate(is.failbit);
631 return is;
632 }
633 } // chrono
634
635 }
636
637 #endif // BOOST_CHRONO_CHRONO_IO_HPP