]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/log/sources/record_ostream.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / log / sources / record_ostream.hpp
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 record_ostream.hpp
9 * \author Andrey Semashev
10 * \date 09.03.2009
11 *
12 * This header contains a wrapper class around a logging record that allows to compose the
13 * record message with a streaming expression.
14 */
15
16 #ifndef BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
17 #define BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
18
19 #include <string>
20 #include <iosfwd>
21 #include <ostream>
22 #include <boost/assert.hpp>
23 #include <boost/move/core.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/type_traits/is_enum.hpp>
26 #include <boost/type_traits/is_scalar.hpp>
27 #include <boost/type_traits/remove_cv.hpp>
28 #include <boost/core/addressof.hpp>
29 #include <boost/core/enable_if.hpp>
30 #include <boost/core/explicit_operator_bool.hpp>
31 #include <boost/log/detail/config.hpp>
32 #include <boost/log/detail/native_typeof.hpp>
33 #include <boost/log/detail/unhandled_exception_count.hpp>
34 #include <boost/log/core/record.hpp>
35 #include <boost/log/utility/unique_identifier_name.hpp>
36 #include <boost/log/utility/formatting_ostream.hpp>
37 #include <boost/log/detail/header.hpp>
38
39 #ifdef BOOST_HAS_PRAGMA_ONCE
40 #pragma once
41 #endif
42
43 namespace boost {
44
45 BOOST_LOG_OPEN_NAMESPACE
46
47 template< typename CharT >
48 class basic_record_ostream;
49
50 namespace aux {
51
52 template< typename StreamT, typename T, bool ByValueV, typename R >
53 struct enable_record_ostream_generic_operator {};
54 template< typename CharT, typename T, typename R >
55 struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, false, R > :
56 public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
57 {
58 };
59 template< typename CharT, typename T, typename R >
60 struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, true, R > :
61 public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
62 {
63 };
64
65 } // namespace aux
66
67 /*!
68 * \brief Logging record adapter with a streaming capability
69 *
70 * This class allows to compose the logging record message by streaming operations. It
71 * aggregates the log record and provides the standard output stream interface.
72 */
73 template< typename CharT >
74 class basic_record_ostream :
75 public basic_formatting_ostream< CharT >
76 {
77 //! Self type
78 typedef basic_record_ostream< CharT > this_type;
79 //! Base stream class
80 typedef basic_formatting_ostream< CharT > base_type;
81
82 public:
83 //! Character type
84 typedef CharT char_type;
85 //! String type to be used as a message text holder
86 typedef std::basic_string< char_type > string_type;
87 //! Stream type
88 typedef std::basic_ostream< char_type > stream_type;
89 //! Character traits
90 typedef typename base_type::traits_type traits_type;
91
92 private:
93 //! Log record
94 record* m_record;
95
96 public:
97 /*!
98 * Default constructor. Creates an empty record that is equivalent to the invalid record handle.
99 * The stream capability is not available after construction.
100 *
101 * \post <tt>!*this == true</tt>
102 */
103 basic_record_ostream() BOOST_NOEXCEPT : m_record(NULL) {}
104
105 /*!
106 * Constructor from a record object. Attaches to the provided record.
107 *
108 * \pre <tt>!!rec == true</tt>
109 * \post <tt>&this->get_record() == &rec</tt>
110 * \param rec The record handle being attached to
111 */
112 explicit basic_record_ostream(record& rec)
113 {
114 BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
115 m_record = &rec;
116 init_stream();
117 }
118
119 /*!
120 * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
121 */
122 ~basic_record_ostream() BOOST_NOEXCEPT
123 {
124 detach_from_record();
125 }
126
127 /*!
128 * Conversion to an unspecified boolean type
129 *
130 * \return \c true, if stream is valid and ready for formatting, \c false, if the stream is not valid. The latter also applies to
131 * the case when the stream is not attached to a log record.
132 */
133 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
134
135 /*!
136 * Inverted conversion to an unspecified boolean type
137 *
138 * \return \c false, if stream is valid and ready for formatting, \c true, if the stream is not valid. The latter also applies to
139 * the case when the stream is not attached to a log record.
140 */
141 bool operator! () const BOOST_NOEXCEPT
142 {
143 return (!m_record || base_type::fail());
144 }
145
146 /*!
147 * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
148 *
149 * \return The aggregated record object
150 */
151 record& get_record()
152 {
153 BOOST_ASSERT(m_record != NULL);
154 this->flush();
155 return *m_record;
156 }
157
158 /*!
159 * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
160 *
161 * \return The aggregated record object
162 */
163 record const& get_record() const
164 {
165 BOOST_ASSERT(m_record != NULL);
166 const_cast< this_type* >(this)->flush();
167 return *m_record;
168 }
169
170 /*!
171 * If the stream is attached to a log record, flushes internal buffers to complete all pending formatting operations.
172 * Then reattaches the stream to another log record.
173 *
174 * \param rec New log record to attach to
175 */
176 void attach_record(record& rec)
177 {
178 BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
179 detach_from_record();
180 m_record = &rec;
181 init_stream();
182 }
183
184 //! The function resets the stream into a detached (default initialized) state
185 BOOST_LOG_API void detach_from_record() BOOST_NOEXCEPT;
186
187 basic_record_ostream& operator<< (typename base_type::ios_base_manip manip)
188 {
189 static_cast< base_type& >(*this) << manip;
190 return *this;
191 }
192 basic_record_ostream& operator<< (typename base_type::basic_ios_manip manip)
193 {
194 static_cast< base_type& >(*this) << manip;
195 return *this;
196 }
197 basic_record_ostream& operator<< (typename base_type::stream_manip manip)
198 {
199 static_cast< base_type& >(*this) << manip;
200 return *this;
201 }
202
203 basic_record_ostream& operator<< (char c)
204 {
205 static_cast< base_type& >(*this) << c;
206 return *this;
207 }
208 basic_record_ostream& operator<< (const char* p)
209 {
210 static_cast< base_type& >(*this) << p;
211 return *this;
212 }
213
214 // When no native character type is supported, the following overloads are disabled as they have ambiguous meaning.
215 // Use basic_string_view or basic_string to explicitly indicate that the data is a string.
216 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
217 basic_record_ostream& operator<< (wchar_t c)
218 {
219 static_cast< base_type& >(*this) << c;
220 return *this;
221 }
222 basic_record_ostream& operator<< (const wchar_t* p)
223 {
224 static_cast< base_type& >(*this) << p;
225 return *this;
226 }
227 #endif
228 #if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
229 #if !defined(BOOST_NO_CXX11_CHAR16_T)
230 basic_record_ostream& operator<< (char16_t c)
231 {
232 static_cast< base_type& >(*this) << c;
233 return *this;
234 }
235 basic_record_ostream& operator<< (const char16_t* p)
236 {
237 static_cast< base_type& >(*this) << p;
238 return *this;
239 }
240 #endif
241 #if !defined(BOOST_NO_CXX11_CHAR32_T)
242 basic_record_ostream& operator<< (char32_t c)
243 {
244 static_cast< base_type& >(*this) << c;
245 return *this;
246 }
247 basic_record_ostream& operator<< (const char32_t* p)
248 {
249 static_cast< base_type& >(*this) << p;
250 return *this;
251 }
252 #endif
253 #endif
254
255 basic_record_ostream& operator<< (bool value)
256 {
257 static_cast< base_type& >(*this) << value;
258 return *this;
259 }
260 basic_record_ostream& operator<< (signed char value)
261 {
262 static_cast< base_type& >(*this) << value;
263 return *this;
264 }
265 basic_record_ostream& operator<< (unsigned char value)
266 {
267 static_cast< base_type& >(*this) << value;
268 return *this;
269 }
270 basic_record_ostream& operator<< (short value)
271 {
272 static_cast< base_type& >(*this) << value;
273 return *this;
274 }
275 basic_record_ostream& operator<< (unsigned short value)
276 {
277 static_cast< base_type& >(*this) << value;
278 return *this;
279 }
280 basic_record_ostream& operator<< (int value)
281 {
282 static_cast< base_type& >(*this) << value;
283 return *this;
284 }
285 basic_record_ostream& operator<< (unsigned int value)
286 {
287 static_cast< base_type& >(*this) << value;
288 return *this;
289 }
290 basic_record_ostream& operator<< (long value)
291 {
292 static_cast< base_type& >(*this) << value;
293 return *this;
294 }
295 basic_record_ostream& operator<< (unsigned long value)
296 {
297 static_cast< base_type& >(*this) << value;
298 return *this;
299 }
300 #if !defined(BOOST_NO_LONG_LONG)
301 basic_record_ostream& operator<< (long long value)
302 {
303 static_cast< base_type& >(*this) << value;
304 return *this;
305 }
306 basic_record_ostream& operator<< (unsigned long long value)
307 {
308 static_cast< base_type& >(*this) << value;
309 return *this;
310 }
311 #endif
312
313 basic_record_ostream& operator<< (float value)
314 {
315 static_cast< base_type& >(*this) << value;
316 return *this;
317 }
318 basic_record_ostream& operator<< (double value)
319 {
320 static_cast< base_type& >(*this) << value;
321 return *this;
322 }
323 basic_record_ostream& operator<< (long double value)
324 {
325 static_cast< base_type& >(*this) << value;
326 return *this;
327 }
328
329 basic_record_ostream& operator<< (const void* value)
330 {
331 static_cast< base_type& >(*this) << value;
332 return *this;
333 }
334
335 basic_record_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
336 {
337 static_cast< base_type& >(*this) << buf;
338 return *this;
339 }
340
341 private:
342 //! The function initializes the stream and the stream buffer
343 BOOST_LOG_API void init_stream();
344
345 // Copy and assignment are closed
346 BOOST_DELETED_FUNCTION(basic_record_ostream(basic_record_ostream const&))
347 BOOST_DELETED_FUNCTION(basic_record_ostream& operator= (basic_record_ostream const&))
348 };
349
350
351 #ifdef BOOST_LOG_USE_CHAR
352 typedef basic_record_ostream< char > record_ostream; //!< Convenience typedef for narrow-character logging
353 #endif
354 #ifdef BOOST_LOG_USE_WCHAR_T
355 typedef basic_record_ostream< wchar_t > wrecord_ostream; //!< Convenience typedef for wide-character logging
356 #endif
357
358 // Implementation note: these operators below should be the least attractive for the compiler
359 // so that user's overloads are chosen, when present. We use function template partial ordering for this purpose.
360 // We also don't use perfect forwarding for the right hand argument because in ths case the generic overload
361 // would be more preferred than the typical one written by users:
362 //
363 // record_ostream& operator<< (record_ostream& strm, my_type const& arg);
364 //
365 // This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required
366 // if there is a perfect forwarding overload.
367 template< typename StreamT, typename T >
368 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, true, StreamT& >::type
369 operator<< (StreamT& strm, T value)
370 {
371 typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
372 static_cast< formatting_ostream_type& >(strm) << value;
373 return strm;
374 }
375
376 template< typename StreamT, typename T >
377 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
378 operator<< (StreamT& strm, T const& value)
379 {
380 typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
381 static_cast< formatting_ostream_type& >(strm) << value;
382 return strm;
383 }
384
385 template< typename StreamT, typename T >
386 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
387 operator<< (StreamT& strm, T& value)
388 {
389 typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
390 static_cast< formatting_ostream_type& >(strm) << value;
391 return strm;
392 }
393
394 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
395
396 template< typename StreamT, typename T >
397 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, true, StreamT& >::type
398 operator<< (StreamT&& strm, T value)
399 {
400 typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
401 static_cast< formatting_ostream_type& >(strm) << value;
402 return strm;
403 }
404
405 template< typename StreamT, typename T >
406 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
407 operator<< (StreamT&& strm, T const& value)
408 {
409 typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
410 static_cast< formatting_ostream_type& >(strm) << value;
411 return strm;
412 }
413
414 template< typename StreamT, typename T >
415 inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
416 operator<< (StreamT&& strm, T& value)
417 {
418 typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
419 static_cast< formatting_ostream_type& >(strm) << value;
420 return strm;
421 }
422
423 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
424
425 namespace aux {
426
427 //! Internal class that provides formatting streams for record pumps
428 template< typename CharT >
429 struct stream_provider
430 {
431 //! Character type
432 typedef CharT char_type;
433
434 //! Formatting stream compound
435 struct stream_compound
436 {
437 stream_compound* next;
438
439 //! Log record stream adapter
440 basic_record_ostream< char_type > stream;
441
442 //! Initializing constructor
443 explicit stream_compound(record& rec) : next(NULL), stream(rec) {}
444 };
445
446 //! The method returns an allocated stream compound
447 BOOST_LOG_API static stream_compound* allocate_compound(record& rec);
448 //! The method releases a compound
449 BOOST_LOG_API static void release_compound(stream_compound* compound) BOOST_NOEXCEPT;
450
451 // Non-constructible, non-copyable, non-assignable
452 BOOST_DELETED_FUNCTION(stream_provider())
453 BOOST_DELETED_FUNCTION(stream_provider(stream_provider const&))
454 BOOST_DELETED_FUNCTION(stream_provider& operator= (stream_provider const&))
455 };
456
457
458 /*!
459 * \brief Logging record pump implementation
460 *
461 * The pump is used to format the logging record message text and then
462 * push it to the logging core. It is constructed on each attempt to write
463 * a log record and destroyed afterwards.
464 *
465 * The pump class template is instantiated on the logger type.
466 */
467 template< typename LoggerT >
468 class record_pump
469 {
470 BOOST_MOVABLE_BUT_NOT_COPYABLE(record_pump)
471
472 private:
473 //! Logger type
474 typedef LoggerT logger_type;
475 //! Character type
476 typedef typename logger_type::char_type char_type;
477 //! Stream compound provider
478 typedef stream_provider< char_type > stream_provider_type;
479 //! Stream compound type
480 typedef typename stream_provider_type::stream_compound stream_compound;
481
482 //! Stream compound release guard
483 class auto_release;
484 friend class auto_release;
485 class auto_release
486 {
487 stream_compound* m_pCompound;
488
489 public:
490 explicit auto_release(stream_compound* p) BOOST_NOEXCEPT : m_pCompound(p) {}
491 ~auto_release() BOOST_NOEXCEPT { stream_provider_type::release_compound(m_pCompound); }
492 };
493
494 protected:
495 //! A reference to the logger
496 logger_type* m_pLogger;
497 //! Stream compound
498 stream_compound* m_pStreamCompound;
499 //! Exception state
500 const unsigned int m_ExceptionCount;
501
502 public:
503 //! Constructor
504 explicit record_pump(logger_type& lg, record& rec) :
505 m_pLogger(boost::addressof(lg)),
506 m_pStreamCompound(stream_provider_type::allocate_compound(rec)),
507 m_ExceptionCount(unhandled_exception_count())
508 {
509 }
510 //! Move constructor
511 record_pump(BOOST_RV_REF(record_pump) that) BOOST_NOEXCEPT :
512 m_pLogger(that.m_pLogger),
513 m_pStreamCompound(that.m_pStreamCompound),
514 m_ExceptionCount(that.m_ExceptionCount)
515 {
516 that.m_pLogger = 0;
517 that.m_pStreamCompound = 0;
518 }
519 //! Destructor. Pushes the composed message to log.
520 ~record_pump() BOOST_NOEXCEPT_IF(false)
521 {
522 if (m_pLogger)
523 {
524 auto_release cleanup(m_pStreamCompound); // destructor doesn't throw
525 // Only push the record if no exception has been thrown in the streaming expression (if possible)
526 if (m_ExceptionCount >= unhandled_exception_count())
527 m_pLogger->push_record(boost::move(m_pStreamCompound->stream.get_record()));
528 }
529 }
530
531 //! Returns the stream to be used for message text formatting
532 basic_record_ostream< char_type >& stream() const BOOST_NOEXCEPT
533 {
534 BOOST_ASSERT(m_pStreamCompound != 0);
535 return m_pStreamCompound->stream;
536 }
537 };
538
539 template< typename LoggerT >
540 BOOST_FORCEINLINE record_pump< LoggerT > make_record_pump(LoggerT& lg, record& rec)
541 {
542 return record_pump< LoggerT >(lg, rec);
543 }
544
545 } // namespace aux
546
547 #ifndef BOOST_LOG_DOXYGEN_PASS
548
549 #define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\
550 for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\
551 ::boost::log::aux::make_record_pump((logger), rec_var).stream()
552
553 #define BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, rec_var, params_seq)\
554 for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\
555 ::boost::log::aux::make_record_pump((logger), rec_var).stream()
556
557 #endif // BOOST_LOG_DOXYGEN_PASS
558
559 //! The macro writes a record to the log
560 #define BOOST_LOG_STREAM(logger)\
561 BOOST_LOG_STREAM_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_))
562
563 //! The macro writes a record to the log and allows to pass additional named arguments to the logger
564 #define BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)\
565 BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_), params_seq)
566
567 #ifndef BOOST_LOG_NO_SHORTHAND_NAMES
568
569 //! An equivalent to BOOST_LOG_STREAM(logger)
570 #define BOOST_LOG(logger) BOOST_LOG_STREAM(logger)
571
572 //! An equivalent to BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
573 #define BOOST_LOG_WITH_PARAMS(logger, params_seq) BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
574
575 #endif // BOOST_LOG_NO_SHORTHAND_NAMES
576
577 BOOST_LOG_CLOSE_NAMESPACE // namespace log
578
579 } // namespace boost
580
581 #include <boost/log/detail/footer.hpp>
582
583 #endif // BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_