File indexing completed on 2025-01-18 09:39:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_
0017 #define BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_
0018
0019 #include <ctime>
0020 #include <string>
0021 #include <vector>
0022 #include <locale>
0023 #include <boost/cstdint.hpp>
0024 #include <boost/move/core.hpp>
0025 #include <boost/range/iterator_range_core.hpp>
0026 #include <boost/log/detail/config.hpp>
0027 #include <boost/log/detail/date_time_format_parser.hpp>
0028 #include <boost/log/detail/attachable_sstream_buf.hpp>
0029 #include <boost/log/utility/formatting_ostream.hpp>
0030 #include <boost/log/detail/header.hpp>
0031
0032 #ifdef BOOST_HAS_PRAGMA_ONCE
0033 #pragma once
0034 #endif
0035
0036 namespace boost {
0037
0038 BOOST_LOG_OPEN_NAMESPACE
0039
0040 namespace aux {
0041
0042
0043 struct decomposed_time
0044 {
0045
0046 enum _
0047 {
0048 subseconds_per_second = 1000000,
0049 subseconds_digits10 = 6
0050 };
0051
0052 uint32_t year, month, day, hours, minutes, seconds, subseconds;
0053 bool negative;
0054
0055 decomposed_time() : year(0), month(1), day(1), hours(0), minutes(0), seconds(0), subseconds(0), negative(false)
0056 {
0057 }
0058
0059 decomposed_time(uint32_t y, uint32_t mo, uint32_t d, uint32_t h, uint32_t mi, uint32_t s, uint32_t ss = 0, bool neg = false) :
0060 year(y), month(mo), day(d), hours(h), minutes(mi), seconds(s), subseconds(ss), negative(neg)
0061 {
0062 }
0063
0064 unsigned int week_day() const
0065 {
0066 unsigned int a = (14u - month) / 12u;
0067 unsigned int y = year - a;
0068 unsigned int m = month + 12u * a - 2u;
0069 return (day + y + (y / 4u) - (y / 100u) + (y / 400u) + (31u * m) / 12u) % 7u;
0070 }
0071
0072 unsigned int year_day() const
0073 {
0074 bool is_leap_year = (!(year % 4u)) && ((year % 100u) || (!(year % 400u)));
0075 static const unsigned int first_day_offset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
0076 return first_day_offset[month - 1] + day + (month > 2 && is_leap_year);
0077 }
0078 };
0079
0080 inline std::tm to_tm(decomposed_time const& t)
0081 {
0082 std::tm res = {};
0083 res.tm_year = static_cast< int >(t.year) - 1900;
0084 res.tm_mon = t.month - 1;
0085 res.tm_mday = t.day;
0086 res.tm_hour = t.hours;
0087 res.tm_min = t.minutes;
0088 res.tm_sec = t.seconds;
0089 res.tm_wday = t.week_day();
0090 res.tm_yday = t.year_day();
0091 res.tm_isdst = -1;
0092
0093 return res;
0094 }
0095
0096 template< typename T >
0097 struct decomposed_time_wrapper :
0098 public boost::log::aux::decomposed_time
0099 {
0100 typedef boost::log::aux::decomposed_time base_type;
0101 typedef T value_type;
0102 value_type m_time;
0103
0104 BOOST_DEFAULTED_FUNCTION(decomposed_time_wrapper(), {})
0105
0106 explicit decomposed_time_wrapper(value_type const& time) : m_time(time)
0107 {
0108 }
0109 };
0110
0111 template< typename CharT >
0112 BOOST_LOG_API void put_integer(boost::log::aux::basic_ostringstreambuf< CharT >& strbuf, uint32_t value, unsigned int width, CharT fill_char);
0113
0114 template< typename T, typename CharT >
0115 class date_time_formatter
0116 {
0117 BOOST_COPYABLE_AND_MOVABLE_ALT(date_time_formatter)
0118
0119 protected:
0120
0121 typedef date_time_formatter date_time_formatter_;
0122
0123 public:
0124 typedef void result_type;
0125 typedef T value_type;
0126 typedef CharT char_type;
0127 typedef std::basic_string< char_type > string_type;
0128 typedef basic_formatting_ostream< char_type > stream_type;
0129
0130 struct context
0131 {
0132 date_time_formatter const& self;
0133 stream_type& strm;
0134 value_type const& value;
0135 unsigned int literal_index, literal_pos;
0136
0137 context(date_time_formatter const& self_, stream_type& strm_, value_type const& value_) :
0138 self(self_),
0139 strm(strm_),
0140 value(value_),
0141 literal_index(0),
0142 literal_pos(0)
0143 {
0144 }
0145
0146 BOOST_DELETED_FUNCTION(context(context const&))
0147 BOOST_DELETED_FUNCTION(context& operator=(context const&))
0148 };
0149
0150 private:
0151 typedef void (*formatter_type)(context&);
0152 typedef std::vector< formatter_type > formatters;
0153 typedef std::vector< unsigned int > literal_lens;
0154
0155 protected:
0156 formatters m_formatters;
0157 literal_lens m_literal_lens;
0158 string_type m_literal_chars;
0159
0160 public:
0161 BOOST_DEFAULTED_FUNCTION(date_time_formatter(), {})
0162 date_time_formatter(date_time_formatter const& that) :
0163 m_formatters(that.m_formatters),
0164 m_literal_lens(that.m_literal_lens),
0165 m_literal_chars(that.m_literal_chars)
0166 {
0167 }
0168 date_time_formatter(BOOST_RV_REF(date_time_formatter) that) BOOST_NOEXCEPT
0169 {
0170 this->swap(static_cast< date_time_formatter& >(that));
0171 }
0172
0173 date_time_formatter& operator= (date_time_formatter that) BOOST_NOEXCEPT
0174 {
0175 this->swap(that);
0176 return *this;
0177 }
0178
0179 result_type operator() (stream_type& strm, value_type const& value) const
0180 {
0181
0182 strm.flush();
0183 context ctx(*this, strm, value);
0184 for (typename formatters::const_iterator it = m_formatters.begin(), end = m_formatters.end(); strm.good() && it != end; ++it)
0185 {
0186 (*it)(ctx);
0187 }
0188 }
0189
0190 void add_formatter(formatter_type fun)
0191 {
0192 m_formatters.push_back(fun);
0193 }
0194
0195 void add_literal(iterator_range< const char_type* > const& lit)
0196 {
0197 m_literal_chars.append(lit.begin(), lit.end());
0198 m_literal_lens.push_back(static_cast< unsigned int >(lit.size()));
0199 m_formatters.push_back(&date_time_formatter_::format_literal);
0200 }
0201
0202 void swap(date_time_formatter& that) BOOST_NOEXCEPT
0203 {
0204 m_formatters.swap(that.m_formatters);
0205 m_literal_lens.swap(that.m_literal_lens);
0206 m_literal_chars.swap(that.m_literal_chars);
0207 }
0208
0209 public:
0210 template< char FormatCharV >
0211 static void format_through_locale(context& ctx)
0212 {
0213 typedef std::time_put< char_type > facet_type;
0214 typedef typename facet_type::iter_type iter_type;
0215 std::tm t = to_tm(static_cast< decomposed_time const& >(ctx.value));
0216 std::use_facet< facet_type >(ctx.strm.getloc()).put(iter_type(ctx.strm.stream()), ctx.strm.stream(), ' ', &t, FormatCharV);
0217 ctx.strm.flush();
0218 }
0219
0220 static void format_full_year(context& ctx)
0221 {
0222 (put_integer)(*ctx.strm.rdbuf(), ctx.value.year, 4, static_cast< char_type >('0'));
0223 }
0224
0225 static void format_short_year(context& ctx)
0226 {
0227 (put_integer)(*ctx.strm.rdbuf(), ctx.value.year % 100u, 2, static_cast< char_type >('0'));
0228 }
0229
0230 static void format_numeric_month(context& ctx)
0231 {
0232 (put_integer)(*ctx.strm.rdbuf(), ctx.value.month, 2, static_cast< char_type >('0'));
0233 }
0234
0235 template< char_type FillCharV >
0236 static void format_month_day(context& ctx)
0237 {
0238 (put_integer)(*ctx.strm.rdbuf(), ctx.value.day, 2, static_cast< char_type >(FillCharV));
0239 }
0240
0241 static void format_week_day(context& ctx)
0242 {
0243 (put_integer)(*ctx.strm.rdbuf(), static_cast< decomposed_time const& >(ctx.value).week_day(), 1, static_cast< char_type >('0'));
0244 }
0245
0246 template< char_type FillCharV >
0247 static void format_hours(context& ctx)
0248 {
0249 (put_integer)(*ctx.strm.rdbuf(), ctx.value.hours, 2, static_cast< char_type >(FillCharV));
0250 }
0251
0252 template< char_type FillCharV >
0253 static void format_hours_12(context& ctx)
0254 {
0255 (put_integer)(*ctx.strm.rdbuf(), ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV));
0256 }
0257
0258 static void format_minutes(context& ctx)
0259 {
0260 (put_integer)(*ctx.strm.rdbuf(), ctx.value.minutes, 2, static_cast< char_type >('0'));
0261 }
0262
0263 static void format_seconds(context& ctx)
0264 {
0265 (put_integer)(*ctx.strm.rdbuf(), ctx.value.seconds, 2, static_cast< char_type >('0'));
0266 }
0267
0268 static void format_fractional_seconds(context& ctx)
0269 {
0270 (put_integer)(*ctx.strm.rdbuf(), ctx.value.subseconds, decomposed_time::subseconds_digits10, static_cast< char_type >('0'));
0271 }
0272
0273 template< bool UpperCaseV >
0274 static void format_am_pm(context& ctx)
0275 {
0276 static const char_type am[] = { static_cast< char_type >(UpperCaseV ? 'A' : 'a'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) };
0277 static const char_type pm[] = { static_cast< char_type >(UpperCaseV ? 'P' : 'p'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) };
0278
0279 ctx.strm.rdbuf()->append(((static_cast< decomposed_time const& >(ctx.value).hours > 11) ? pm : am), 2u);
0280 }
0281
0282 template< bool DisplayPositiveV >
0283 static void format_sign(context& ctx)
0284 {
0285 if (static_cast< decomposed_time const& >(ctx.value).negative)
0286 ctx.strm.rdbuf()->push_back('-');
0287 else if (DisplayPositiveV)
0288 ctx.strm.rdbuf()->push_back('+');
0289 }
0290
0291 private:
0292 static void format_literal(context& ctx)
0293 {
0294 unsigned int len = ctx.self.m_literal_lens[ctx.literal_index], pos = ctx.literal_pos;
0295 ++ctx.literal_index;
0296 ctx.literal_pos += len;
0297 const char_type* lit = ctx.self.m_literal_chars.c_str();
0298 ctx.strm.rdbuf()->append(lit + pos, len);
0299 }
0300 };
0301
0302 template< typename FormatterT, typename CharT >
0303 class decomposed_time_formatter_builder :
0304 public date_time_format_parser_callback< CharT >
0305 {
0306 public:
0307 typedef date_time_format_parser_callback< CharT > base_type;
0308 typedef typename base_type::char_type char_type;
0309 typedef FormatterT formatter_type;
0310 typedef typename formatter_type::value_type value_type;
0311 typedef typename formatter_type::stream_type stream_type;
0312 typedef typename stream_type::string_type string_type;
0313
0314 protected:
0315 formatter_type& m_formatter;
0316
0317 public:
0318 explicit decomposed_time_formatter_builder(formatter_type& fmt) : m_formatter(fmt)
0319 {
0320 }
0321
0322 void on_literal(iterator_range< const char_type* > const& lit)
0323 {
0324 m_formatter.add_literal(lit);
0325 }
0326
0327 void on_short_year()
0328 {
0329 m_formatter.add_formatter(&formatter_type::format_short_year);
0330 }
0331
0332 void on_full_year()
0333 {
0334 m_formatter.add_formatter(&formatter_type::format_full_year);
0335 }
0336
0337 void on_numeric_month()
0338 {
0339 m_formatter.add_formatter(&formatter_type::format_numeric_month);
0340 }
0341
0342 void on_short_month()
0343 {
0344 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'b' >);
0345 }
0346
0347 void on_full_month()
0348 {
0349 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'B' >);
0350 }
0351
0352 void on_month_day(bool leading_zero)
0353 {
0354 if (leading_zero)
0355 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< '0' >);
0356 else
0357 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< ' ' >);
0358 }
0359
0360 void on_numeric_week_day()
0361 {
0362 m_formatter.add_formatter(&formatter_type::format_week_day);
0363 }
0364
0365 void on_short_week_day()
0366 {
0367 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'a' >);
0368 }
0369
0370 void on_full_week_day()
0371 {
0372 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'A' >);
0373 }
0374
0375 void on_hours(bool leading_zero)
0376 {
0377 if (leading_zero)
0378 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< '0' >);
0379 else
0380 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< ' ' >);
0381 }
0382
0383 void on_hours_12(bool leading_zero)
0384 {
0385 if (leading_zero)
0386 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< '0' >);
0387 else
0388 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< ' ' >);
0389 }
0390
0391 void on_minutes()
0392 {
0393 m_formatter.add_formatter(&formatter_type::format_minutes);
0394 }
0395
0396 void on_seconds()
0397 {
0398 m_formatter.add_formatter(&formatter_type::format_seconds);
0399 }
0400
0401 void on_fractional_seconds()
0402 {
0403 m_formatter.add_formatter(&formatter_type::format_fractional_seconds);
0404 }
0405
0406 void on_am_pm(bool upper_case)
0407 {
0408 if (upper_case)
0409 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< true >);
0410 else
0411 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< false >);
0412 }
0413
0414 void on_duration_sign(bool display_positive)
0415 {
0416 if (display_positive)
0417 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< true >);
0418 else
0419 m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< false >);
0420 }
0421
0422 void on_iso_time_zone()
0423 {
0424 }
0425
0426 void on_extended_iso_time_zone()
0427 {
0428 }
0429 };
0430
0431 }
0432
0433 BOOST_LOG_CLOSE_NAMESPACE
0434
0435 }
0436
0437 #include <boost/log/detail/footer.hpp>
0438
0439 #endif