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