]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/src/date_time_format_parser.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / log / src / date_time_format_parser.cpp
1 /*
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)
6 */
7 /*!
8 * \file date_time_format_parser.cpp
9 * \author Andrey Semashev
10 * \date 30.09.2012
11 *
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.
14 */
15
16 #include <boost/log/detail/config.hpp>
17 #include <cstring>
18 #include <string>
19 #include <algorithm>
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>
26
27 namespace karma = boost::spirit::karma;
28
29 namespace boost {
30
31 BOOST_LOG_OPEN_NAMESPACE
32
33 namespace aux {
34
35 BOOST_LOG_ANONYMOUS_NAMESPACE {
36
37 template< typename CharT >
38 struct string_constants;
39
40 #ifdef BOOST_LOG_USE_CHAR
41
42 template< >
43 struct string_constants< char >
44 {
45 typedef char char_type;
46
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"; }
49
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"; }
53 };
54
55 #endif // BOOST_LOG_USE_CHAR
56
57 #ifdef BOOST_LOG_USE_WCHAR_T
58
59 template< >
60 struct string_constants< wchar_t >
61 {
62 typedef wchar_t char_type;
63
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"; }
66
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"; }
70 };
71
72 #endif // BOOST_LOG_USE_WCHAR_T
73
74 template< typename CallbackT >
75 struct common_flags
76 {
77 typedef CallbackT callback_type;
78 typedef typename callback_type::char_type char_type;
79 typedef std::basic_string< char_type > string_type;
80
81 const char_type* parse(const char_type* begin, const char_type* end, callback_type& callback)
82 {
83 switch (begin[1])
84 {
85 case '%':
86 m_literal.push_back('%');
87 break;
88
89 default:
90 flush(callback);
91 callback.on_placeholder(iterator_range< const char_type* >(begin, begin + 2));
92 break;
93 }
94
95 return begin + 2;
96 }
97
98 void add_literal(const char_type* begin, const char_type* end)
99 {
100 m_literal.append(begin, end);
101 }
102
103 void flush(callback_type& callback)
104 {
105 if (!m_literal.empty())
106 {
107 const char_type* p = m_literal.c_str();
108 callback.on_literal(iterator_range< const char_type* >(p, p + m_literal.size()));
109 m_literal.clear();
110 }
111 }
112
113 private:
114 string_type m_literal;
115 };
116
117 template< typename BaseT >
118 struct date_flags :
119 public BaseT
120 {
121 typedef typename BaseT::callback_type callback_type;
122 typedef typename BaseT::char_type char_type;
123
124 const char_type* parse(const char_type* begin, const char_type* end, callback_type& callback)
125 {
126 typedef string_constants< char_type > constants;
127
128 switch (begin[1])
129 {
130 case 'Y':
131 {
132 this->flush(callback);
133
134 std::size_t len = end - begin;
135 if (len >= 8 && std::memcmp(begin, constants::extended_iso_date_format(), 8 * sizeof(char_type)) == 0)
136 {
137 callback.on_extended_iso_date();
138 return begin + 8;
139 }
140 else if (len >= 6 && std::memcmp(begin, constants::iso_date_format(), 6 * sizeof(char_type)) == 0)
141 {
142 callback.on_iso_date();
143 return begin + 6;
144 }
145 else
146 {
147 callback.on_full_year();
148 }
149 }
150 break;
151
152 case 'y':
153 this->flush(callback);
154 callback.on_short_year();
155 break;
156
157 case 'm':
158 this->flush(callback);
159 callback.on_numeric_month();
160 break;
161
162 case 'B':
163 this->flush(callback);
164 callback.on_full_month();
165 break;
166
167 case 'b':
168 this->flush(callback);
169 callback.on_short_month();
170 break;
171
172 case 'd':
173 this->flush(callback);
174 callback.on_month_day(true);
175 break;
176
177 case 'e':
178 this->flush(callback);
179 callback.on_month_day(false);
180 break;
181
182 case 'w':
183 this->flush(callback);
184 callback.on_numeric_week_day();
185 break;
186
187 case 'A':
188 this->flush(callback);
189 callback.on_full_week_day();
190 break;
191
192 case 'a':
193 this->flush(callback);
194 callback.on_short_week_day();
195 break;
196
197 default:
198 return BaseT::parse(begin, end, callback);
199 }
200
201 return begin + 2;
202 }
203 };
204
205 template< typename BaseT >
206 struct time_flags :
207 public BaseT
208 {
209 typedef typename BaseT::callback_type callback_type;
210 typedef typename BaseT::char_type char_type;
211
212 const char_type* parse(const char_type* begin, const char_type* end, callback_type& callback)
213 {
214 typedef string_constants< char_type > constants;
215
216 switch (begin[1])
217 {
218 case 'O':
219 case 'H':
220 {
221 this->flush(callback);
222
223 std::size_t len = end - begin;
224 if (len >= 11 && std::memcmp(begin, constants::default_time_format(), 11 * sizeof(char_type)) == 0)
225 {
226 callback.on_default_time();
227 return begin + 11;
228 }
229 else if (len >= 8 && std::memcmp(begin, constants::extended_iso_time_format(), 8 * sizeof(char_type)) == 0)
230 {
231 callback.on_extended_iso_time();
232 return begin + 8;
233 }
234 else if (len >= 6 && std::memcmp(begin, constants::iso_time_format(), 6 * sizeof(char_type)) == 0)
235 {
236 callback.on_iso_time();
237 return begin + 6;
238 }
239 else
240 {
241 callback.on_hours(true);
242 }
243 }
244 break;
245
246 case 'T':
247 this->flush(callback);
248 callback.on_extended_iso_time();
249 break;
250
251 case 'k':
252 this->flush(callback);
253 callback.on_hours(false);
254 break;
255
256 case 'I':
257 this->flush(callback);
258 callback.on_hours_12(true);
259 break;
260
261 case 'l':
262 this->flush(callback);
263 callback.on_hours_12(false);
264 break;
265
266 case 'M':
267 this->flush(callback);
268 callback.on_minutes();
269 break;
270
271 case 'S':
272 this->flush(callback);
273 callback.on_seconds();
274 break;
275
276 case 'f':
277 this->flush(callback);
278 callback.on_fractional_seconds();
279 break;
280
281 case 'P':
282 this->flush(callback);
283 callback.on_am_pm(false);
284 break;
285
286 case 'p':
287 this->flush(callback);
288 callback.on_am_pm(true);
289 break;
290
291 case 'Q':
292 this->flush(callback);
293 callback.on_extended_iso_time_zone();
294 break;
295
296 case 'q':
297 this->flush(callback);
298 callback.on_iso_time_zone();
299 break;
300
301 case '-':
302 this->flush(callback);
303 callback.on_duration_sign(false);
304 break;
305
306 case '+':
307 this->flush(callback);
308 callback.on_duration_sign(true);
309 break;
310
311 default:
312 return BaseT::parse(begin, end, callback);
313 }
314
315 return begin + 2;
316 }
317 };
318
319 template< typename CharT, typename ParserT, typename CallbackT >
320 inline void parse_format(const CharT* begin, const CharT* end, ParserT& parser, CallbackT& callback)
321 {
322 typedef CharT char_type;
323
324 while (begin != end)
325 {
326 const char_type* p = std::find(begin, end, static_cast< char_type >('%'));
327 parser.add_literal(begin, p);
328
329 if ((end - p) >= 2)
330 {
331 begin = parser.parse(p, end, callback);
332 }
333 else
334 {
335 if (p != end)
336 parser.add_literal(p, end); // a single '%' character at the end of the string
337 begin = end;
338 }
339 }
340
341 parser.flush(callback);
342 }
343
344 } // namespace
345
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)
349 {
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);
354 }
355
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)
359 {
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);
364 }
365
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)
369 {
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);
374 }
375
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)
378 {
379 typedef CharT char_type;
380 char_type buf[std::numeric_limits< uint32_t >::digits10 + 2];
381 char_type* p = buf;
382
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;
386 if (len < width)
387 strbuf.append(width - len, fill_char);
388 strbuf.append(buf, len);
389 }
390
391 #ifdef BOOST_LOG_USE_CHAR
392
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);
401
402 #endif // BOOST_LOG_USE_CHAR
403
404 #ifdef BOOST_LOG_USE_WCHAR_T
405
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);
414
415 #endif // BOOST_LOG_USE_WCHAR_T
416
417 } // namespace aux
418
419 BOOST_LOG_CLOSE_NAMESPACE // namespace log
420
421 } // namespace boost
422
423 #include <boost/log/detail/footer.hpp>