2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
8 * \file date_time_format_parser.cpp
9 * \author Andrey Semashev
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
16 #include <boost/log/detail/config.hpp>
20 #include <boost/spirit/include/karma_uint.hpp>
21 #include <boost/spirit/include/karma_generate.hpp>
22 #include <boost/range/iterator_range_core.hpp>
23 #include <boost/log/detail/attachable_sstream_buf.hpp>
24 #include <boost/log/detail/date_time_format_parser.hpp>
25 #include <boost/log/detail/header.hpp>
27 namespace karma
= boost::spirit::karma
;
31 BOOST_LOG_OPEN_NAMESPACE
35 BOOST_LOG_ANONYMOUS_NAMESPACE
{
37 template< typename CharT
>
38 struct string_constants
;
40 #ifdef BOOST_LOG_USE_CHAR
43 struct string_constants
< char >
45 typedef char char_type
;
47 static const char_type
* iso_date_format() { return "%Y%m%d"; }
48 static const char_type
* extended_iso_date_format() { return "%Y-%m-%d"; }
50 static const char_type
* iso_time_format() { return "%H%M%S"; }
51 static const char_type
* extended_iso_time_format() { return "%H:%M:%S"; }
52 static const char_type
* default_time_format() { return "%H:%M:%S.%f"; }
55 #endif // BOOST_LOG_USE_CHAR
57 #ifdef BOOST_LOG_USE_WCHAR_T
60 struct string_constants
< wchar_t >
62 typedef wchar_t char_type
;
64 static const char_type
* iso_date_format() { return L
"%Y%m%d"; }
65 static const char_type
* extended_iso_date_format() { return L
"%Y-%m-%d"; }
67 static const char_type
* iso_time_format() { return L
"%H%M%S"; }
68 static const char_type
* extended_iso_time_format() { return L
"%H:%M:%S"; }
69 static const char_type
* default_time_format() { return L
"%H:%M:%S.%f"; }
72 #endif // BOOST_LOG_USE_WCHAR_T
74 template< typename CallbackT
>
77 typedef CallbackT callback_type
;
78 typedef typename
callback_type::char_type char_type
;
79 typedef std::basic_string
< char_type
> string_type
;
81 const char_type
* parse(const char_type
* begin
, const char_type
* end
, callback_type
& callback
)
86 m_literal
.push_back('%');
91 callback
.on_placeholder(iterator_range
< const char_type
* >(begin
, begin
+ 2));
98 void add_literal(const char_type
* begin
, const char_type
* end
)
100 m_literal
.append(begin
, end
);
103 void flush(callback_type
& callback
)
105 if (!m_literal
.empty())
107 const char_type
* p
= m_literal
.c_str();
108 callback
.on_literal(iterator_range
< const char_type
* >(p
, p
+ m_literal
.size()));
114 string_type m_literal
;
117 template< typename BaseT
>
121 typedef typename
BaseT::callback_type callback_type
;
122 typedef typename
BaseT::char_type char_type
;
124 const char_type
* parse(const char_type
* begin
, const char_type
* end
, callback_type
& callback
)
126 typedef string_constants
< char_type
> constants
;
132 this->flush(callback
);
134 std::size_t len
= end
- begin
;
135 if (len
>= 8 && std::memcmp(begin
, constants::extended_iso_date_format(), 8 * sizeof(char_type
)) == 0)
137 callback
.on_extended_iso_date();
140 else if (len
>= 6 && std::memcmp(begin
, constants::iso_date_format(), 6 * sizeof(char_type
)) == 0)
142 callback
.on_iso_date();
147 callback
.on_full_year();
153 this->flush(callback
);
154 callback
.on_short_year();
158 this->flush(callback
);
159 callback
.on_numeric_month();
163 this->flush(callback
);
164 callback
.on_full_month();
168 this->flush(callback
);
169 callback
.on_short_month();
173 this->flush(callback
);
174 callback
.on_month_day(true);
178 this->flush(callback
);
179 callback
.on_month_day(false);
183 this->flush(callback
);
184 callback
.on_numeric_week_day();
188 this->flush(callback
);
189 callback
.on_full_week_day();
193 this->flush(callback
);
194 callback
.on_short_week_day();
198 return BaseT::parse(begin
, end
, callback
);
205 template< typename BaseT
>
209 typedef typename
BaseT::callback_type callback_type
;
210 typedef typename
BaseT::char_type char_type
;
212 const char_type
* parse(const char_type
* begin
, const char_type
* end
, callback_type
& callback
)
214 typedef string_constants
< char_type
> constants
;
221 this->flush(callback
);
223 std::size_t len
= end
- begin
;
224 if (len
>= 11 && std::memcmp(begin
, constants::default_time_format(), 11 * sizeof(char_type
)) == 0)
226 callback
.on_default_time();
229 else if (len
>= 8 && std::memcmp(begin
, constants::extended_iso_time_format(), 8 * sizeof(char_type
)) == 0)
231 callback
.on_extended_iso_time();
234 else if (len
>= 6 && std::memcmp(begin
, constants::iso_time_format(), 6 * sizeof(char_type
)) == 0)
236 callback
.on_iso_time();
241 callback
.on_hours(true);
247 this->flush(callback
);
248 callback
.on_extended_iso_time();
252 this->flush(callback
);
253 callback
.on_hours(false);
257 this->flush(callback
);
258 callback
.on_hours_12(true);
262 this->flush(callback
);
263 callback
.on_hours_12(false);
267 this->flush(callback
);
268 callback
.on_minutes();
272 this->flush(callback
);
273 callback
.on_seconds();
277 this->flush(callback
);
278 callback
.on_fractional_seconds();
282 this->flush(callback
);
283 callback
.on_am_pm(false);
287 this->flush(callback
);
288 callback
.on_am_pm(true);
292 this->flush(callback
);
293 callback
.on_extended_iso_time_zone();
297 this->flush(callback
);
298 callback
.on_iso_time_zone();
302 this->flush(callback
);
303 callback
.on_duration_sign(false);
307 this->flush(callback
);
308 callback
.on_duration_sign(true);
312 return BaseT::parse(begin
, end
, callback
);
319 template< typename CharT
, typename ParserT
, typename CallbackT
>
320 inline void parse_format(const CharT
* begin
, const CharT
* end
, ParserT
& parser
, CallbackT
& callback
)
322 typedef CharT char_type
;
326 const char_type
* p
= std::find(begin
, end
, static_cast< char_type
>('%'));
327 parser
.add_literal(begin
, p
);
331 begin
= parser
.parse(p
, end
, callback
);
336 parser
.add_literal(p
, end
); // a single '%' character at the end of the string
341 parser
.flush(callback
);
346 //! Parses the date format string and invokes the callback object
347 template< typename CharT
>
348 BOOST_LOG_API
void parse_date_format(const CharT
* begin
, const CharT
* end
, date_format_parser_callback
< CharT
>& callback
)
350 typedef CharT char_type
;
351 typedef date_format_parser_callback
< char_type
> callback_type
;
352 date_flags
< common_flags
< callback_type
> > parser
;
353 parse_format(begin
, end
, parser
, callback
);
356 //! Parses the time format string and invokes the callback object
357 template< typename CharT
>
358 BOOST_LOG_API
void parse_time_format(const CharT
* begin
, const CharT
* end
, time_format_parser_callback
< CharT
>& callback
)
360 typedef CharT char_type
;
361 typedef time_format_parser_callback
< char_type
> callback_type
;
362 time_flags
< common_flags
< callback_type
> > parser
;
363 parse_format(begin
, end
, parser
, callback
);
366 //! Parses the date and time format string and invokes the callback object
367 template< typename CharT
>
368 BOOST_LOG_API
void parse_date_time_format(const CharT
* begin
, const CharT
* end
, date_time_format_parser_callback
< CharT
>& callback
)
370 typedef CharT char_type
;
371 typedef date_time_format_parser_callback
< char_type
> callback_type
;
372 date_flags
< time_flags
< common_flags
< callback_type
> > > parser
;
373 parse_format(begin
, end
, parser
, callback
);
376 template< typename CharT
>
377 BOOST_LOG_API
void put_integer(boost::log::aux::basic_ostringstreambuf
< CharT
>& strbuf
, uint32_t value
, unsigned int width
, CharT fill_char
)
379 typedef CharT char_type
;
380 char_type buf
[std::numeric_limits
< uint32_t >::digits10
+ 2];
383 typedef karma::uint_generator
< uint32_t, 10 > uint_gen
;
384 karma::generate(p
, uint_gen(), value
);
385 const std::size_t len
= p
- buf
;
387 strbuf
.append(width
- len
, fill_char
);
388 strbuf
.append(buf
, len
);
391 #ifdef BOOST_LOG_USE_CHAR
393 template BOOST_LOG_API
394 void parse_date_format(const char* begin
, const char* end
, date_format_parser_callback
< char >& callback
);
395 template BOOST_LOG_API
396 void parse_time_format(const char* begin
, const char* end
, time_format_parser_callback
< char >& callback
);
397 template BOOST_LOG_API
398 void parse_date_time_format(const char* begin
, const char* end
, date_time_format_parser_callback
< char >& callback
);
399 template BOOST_LOG_API
400 void put_integer(boost::log::aux::basic_ostringstreambuf
< char >& strbuf
, uint32_t value
, unsigned int width
, char fill_char
);
402 #endif // BOOST_LOG_USE_CHAR
404 #ifdef BOOST_LOG_USE_WCHAR_T
406 template BOOST_LOG_API
407 void parse_date_format(const wchar_t* begin
, const wchar_t* end
, date_format_parser_callback
< wchar_t >& callback
);
408 template BOOST_LOG_API
409 void parse_time_format(const wchar_t* begin
, const wchar_t* end
, time_format_parser_callback
< wchar_t >& callback
);
410 template BOOST_LOG_API
411 void parse_date_time_format(const wchar_t* begin
, const wchar_t* end
, date_time_format_parser_callback
< wchar_t >& callback
);
412 template BOOST_LOG_API
413 void put_integer(boost::log::aux::basic_ostringstreambuf
< wchar_t >& strbuf
, uint32_t value
, unsigned int width
, wchar_t fill_char
);
415 #endif // BOOST_LOG_USE_WCHAR_T
419 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
423 #include <boost/log/detail/footer.hpp>