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
|