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