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 // This code was adapted by Vicente from Howard Hinnant's experimental work 8 // on chrono i/o to Boost 9 10 #ifndef BOOST_CHRONO_IO_DURATION_IO_HPP 11 #define BOOST_CHRONO_IO_DURATION_IO_HPP 12 13 #include <boost/chrono/duration.hpp> 14 #include <boost/ratio/ratio_io.hpp> 15 #include <boost/chrono/io/duration_style.hpp> 16 #include <boost/chrono/io/ios_base_state.hpp> 17 #include <boost/chrono/io/duration_put.hpp> 18 #include <boost/chrono/io/duration_get.hpp> 19 #include <boost/chrono/io/utility/manip_base.hpp> 20 #include <boost/detail/no_exceptions_support.hpp> 21 #include <boost/type_traits/is_integral.hpp> 22 #include <boost/type_traits/is_floating_point.hpp> 23 #include <locale> 24 #include <iosfwd> 25 #include <sstream> 26 27 namespace boost 28 { 29 namespace chrono 30 { 31 32 /** 33 * duration parameterized manipulator. 34 */ 35 36 class duration_fmt: public manip<duration_fmt> 37 { 38 duration_style style_; 39 public: 40 41 /** 42 * explicit manipulator constructor from a @c duration_style 43 */ duration_fmt(duration_style style)44 explicit duration_fmt(duration_style style)BOOST_NOEXCEPT 45 : style_(style) 46 {} 47 48 /** 49 * Change the duration_style ios state; 50 */ operator ()(std::ios_base & ios) const51 void operator()(std::ios_base &ios) const 52 53 { 54 set_duration_style(ios, style_); 55 } 56 }; 57 58 /** 59 * duration_style i/o saver. 60 * 61 * See Boost.IO i/o state savers for a motivating compression. 62 */ 63 struct duration_style_io_saver 64 { 65 66 //! the type of the state to restore 67 typedef std::ios_base state_type; 68 //! the type of aspect to save 69 typedef duration_style aspect_type; 70 71 /** 72 * Explicit construction from an i/o stream. 73 * 74 * Store a reference to the i/o stream and the value of the associated @c duration_style. 75 */ duration_style_io_saverboost::chrono::duration_style_io_saver76 explicit duration_style_io_saver(state_type &s) : 77 s_save_(s), a_save_(get_duration_style(s)) 78 { 79 } 80 81 /** 82 * Construction from an i/o stream and a @c duration_style to restore. 83 * 84 * Stores a reference to the i/o stream and the value @c new_value @c duration_style to set. 85 */ duration_style_io_saverboost::chrono::duration_style_io_saver86 duration_style_io_saver(state_type &s, aspect_type new_value) : 87 s_save_(s), a_save_(get_duration_style(s)) 88 { 89 set_duration_style(s, new_value); 90 } 91 92 /** 93 * Destructor. 94 * 95 * Restores the i/o stream with the duration_style to be restored. 96 */ ~duration_style_io_saverboost::chrono::duration_style_io_saver97 ~duration_style_io_saver() 98 { 99 this->restore(); 100 } 101 102 /** 103 * Restores the i/o stream with the duration_style to be restored. 104 */ restoreboost::chrono::duration_style_io_saver105 void restore() 106 { 107 set_duration_style(s_save_, a_save_); 108 } 109 110 private: 111 duration_style_io_saver& operator=(duration_style_io_saver const& rhs) ; 112 113 state_type& s_save_; 114 aspect_type a_save_; 115 }; 116 117 template <class Rep> 118 struct duration_put_enabled 119 : integral_constant<bool, 120 is_integral<Rep>::value || is_floating_point<Rep>::value 121 > 122 {}; 123 124 125 /** 126 * duration stream inserter 127 * @param os the output stream 128 * @param d to value to insert 129 * @return @c os 130 */ 131 132 template <class CharT, class Traits, class Rep, class Period> 133 typename boost::enable_if_c< ! duration_put_enabled<Rep>::value, std::basic_ostream<CharT, Traits>& >::type operator <<(std::basic_ostream<CharT,Traits> & os,const duration<Rep,Period> & d)134 operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d) 135 { 136 std::basic_ostringstream<CharT, Traits> ostr; 137 ostr << d.count(); 138 duration<int, Period> dd(0); 139 bool failed = false; 140 BOOST_TRY 141 { 142 std::ios_base::iostate err = std::ios_base::goodbit; 143 BOOST_TRY 144 { 145 typename std::basic_ostream<CharT, Traits>::sentry opfx(os); 146 if (bool(opfx)) 147 { 148 if (!std::has_facet<duration_put<CharT> >(os.getloc())) 149 { 150 if (duration_put<CharT> ().put(os, os, os.fill(), dd, ostr.str().c_str()) .failed()) 151 { 152 err = std::ios_base::badbit; 153 } 154 } 155 else if (std::use_facet<duration_put<CharT> >(os.getloc()) .put(os, os, os.fill(), dd, ostr.str().c_str()) .failed()) 156 { 157 err = std::ios_base::badbit; 158 } 159 os.width(0); 160 } 161 } 162 BOOST_CATCH(...) 163 { 164 bool flag = false; 165 BOOST_TRY 166 { 167 os.setstate(std::ios_base::failbit); 168 } 169 BOOST_CATCH (std::ios_base::failure ) 170 { 171 flag = true; 172 } 173 BOOST_CATCH_END 174 if (flag) throw; 175 } 176 BOOST_CATCH_END 177 if (err) os.setstate(err); 178 return os; 179 } 180 BOOST_CATCH(...) 181 { 182 failed = true; 183 } 184 BOOST_CATCH_END 185 if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit); 186 return os; 187 188 } 189 190 template <class CharT, class Traits, class Rep, class Period> 191 typename boost::enable_if_c< duration_put_enabled<Rep>::value, std::basic_ostream<CharT, Traits>& >::type operator <<(std::basic_ostream<CharT,Traits> & os,const duration<Rep,Period> & d)192 operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d) 193 { 194 bool failed = false; 195 BOOST_TRY 196 { 197 std::ios_base::iostate err = std::ios_base::goodbit; 198 BOOST_TRY 199 { 200 typename std::basic_ostream<CharT, Traits>::sentry opfx(os); 201 if (bool(opfx)) 202 { 203 if (!std::has_facet<duration_put<CharT> >(os.getloc())) 204 { 205 if (duration_put<CharT> ().put(os, os, os.fill(), d) .failed()) 206 { 207 err = std::ios_base::badbit; 208 } 209 } 210 else if (std::use_facet<duration_put<CharT> >(os.getloc()) .put(os, os, os.fill(), d) .failed()) 211 { 212 err = std::ios_base::badbit; 213 } 214 os.width(0); 215 } 216 } 217 BOOST_CATCH(...) 218 { 219 bool flag = false; 220 BOOST_TRY 221 { 222 os.setstate(std::ios_base::failbit); 223 } 224 BOOST_CATCH (std::ios_base::failure ) 225 { 226 flag = true; 227 } 228 BOOST_CATCH_END 229 if (flag) throw; 230 } 231 BOOST_CATCH_END 232 if (err) os.setstate(err); 233 return os; 234 } 235 BOOST_CATCH(...) 236 { 237 failed = true; 238 } 239 BOOST_CATCH_END 240 if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit); 241 return os; 242 } 243 244 /** 245 * 246 * @param is the input stream 247 * @param d the duration 248 * @return @c is 249 */ 250 template <class CharT, class Traits, class Rep, class Period> 251 std::basic_istream<CharT, Traits>& operator >>(std::basic_istream<CharT,Traits> & is,duration<Rep,Period> & d)252 operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) 253 { 254 std::ios_base::iostate err = std::ios_base::goodbit; 255 256 BOOST_TRY 257 { 258 typename std::basic_istream<CharT, Traits>::sentry ipfx(is); 259 if (bool(ipfx)) 260 { 261 if (!std::has_facet<duration_get<CharT> >(is.getloc())) 262 { 263 duration_get<CharT> ().get(is, std::istreambuf_iterator<CharT, Traits>(), is, err, d); 264 } 265 else 266 { 267 std::use_facet<duration_get<CharT> >(is.getloc()) .get(is, std::istreambuf_iterator<CharT, Traits>(), is, 268 err, d); 269 } 270 } 271 } 272 BOOST_CATCH (...) 273 { 274 bool flag = false; 275 BOOST_TRY 276 { 277 is.setstate(std::ios_base::failbit); 278 } 279 BOOST_CATCH (std::ios_base::failure ) 280 { 281 flag = true; 282 } 283 BOOST_CATCH_END 284 if (flag) { BOOST_RETHROW } 285 } 286 BOOST_CATCH_END 287 if (err) is.setstate(err); 288 return is; 289 } 290 291 } // chrono 292 293 } 294 295 #endif // header 296