duration_put.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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. * Duration formatting facet for output.
  9. */
  10. #ifndef BOOST_CHRONO_IO_DURATION_PUT_HPP
  11. #define BOOST_CHRONO_IO_DURATION_PUT_HPP
  12. #include <boost/chrono/config.hpp>
  13. #include <boost/chrono/io/duration_units.hpp>
  14. #include <boost/assert.hpp>
  15. #include <locale>
  16. namespace boost
  17. {
  18. namespace chrono
  19. {
  20. /**
  21. * @tparam ChatT a character type
  22. * @tparam OutputIterator a model of @c OutputIterator
  23. *
  24. * The @c duration_put facet provides facilities for formatted output of duration values.
  25. * The member function of @c duration_put take a duration and format it into character string representation.
  26. *
  27. */
  28. template <class CharT, class OutputIterator = std::ostreambuf_iterator<CharT> >
  29. class duration_put: public std::locale::facet
  30. {
  31. public:
  32. /**
  33. * Type of character the facet is instantiated on.
  34. */
  35. typedef CharT char_type;
  36. /**
  37. * Type of character string passed to member functions.
  38. */
  39. typedef std::basic_string<CharT> string_type;
  40. /**
  41. * Type of iterator used to write in the character buffer.
  42. */
  43. typedef OutputIterator iter_type;
  44. /**
  45. * Construct a duration_put facet.
  46. * @param refs
  47. * @Effects Construct a duration_put facet.
  48. * If the @c refs argument is @c 0 then destruction of the object is
  49. * delegated to the @c locale, or locales, containing it. This allows
  50. * the user to ignore lifetime management issues. On the other had,
  51. * if @c refs is @c 1 then the object must be explicitly deleted;
  52. * the @c locale will not do so. In this case, the object can be
  53. * maintained across the lifetime of multiple locales.
  54. */
  55. explicit duration_put(size_t refs = 0) :
  56. std::locale::facet(refs)
  57. {
  58. }
  59. /**
  60. *
  61. * @param s an output stream iterator
  62. * @param ios a reference to a ios_base
  63. * @param fill the character used as filler
  64. * @param d the duration
  65. * @param pattern begin of the formatting pattern
  66. * @param pat_end end of the formatting pattern
  67. *
  68. * @Effects Steps through the sequence from @c pattern to @c pat_end,
  69. * identifying characters that are part of a pattern sequence. Each character
  70. * that is not part of a pattern sequence is written to @c s immediately, and
  71. * each pattern sequence, as it is identified, results in a call to
  72. * @c put_value or @c put_unit;
  73. * thus, pattern elements and other characters are interleaved in the output
  74. * in the order in which they appear in the pattern. Pattern sequences are
  75. * identified by converting each character @c c to a @c char value as if by
  76. * @c ct.narrow(c,0), where @c ct is a reference to @c ctype<charT> obtained from
  77. * @c ios.getloc(). The first character of each sequence is equal to @c '%',
  78. * followed by a pattern specifier character @c spec, which can be @c 'v' for
  79. * the duration value or @c 'u' for the duration unit. .
  80. * For each valid pattern sequence identified, calls
  81. * <c>put_value(s, ios, fill, d)</c> or <c>put_unit(s, ios, fill, d)</c>.
  82. *
  83. * @Returns An iterator pointing immediately after the last character produced.
  84. */
  85. template <typename Rep, typename Period>
  86. iter_type put(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d, const CharT* pattern,
  87. const CharT* pat_end) const
  88. {
  89. if (std::has_facet<duration_units<CharT> >(ios.getloc()))
  90. {
  91. duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >(
  92. ios.getloc());
  93. return put(facet, s, ios, fill, d, pattern, pat_end);
  94. }
  95. else
  96. {
  97. duration_units_default<CharT> facet;
  98. return put(facet, s, ios, fill, d, pattern, pat_end);
  99. }
  100. }
  101. template <typename Rep, typename Period>
  102. iter_type put(duration_units<CharT> const& units_facet, iter_type s, std::ios_base& ios, char_type fill,
  103. duration<Rep, Period> const& d, const CharT* pattern, const CharT* pat_end) const
  104. {
  105. const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc());
  106. for (; pattern != pat_end; ++pattern)
  107. {
  108. if (ct.narrow(*pattern, 0) == '%')
  109. {
  110. if (++pattern == pat_end)
  111. {
  112. *s++ = pattern[-1];
  113. break;
  114. }
  115. char fmt = ct.narrow(*pattern, 0);
  116. switch (fmt)
  117. {
  118. case 'v':
  119. {
  120. s = put_value(s, ios, fill, d);
  121. break;
  122. }
  123. case 'u':
  124. {
  125. s = put_unit(units_facet, s, ios, fill, d);
  126. break;
  127. }
  128. default:
  129. BOOST_ASSERT(false && "Boost::Chrono internal error.");
  130. break;
  131. }
  132. }
  133. else
  134. *s++ = *pattern;
  135. }
  136. return s;
  137. }
  138. /**
  139. *
  140. * @param s an output stream iterator
  141. * @param ios a reference to a ios_base
  142. * @param fill the character used as filler
  143. * @param d the duration
  144. * @Effects imbue in @c ios the @c duration_units_default facet if not already present.
  145. * Retrieves Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if
  146. * @code
  147. * return put(s, ios, d, str.data(), str.data() + str.size());
  148. * @endcode
  149. * @Returns An iterator pointing immediately after the last character produced.
  150. */
  151. template <typename Rep, typename Period>
  152. iter_type put(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const
  153. {
  154. if (std::has_facet<duration_units<CharT> >(ios.getloc()))
  155. {
  156. duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >(
  157. ios.getloc());
  158. std::basic_string<CharT> str = facet.get_pattern();
  159. return put(facet, s, ios, fill, d, str.data(), str.data() + str.size());
  160. }
  161. else
  162. {
  163. duration_units_default<CharT> facet;
  164. std::basic_string<CharT> str = facet.get_pattern();
  165. return put(facet, s, ios, fill, d, str.data(), str.data() + str.size());
  166. }
  167. }
  168. /**
  169. *
  170. * @param s an output stream iterator
  171. * @param ios a reference to a ios_base
  172. * @param fill the character used as filler
  173. * @param d the duration
  174. * @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())).
  175. * @Returns s, iterator pointing immediately after the last character produced.
  176. */
  177. template <typename Rep, typename Period>
  178. iter_type put_value(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const
  179. {
  180. return std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill,
  181. static_cast<long int> (d.count()));
  182. }
  183. /**
  184. *
  185. * @param s an output stream iterator
  186. * @param ios a reference to a ios_base
  187. * @param fill the character used as filler
  188. * @param d the duration
  189. * @Effects Let facet be the duration_units<CharT> facet associated to ios. If the associated unit is named,
  190. * as if
  191. * @code
  192. string_type str = facet.get_unit(get_duration_style(ios), d);
  193. s=std::copy(str.begin(), str.end(), s);
  194. * @endcode
  195. * 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)
  196. * @Returns s, iterator pointing immediately after the last character produced.
  197. */
  198. template <typename Rep, typename Period>
  199. iter_type put_unit(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const
  200. {
  201. if (std::has_facet<duration_units<CharT> >(ios.getloc()))
  202. {
  203. duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >(
  204. ios.getloc());
  205. return put_unit(facet, s, ios, fill, d);
  206. }
  207. else
  208. {
  209. duration_units_default<CharT> facet;
  210. return put_unit(facet, s, ios, fill, d);
  211. }
  212. }
  213. template <typename Rep, typename Period>
  214. iter_type put_unit(duration_units<CharT> const& facet, iter_type s, std::ios_base& ios, char_type fill,
  215. duration<Rep, Period> const& d) const
  216. {
  217. if (facet.template is_named_unit<Period>()) {
  218. string_type str = facet.get_unit(get_duration_style(ios), d);
  219. s=std::copy(str.begin(), str.end(), s);
  220. } else {
  221. *s++ = CharT('[');
  222. std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::num);
  223. *s++ = CharT('/');
  224. std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::den);
  225. *s++ = CharT(']');
  226. string_type str = facet.get_n_d_unit(get_duration_style(ios), d);
  227. s=std::copy(str.begin(), str.end(), s);
  228. }
  229. return s;
  230. }
  231. /**
  232. * Unique identifier for this type of facet.
  233. */
  234. static std::locale::id id;
  235. /**
  236. * @Effects Destroy the facet
  237. */
  238. ~duration_put()
  239. {
  240. }
  241. };
  242. template <class CharT, class OutputIterator>
  243. std::locale::id duration_put<CharT, OutputIterator>::id;
  244. } // chrono
  245. } // boost
  246. #endif // header