]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright Howard Hinnant |
2 | // (C) Copyright 2011 Vicente J. Botet Escriba | |
3 | // Use, modification and distribution are subject to the Boost Software License, | |
4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
5 | // http://www.boost.org/LICENSE_1_0.txt). | |
6 | // | |
7 | ||
8 | /** | |
9 | * Duration formatting facet for output. | |
10 | */ | |
11 | #ifndef BOOST_CHRONO_IO_DURATION_PUT_HPP | |
12 | #define BOOST_CHRONO_IO_DURATION_PUT_HPP | |
13 | ||
14 | #include <boost/chrono/config.hpp> | |
15 | #include <boost/chrono/io/duration_units.hpp> | |
16 | #include <boost/chrono/process_cpu_clocks.hpp> | |
17 | #include <boost/assert.hpp> | |
18 | #include <locale> | |
19 | ||
20 | namespace boost | |
21 | { | |
22 | namespace chrono | |
23 | { | |
24 | ||
25 | namespace detail | |
26 | { | |
27 | template <class T> | |
28 | struct propagate { | |
29 | typedef T type; | |
30 | }; | |
31 | template <> | |
32 | struct propagate<boost::int_least32_t> { | |
33 | typedef boost::int_least64_t type; | |
34 | }; | |
35 | } | |
36 | /** | |
37 | * @tparam ChatT a character type | |
38 | * @tparam OutputIterator a model of @c OutputIterator | |
39 | * | |
40 | * The @c duration_put facet provides facilities for formatted output of duration values. | |
41 | * The member function of @c duration_put take a duration and format it into character string representation. | |
42 | * | |
43 | */ | |
44 | template <class CharT, class OutputIterator = std::ostreambuf_iterator<CharT> > | |
45 | class duration_put: public std::locale::facet | |
46 | { | |
47 | public: | |
48 | /** | |
49 | * Type of character the facet is instantiated on. | |
50 | */ | |
51 | typedef CharT char_type; | |
52 | /** | |
53 | * Type of character string passed to member functions. | |
54 | */ | |
55 | typedef std::basic_string<CharT> string_type; | |
56 | /** | |
57 | * Type of iterator used to write in the character buffer. | |
58 | */ | |
59 | typedef OutputIterator iter_type; | |
60 | ||
61 | /** | |
62 | * Construct a duration_put facet. | |
63 | * @param refs | |
64 | * @Effects Construct a duration_put facet. | |
65 | * If the @c refs argument is @c 0 then destruction of the object is | |
66 | * delegated to the @c locale, or locales, containing it. This allows | |
67 | * the user to ignore lifetime management issues. On the other had, | |
68 | * if @c refs is @c 1 then the object must be explicitly deleted; | |
69 | * the @c locale will not do so. In this case, the object can be | |
70 | * maintained across the lifetime of multiple locales. | |
71 | */ | |
72 | explicit duration_put(size_t refs = 0) : | |
73 | std::locale::facet(refs) | |
74 | { | |
75 | } | |
76 | ||
77 | /** | |
78 | * | |
79 | * @param s an output stream iterator | |
80 | * @param ios a reference to a ios_base | |
81 | * @param fill the character used as filler | |
82 | * @param d the duration | |
83 | * @param pattern begin of the formatting pattern | |
84 | * @param pat_end end of the formatting pattern | |
85 | * | |
86 | * @Effects Steps through the sequence from @c pattern to @c pat_end, | |
87 | * identifying characters that are part of a pattern sequence. Each character | |
88 | * that is not part of a pattern sequence is written to @c s immediately, and | |
89 | * each pattern sequence, as it is identified, results in a call to | |
90 | * @c put_value or @c put_unit; | |
91 | * thus, pattern elements and other characters are interleaved in the output | |
92 | * in the order in which they appear in the pattern. Pattern sequences are | |
93 | * identified by converting each character @c c to a @c char value as if by | |
94 | * @c ct.narrow(c,0), where @c ct is a reference to @c ctype<charT> obtained from | |
95 | * @c ios.getloc(). The first character of each sequence is equal to @c '%', | |
96 | * followed by a pattern specifier character @c spec, which can be @c 'v' for | |
97 | * the duration value or @c 'u' for the duration unit. . | |
98 | * For each valid pattern sequence identified, calls | |
99 | * <c>put_value(s, ios, fill, d)</c> or <c>put_unit(s, ios, fill, d)</c>. | |
100 | * | |
101 | * @Returns An iterator pointing immediately after the last character produced. | |
102 | */ | |
103 | template <typename Rep, typename Period> | |
104 | iter_type put(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d, const CharT* pattern, | |
105 | const CharT* pat_end, const char_type* val = 0) const | |
106 | { | |
107 | if (std::has_facet<duration_units<CharT> >(ios.getloc())) | |
108 | { | |
109 | duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >( | |
110 | ios.getloc()); | |
111 | return put(facet, s, ios, fill, d, pattern, pat_end, val); | |
112 | } | |
113 | else | |
114 | { | |
115 | duration_units_default<CharT> facet; | |
116 | return put(facet, s, ios, fill, d, pattern, pat_end, val); | |
117 | } | |
118 | } | |
119 | ||
120 | template <typename Rep, typename Period> | |
121 | iter_type put(duration_units<CharT> const& units_facet, iter_type s, std::ios_base& ios, char_type fill, | |
122 | duration<Rep, Period> const& d, const CharT* pattern, const CharT* pat_end, const char_type* val = 0) const | |
123 | { | |
124 | ||
125 | const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc()); | |
126 | for (; pattern != pat_end; ++pattern) | |
127 | { | |
128 | if (ct.narrow(*pattern, 0) == '%') | |
129 | { | |
130 | if (++pattern == pat_end) | |
131 | { | |
132 | *s++ = pattern[-1]; | |
133 | break; | |
134 | } | |
135 | char fmt = ct.narrow(*pattern, 0); | |
136 | switch (fmt) | |
137 | { | |
138 | case 'v': | |
139 | { | |
140 | s = put_value(s, ios, fill, d, val); | |
141 | break; | |
142 | } | |
143 | case 'u': | |
144 | { | |
145 | s = put_unit(units_facet, s, ios, fill, d); | |
146 | break; | |
147 | } | |
148 | default: | |
149 | BOOST_ASSERT(false && "Boost::Chrono internal error."); | |
150 | break; | |
151 | } | |
152 | } | |
153 | else | |
154 | *s++ = *pattern; | |
155 | } | |
156 | return s; | |
157 | } | |
158 | ||
159 | /** | |
160 | * | |
161 | * @param s an output stream iterator | |
162 | * @param ios a reference to a ios_base | |
163 | * @param fill the character used as filler | |
164 | * @param d the duration | |
165 | * @Effects imbue in @c ios the @c duration_units_default facet if not already present. | |
166 | * Retrieves Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if | |
167 | * @code | |
168 | * return put(s, ios, d, str.data(), str.data() + str.size()); | |
169 | * @endcode | |
170 | * @Returns An iterator pointing immediately after the last character produced. | |
171 | */ | |
172 | template <typename Rep, typename Period> | |
173 | iter_type put(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d, const char_type* val = 0) const | |
174 | { | |
175 | if (std::has_facet<duration_units<CharT> >(ios.getloc())) | |
176 | { | |
177 | duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >( | |
178 | ios.getloc()); | |
179 | std::basic_string<CharT> str = facet.get_pattern(); | |
180 | return put(facet, s, ios, fill, d, str.data(), str.data() + str.size(), val); | |
181 | } | |
182 | else | |
183 | { | |
184 | duration_units_default<CharT> facet; | |
185 | std::basic_string<CharT> str = facet.get_pattern(); | |
186 | ||
187 | return put(facet, s, ios, fill, d, str.data(), str.data() + str.size(), val); | |
188 | } | |
189 | } | |
190 | ||
191 | /** | |
192 | * | |
193 | * @param s an output stream iterator | |
194 | * @param ios a reference to a ios_base | |
195 | * @param fill the character used as filler | |
196 | * @param d the duration | |
197 | * @Effects As if s=std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, static_cast<long int> (d.count())). | |
198 | * @Returns s, iterator pointing immediately after the last character produced. | |
199 | */ | |
200 | template <typename Rep, typename Period> | |
201 | iter_type put_value(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d, const char_type* val = 0) const | |
202 | { | |
203 | if (val) | |
204 | { | |
205 | while (*val) { | |
206 | *s = *val; | |
207 | s++; val++; | |
208 | } | |
209 | return s; | |
210 | } | |
211 | return std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, | |
212 | static_cast<typename detail::propagate<Rep>::type> (d.count())); | |
213 | } | |
214 | ||
215 | template <typename Rep, typename Period> | |
216 | iter_type put_value(iter_type s, std::ios_base& ios, char_type fill, duration<process_times<Rep>, Period> const& d, const char_type* = 0) const | |
217 | { | |
218 | *s++ = CharT('{'); | |
219 | s = put_value(s, ios, fill, process_real_cpu_clock::duration(d.count().real)); | |
220 | *s++ = CharT(';'); | |
221 | s = put_value(s, ios, fill, process_user_cpu_clock::duration(d.count().user)); | |
222 | *s++ = CharT(';'); | |
223 | s = put_value(s, ios, fill, process_system_cpu_clock::duration(d.count().system)); | |
224 | *s++ = CharT('}'); | |
225 | return s; | |
226 | } | |
227 | ||
228 | /** | |
229 | * | |
230 | * @param s an output stream iterator | |
231 | * @param ios a reference to a ios_base | |
232 | * @param fill the character used as filler | |
233 | * @param d the duration | |
234 | * @Effects Let facet be the duration_units<CharT> facet associated to ios. If the associated unit is named, | |
235 | * as if | |
236 | * @code | |
237 | string_type str = facet.get_unit(get_duration_style(ios), d); | |
238 | s=std::copy(str.begin(), str.end(), s); | |
239 | * @endcode | |
240 | * Otherwise, format the unit as "[Period::num/Period::den]" followed by the unit associated to [N/D] obtained using facet.get_n_d_unit(get_duration_style(ios), d) | |
241 | * @Returns s, iterator pointing immediately after the last character produced. | |
242 | */ | |
243 | template <typename Rep, typename Period> | |
244 | iter_type put_unit(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const | |
245 | { | |
246 | if (std::has_facet<duration_units<CharT> >(ios.getloc())) | |
247 | { | |
248 | duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >( | |
249 | ios.getloc()); | |
250 | return put_unit(facet, s, ios, fill, d); | |
251 | } | |
252 | else | |
253 | { | |
254 | duration_units_default<CharT> facet; | |
255 | return put_unit(facet, s, ios, fill, d); | |
256 | } | |
257 | } | |
258 | ||
259 | template <typename Rep, typename Period> | |
260 | iter_type put_unit(duration_units<CharT> const& facet, iter_type s, std::ios_base& ios, char_type fill, | |
261 | duration<Rep, Period> const& d) const | |
262 | { | |
263 | if (facet.template is_named_unit<Period>()) { | |
264 | string_type str = facet.get_unit(get_duration_style(ios), d); | |
265 | s=std::copy(str.begin(), str.end(), s); | |
266 | } else { | |
267 | *s++ = CharT('['); | |
268 | std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::num); | |
269 | *s++ = CharT('/'); | |
270 | std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::den); | |
271 | *s++ = CharT(']'); | |
272 | string_type str = facet.get_n_d_unit(get_duration_style(ios), d); | |
273 | s=std::copy(str.begin(), str.end(), s); | |
274 | } | |
275 | return s; | |
276 | } | |
277 | template <typename Rep, typename Period> | |
278 | iter_type put_unit(duration_units<CharT> const& facet, iter_type s, std::ios_base& ios, char_type fill, | |
279 | duration<process_times<Rep>, Period> const& d) const | |
280 | { | |
281 | duration<Rep,Period> real(d.count().real); | |
282 | if (facet.template is_named_unit<Period>()) { | |
283 | string_type str = facet.get_unit(get_duration_style(ios), real); | |
284 | s=std::copy(str.begin(), str.end(), s); | |
285 | } else { | |
286 | *s++ = CharT('['); | |
287 | std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::num); | |
288 | *s++ = CharT('/'); | |
289 | std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::den); | |
290 | *s++ = CharT(']'); | |
291 | string_type str = facet.get_n_d_unit(get_duration_style(ios), real); | |
292 | s=std::copy(str.begin(), str.end(), s); | |
293 | } | |
294 | return s; | |
295 | } | |
296 | ||
297 | /** | |
298 | * Unique identifier for this type of facet. | |
299 | */ | |
300 | static std::locale::id id; | |
301 | ||
302 | /** | |
303 | * @Effects Destroy the facet | |
304 | */ | |
305 | ~duration_put() | |
306 | { | |
307 | } | |
308 | ||
309 | }; | |
310 | ||
311 | template <class CharT, class OutputIterator> | |
312 | std::locale::id duration_put<CharT, OutputIterator>::id; | |
313 | ||
314 | } // chrono | |
315 | } // boost | |
316 | ||
317 | #endif // header |