| 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 formatters/named_scope.hpp |
| 9 | * \author Andrey Semashev |
| 10 | * \date 11.11.2012 |
| 11 | * |
| 12 | * The header contains a formatter function for named scope attribute values. |
| 13 | */ |
| 14 | |
| 15 | #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_ |
| 16 | #define BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_ |
| 17 | |
| 18 | #include <string> |
| 19 | #include <iterator> |
| 20 | #include <utility> |
| 21 | #include <boost/type_traits/is_same.hpp> |
| 22 | #include <boost/move/core.hpp> |
| 23 | #include <boost/move/utility_core.hpp> |
| 24 | #include <boost/parameter/binding.hpp> |
| 25 | #include <boost/preprocessor/iteration/iterate.hpp> |
| 26 | #include <boost/preprocessor/repetition/enum_params.hpp> |
| 27 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> |
| 28 | #include <boost/phoenix/core/actor.hpp> |
| 29 | #include <boost/phoenix/core/terminal_fwd.hpp> |
| 30 | #include <boost/phoenix/core/is_nullary.hpp> |
| 31 | #include <boost/phoenix/core/environment.hpp> |
| 32 | #include <boost/fusion/sequence/intrinsic/at_c.hpp> |
| 33 | #include <boost/log/detail/config.hpp> |
| 34 | #include <boost/log/attributes/attribute_name.hpp> |
| 35 | #include <boost/log/attributes/fallback_policy.hpp> |
| 36 | #include <boost/log/attributes/named_scope.hpp> |
| 37 | #include <boost/log/attributes/value_visitation.hpp> |
| 38 | #include <boost/log/detail/light_function.hpp> |
| 39 | #include <boost/log/detail/parameter_tools.hpp> |
| 40 | #include <boost/log/detail/custom_terminal_spec.hpp> |
| 41 | #include <boost/log/detail/deduce_char_type.hpp> |
| 42 | #include <boost/log/detail/attr_output_terminal.hpp> |
| 43 | #include <boost/log/expressions/attr_fwd.hpp> |
| 44 | #include <boost/log/expressions/keyword_fwd.hpp> |
| 45 | #include <boost/log/utility/formatting_ostream.hpp> |
| 46 | #include <boost/log/utility/string_literal_fwd.hpp> |
| 47 | #include <boost/log/utility/functional/bind.hpp> |
| 48 | #include <boost/log/keywords/format.hpp> |
| 49 | #include <boost/log/keywords/delimiter.hpp> |
| 50 | #include <boost/log/keywords/depth.hpp> |
| 51 | #include <boost/log/keywords/iteration.hpp> |
| 52 | #include <boost/log/keywords/empty_marker.hpp> |
| 53 | #include <boost/log/keywords/incomplete_marker.hpp> |
| 54 | #include <boost/log/detail/header.hpp> |
| 55 | |
| 56 | #ifdef BOOST_HAS_PRAGMA_ONCE |
| 57 | #pragma once |
| 58 | #endif |
| 59 | |
| 60 | namespace boost { |
| 61 | |
| 62 | BOOST_LOG_OPEN_NAMESPACE |
| 63 | |
| 64 | namespace expressions { |
| 65 | |
| 66 | //! Scope iteration directions |
| 67 | enum scope_iteration_direction |
| 68 | { |
| 69 | forward, //!< Iterate through scopes from outermost to innermost |
| 70 | reverse //!< Iterate through scopes from innermost to outermost |
| 71 | }; |
| 72 | |
| 73 | namespace aux { |
| 74 | |
| 75 | #ifdef BOOST_LOG_USE_CHAR |
| 76 | //! Parses the named scope format string and constructs the formatter function |
| 77 | BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< char >&, attributes::named_scope::value_type::value_type const&) > |
| 78 | parse_named_scope_format(const char* begin, const char* end); |
| 79 | #endif |
| 80 | |
| 81 | #ifdef BOOST_LOG_USE_WCHAR_T |
| 82 | //! Parses the named scope format string and constructs the formatter function |
| 83 | BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< wchar_t >&, attributes::named_scope::value_type::value_type const&) > |
| 84 | parse_named_scope_format(const wchar_t* begin, const wchar_t* end); |
| 85 | #endif |
| 86 | |
| 87 | //! Parses the named scope format string and constructs the formatter function |
| 88 | template< typename CharT > |
| 89 | inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) > |
| 90 | parse_named_scope_format(const CharT* format) |
| 91 | { |
| 92 | return parse_named_scope_format(format, format + std::char_traits< CharT >::length(format)); |
| 93 | } |
| 94 | |
| 95 | //! Parses the named scope format string and constructs the formatter function |
| 96 | template< typename CharT, typename TraitsT, typename AllocatorT > |
| 97 | inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) > |
| 98 | parse_named_scope_format(std::basic_string< CharT, TraitsT, AllocatorT > const& format) |
| 99 | { |
| 100 | const CharT* p = format.c_str(); |
| 101 | return parse_named_scope_format(p, p + format.size()); |
| 102 | } |
| 103 | |
| 104 | //! Parses the named scope format string and constructs the formatter function |
| 105 | template< typename CharT, typename TraitsT > |
| 106 | inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) > |
| 107 | parse_named_scope_format(basic_string_literal< CharT, TraitsT > const& format) |
| 108 | { |
| 109 | const CharT* p = format.c_str(); |
| 110 | return parse_named_scope_format(p, p + format.size()); |
| 111 | } |
| 112 | |
| 113 | template< typename CharT > |
| 114 | class format_named_scope_impl |
| 115 | { |
| 116 | public: |
| 117 | //! Function result type |
| 118 | typedef void result_type; |
| 119 | |
| 120 | //! Character type |
| 121 | typedef CharT char_type; |
| 122 | //! String type |
| 123 | typedef std::basic_string< char_type > string_type; |
| 124 | //! Formatting stream type |
| 125 | typedef basic_formatting_ostream< char_type > stream_type; |
| 126 | //! Attribute value type |
| 127 | typedef attributes::named_scope::value_type value_type; |
| 128 | //! Named scope formatter |
| 129 | typedef boost::log::aux::light_function< void (stream_type&, value_type::value_type const&) > element_formatter_type; |
| 130 | |
| 131 | private: |
| 132 | //! Element formatting function |
| 133 | element_formatter_type m_element_formatter; |
| 134 | //! Element delimiter |
| 135 | string_type m_delimiter; |
| 136 | //! Incomplete list marker |
| 137 | string_type m_incomplete_marker; |
| 138 | //! Empty list marker |
| 139 | string_type m_empty_marker; |
| 140 | //! Maximum number of elements to output |
| 141 | value_type::size_type m_depth; |
| 142 | //! Iteration direction |
| 143 | scope_iteration_direction m_direction; |
| 144 | |
| 145 | public: |
| 146 | //! Initializing constructor |
| 147 | format_named_scope_impl |
| 148 | ( |
| 149 | element_formatter_type const& element_formatter, |
| 150 | string_type const& delimiter, |
| 151 | string_type const& incomplete_marker, |
| 152 | string_type const& empty_marker, |
| 153 | value_type::size_type depth, |
| 154 | scope_iteration_direction direction |
| 155 | ) : |
| 156 | m_element_formatter(element_formatter), |
| 157 | m_delimiter(delimiter), |
| 158 | m_incomplete_marker(incomplete_marker), |
| 159 | m_empty_marker(empty_marker), |
| 160 | m_depth(depth), |
| 161 | m_direction(direction) |
| 162 | { |
| 163 | } |
| 164 | //! Copy constructor |
| 165 | format_named_scope_impl(format_named_scope_impl const& that) : |
| 166 | m_element_formatter(that.m_element_formatter), |
| 167 | m_delimiter(that.m_delimiter), |
| 168 | m_incomplete_marker(that.m_incomplete_marker), |
| 169 | m_empty_marker(that.m_empty_marker), |
| 170 | m_depth(that.m_depth), |
| 171 | m_direction(that.m_direction) |
| 172 | { |
| 173 | } |
| 174 | |
| 175 | //! Formatting operator |
| 176 | result_type operator() (stream_type& strm, value_type const& scopes) const |
| 177 | { |
| 178 | if (!scopes.empty()) |
| 179 | { |
| 180 | if (m_direction == expressions::forward) |
| 181 | format_forward(strm, scopes); |
| 182 | else |
| 183 | format_reverse(strm, scopes); |
| 184 | } |
| 185 | else |
| 186 | { |
| 187 | strm << m_empty_marker; |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | private: |
| 192 | //! The function performs formatting of the extracted scope stack in forward direction |
| 193 | void format_forward(stream_type& strm, value_type const& scopes) const |
| 194 | { |
| 195 | value_type::const_iterator it, end = scopes.end(); |
| 196 | if (m_depth > 0) |
| 197 | { |
| 198 | value_type::size_type const scopes_to_iterate = (std::min)(a: m_depth, b: scopes.size()); |
| 199 | it = scopes.end(); |
| 200 | std::advance(i&: it, n: -static_cast< value_type::difference_type >(scopes_to_iterate)); |
| 201 | } |
| 202 | else |
| 203 | { |
| 204 | it = scopes.begin(); |
| 205 | } |
| 206 | |
| 207 | if (it != end) |
| 208 | { |
| 209 | if (it != scopes.begin()) |
| 210 | strm << m_incomplete_marker; |
| 211 | |
| 212 | m_element_formatter(strm, *it); |
| 213 | for (++it; it != end; ++it) |
| 214 | { |
| 215 | strm << m_delimiter; |
| 216 | m_element_formatter(strm, *it); |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | //! The function performs formatting of the extracted scope stack in reverse direction |
| 221 | void format_reverse(stream_type& strm, value_type const& scopes) const |
| 222 | { |
| 223 | value_type::const_reverse_iterator it = scopes.rbegin(), end; |
| 224 | if (m_depth > 0) |
| 225 | { |
| 226 | value_type::size_type const scopes_to_iterate = (std::min)(a: m_depth, b: scopes.size()); |
| 227 | end = it; |
| 228 | std::advance(i&: end, n: static_cast< value_type::difference_type >(scopes_to_iterate)); |
| 229 | } |
| 230 | else |
| 231 | { |
| 232 | end = scopes.rend(); |
| 233 | } |
| 234 | |
| 235 | if (it != end) |
| 236 | { |
| 237 | m_element_formatter(strm, *it); |
| 238 | for (++it; it != end; ++it) |
| 239 | { |
| 240 | strm << m_delimiter; |
| 241 | m_element_formatter(strm, *it); |
| 242 | } |
| 243 | |
| 244 | if (it != scopes.rend()) |
| 245 | strm << m_incomplete_marker; |
| 246 | } |
| 247 | } |
| 248 | }; |
| 249 | |
| 250 | } // namespace aux |
| 251 | |
| 252 | /*! |
| 253 | * Named scope formatter terminal. |
| 254 | */ |
| 255 | template< typename FallbackPolicyT, typename CharT > |
| 256 | class format_named_scope_terminal |
| 257 | { |
| 258 | public: |
| 259 | #ifndef BOOST_LOG_DOXYGEN_PASS |
| 260 | //! Internal typedef for type categorization |
| 261 | typedef void _is_boost_log_terminal; |
| 262 | #endif |
| 263 | |
| 264 | //! Attribute value type |
| 265 | typedef attributes::named_scope::value_type value_type; |
| 266 | //! Fallback policy |
| 267 | typedef FallbackPolicyT fallback_policy; |
| 268 | //! Character type |
| 269 | typedef CharT char_type; |
| 270 | //! String type |
| 271 | typedef std::basic_string< char_type > string_type; |
| 272 | //! Formatting stream type |
| 273 | typedef basic_formatting_ostream< char_type > stream_type; |
| 274 | //! Formatter function |
| 275 | typedef aux::format_named_scope_impl< char_type > formatter_function_type; |
| 276 | |
| 277 | //! Function result type |
| 278 | typedef string_type result_type; |
| 279 | |
| 280 | private: |
| 281 | //! Attribute value visitor invoker |
| 282 | typedef value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type; |
| 283 | |
| 284 | private: |
| 285 | //! Attribute name |
| 286 | attribute_name m_name; |
| 287 | //! Formatter function |
| 288 | formatter_function_type m_formatter; |
| 289 | //! Attribute value visitor invoker |
| 290 | visitor_invoker_type m_visitor_invoker; |
| 291 | |
| 292 | public: |
| 293 | //! Initializing constructor |
| 294 | template< typename FormatT > |
| 295 | format_named_scope_terminal |
| 296 | ( |
| 297 | attribute_name const& name, |
| 298 | fallback_policy const& fallback, |
| 299 | FormatT const& element_format, |
| 300 | string_type const& delimiter, |
| 301 | string_type const& incomplete_marker, |
| 302 | string_type const& empty_marker, |
| 303 | value_type::size_type depth, |
| 304 | scope_iteration_direction direction |
| 305 | ) : |
| 306 | m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, incomplete_marker, empty_marker, depth, direction), m_visitor_invoker(fallback) |
| 307 | { |
| 308 | } |
| 309 | //! Copy constructor |
| 310 | format_named_scope_terminal(format_named_scope_terminal const& that) : |
| 311 | m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker) |
| 312 | { |
| 313 | } |
| 314 | |
| 315 | //! Returns attribute name |
| 316 | attribute_name get_name() const |
| 317 | { |
| 318 | return m_name; |
| 319 | } |
| 320 | |
| 321 | //! Returns fallback policy |
| 322 | fallback_policy const& get_fallback_policy() const |
| 323 | { |
| 324 | return m_visitor_invoker.get_fallback_policy(); |
| 325 | } |
| 326 | |
| 327 | //! Retruns formatter function |
| 328 | formatter_function_type const& get_formatter_function() const |
| 329 | { |
| 330 | return m_formatter; |
| 331 | } |
| 332 | |
| 333 | //! Invokation operator |
| 334 | template< typename ContextT > |
| 335 | result_type operator() (ContextT const& ctx) |
| 336 | { |
| 337 | string_type str; |
| 338 | stream_type strm(str); |
| 339 | m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm)); |
| 340 | strm.flush(); |
| 341 | return BOOST_LOG_NRVO_RESULT(str); |
| 342 | } |
| 343 | |
| 344 | //! Invokation operator |
| 345 | template< typename ContextT > |
| 346 | result_type operator() (ContextT const& ctx) const |
| 347 | { |
| 348 | string_type str; |
| 349 | stream_type strm(str); |
| 350 | m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm)); |
| 351 | strm.flush(); |
| 352 | return BOOST_LOG_NRVO_RESULT(str); |
| 353 | } |
| 354 | |
| 355 | BOOST_DELETED_FUNCTION(format_named_scope_terminal()) |
| 356 | }; |
| 357 | |
| 358 | /*! |
| 359 | * Named scope formatter actor. |
| 360 | */ |
| 361 | template< typename FallbackPolicyT, typename CharT, template< typename > class ActorT = phoenix::actor > |
| 362 | class format_named_scope_actor : |
| 363 | public ActorT< format_named_scope_terminal< FallbackPolicyT, CharT > > |
| 364 | { |
| 365 | public: |
| 366 | //! Character type |
| 367 | typedef CharT char_type; |
| 368 | //! Fallback policy |
| 369 | typedef FallbackPolicyT fallback_policy; |
| 370 | //! Base terminal type |
| 371 | typedef format_named_scope_terminal< fallback_policy, char_type > terminal_type; |
| 372 | //! Attribute value type |
| 373 | typedef typename terminal_type::value_type value_type; |
| 374 | //! Formatter function |
| 375 | typedef typename terminal_type::formatter_function_type formatter_function_type; |
| 376 | |
| 377 | //! Base actor type |
| 378 | typedef ActorT< terminal_type > base_type; |
| 379 | |
| 380 | public: |
| 381 | //! Initializing constructor |
| 382 | explicit format_named_scope_actor(base_type const& act) : base_type(act) |
| 383 | { |
| 384 | } |
| 385 | |
| 386 | /*! |
| 387 | * \returns The attribute name |
| 388 | */ |
| 389 | attribute_name get_name() const |
| 390 | { |
| 391 | return this->proto_expr_.child0.get_name(); |
| 392 | } |
| 393 | |
| 394 | /*! |
| 395 | * \returns Fallback policy |
| 396 | */ |
| 397 | fallback_policy const& get_fallback_policy() const |
| 398 | { |
| 399 | return this->proto_expr_.child0.get_fallback_policy(); |
| 400 | } |
| 401 | |
| 402 | /*! |
| 403 | * \returns Formatter function |
| 404 | */ |
| 405 | formatter_function_type const& get_formatter_function() const |
| 406 | { |
| 407 | return this->proto_expr_.child0.get_formatter_function(); |
| 408 | } |
| 409 | }; |
| 410 | |
| 411 | #ifndef BOOST_LOG_DOXYGEN_PASS |
| 412 | |
| 413 | #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ |
| 414 | template< typename LeftExprT, typename FallbackPolicyT, typename CharT >\ |
| 415 | BOOST_FORCEINLINE phoenix::actor< aux::attribute_output_terminal< phoenix::actor< LeftExprT >, attributes::named_scope::value_type, FallbackPolicyT, typename format_named_scope_actor< FallbackPolicyT, CharT >::formatter_function_type > >\ |
| 416 | operator<< (phoenix::actor< LeftExprT > left_ref left, format_named_scope_actor< FallbackPolicyT, CharT > right_ref right)\ |
| 417 | {\ |
| 418 | typedef aux::attribute_output_terminal< phoenix::actor< LeftExprT >, attributes::named_scope::value_type, FallbackPolicyT, typename format_named_scope_actor< FallbackPolicyT, CharT >::formatter_function_type > terminal_type;\ |
| 419 | phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_name(), right.get_formatter_function(), right.get_fallback_policy()) }};\ |
| 420 | return actor;\ |
| 421 | } |
| 422 | |
| 423 | #include <boost/log/detail/generate_overloads.hpp> |
| 424 | |
| 425 | #undef BOOST_LOG_AUX_OVERLOAD |
| 426 | |
| 427 | #endif // BOOST_LOG_DOXYGEN_PASS |
| 428 | |
| 429 | namespace aux { |
| 430 | |
| 431 | //! Auxiliary traits to acquire default formatter parameters depending on the character type |
| 432 | template< typename CharT > |
| 433 | struct default_named_scope_params; |
| 434 | |
| 435 | #ifdef BOOST_LOG_USE_CHAR |
| 436 | template< > |
| 437 | struct default_named_scope_params< char > |
| 438 | { |
| 439 | static const char* forward_delimiter() { return "->" ; } |
| 440 | static const char* reverse_delimiter() { return "<-" ; } |
| 441 | static const char* incomplete_marker() { return "..." ; } |
| 442 | static const char* empty_marker() { return "" ; } |
| 443 | }; |
| 444 | #endif |
| 445 | #ifdef BOOST_LOG_USE_WCHAR_T |
| 446 | template< > |
| 447 | struct default_named_scope_params< wchar_t > |
| 448 | { |
| 449 | static const wchar_t* forward_delimiter() { return L"->" ; } |
| 450 | static const wchar_t* reverse_delimiter() { return L"<-" ; } |
| 451 | static const wchar_t* incomplete_marker() { return L"..." ; } |
| 452 | static const wchar_t* empty_marker() { return L"" ; } |
| 453 | }; |
| 454 | #endif |
| 455 | |
| 456 | template< typename CharT, template< typename > class ActorT, typename FallbackPolicyT, typename ArgsT > |
| 457 | BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > format_named_scope(attribute_name const& name, FallbackPolicyT const& fallback, ArgsT const& args) |
| 458 | { |
| 459 | typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type; |
| 460 | typedef typename actor_type::terminal_type terminal_type; |
| 461 | typedef default_named_scope_params< CharT > default_params; |
| 462 | scope_iteration_direction dir = args[keywords::iteration | expressions::forward]; |
| 463 | const CharT* default_delimiter = (dir == expressions::forward ? default_params::forward_delimiter() : default_params::reverse_delimiter()); |
| 464 | typename actor_type::base_type act = |
| 465 | {{ |
| 466 | terminal_type |
| 467 | ( |
| 468 | name, |
| 469 | fallback, |
| 470 | args[keywords::format], |
| 471 | args[keywords::delimiter | default_delimiter], |
| 472 | args[keywords::incomplete_marker | default_params::incomplete_marker()], |
| 473 | args[keywords::empty_marker | default_params::empty_marker()], |
| 474 | args[keywords::depth | static_cast< attributes::named_scope::value_type::size_type >(0)], |
| 475 | dir |
| 476 | ) |
| 477 | }}; |
| 478 | return actor_type(act); |
| 479 | } |
| 480 | |
| 481 | } // namespace aux |
| 482 | |
| 483 | /*! |
| 484 | * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting |
| 485 | * expression (stream output or \c format placeholder filler). |
| 486 | * |
| 487 | * \param name Attribute name |
| 488 | * \param element_format Format string for a single named scope |
| 489 | */ |
| 490 | template< typename CharT > |
| 491 | BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, const CharT* element_format) |
| 492 | { |
| 493 | typedef format_named_scope_actor< fallback_to_none, CharT > actor_type; |
| 494 | typedef typename actor_type::terminal_type terminal_type; |
| 495 | typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }}; |
| 496 | return actor_type(act); |
| 497 | } |
| 498 | |
| 499 | /*! |
| 500 | * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting |
| 501 | * expression (stream output or \c format placeholder filler). |
| 502 | * |
| 503 | * \param name Attribute name |
| 504 | * \param element_format Format string for a single named scope |
| 505 | */ |
| 506 | template< typename CharT > |
| 507 | BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, std::basic_string< CharT > const& element_format) |
| 508 | { |
| 509 | typedef format_named_scope_actor< fallback_to_none, CharT > actor_type; |
| 510 | typedef typename actor_type::terminal_type terminal_type; |
| 511 | typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }}; |
| 512 | return actor_type(act); |
| 513 | } |
| 514 | |
| 515 | /*! |
| 516 | * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting |
| 517 | * expression (stream output or \c format placeholder filler). |
| 518 | * |
| 519 | * \param keyword Attribute keyword |
| 520 | * \param element_format Format string for a single named scope |
| 521 | */ |
| 522 | template< typename DescriptorT, template< typename > class ActorT, typename CharT > |
| 523 | BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT > |
| 524 | format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, const CharT* element_format) |
| 525 | { |
| 526 | static_assert(is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value, |
| 527 | "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type." ); |
| 528 | |
| 529 | typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type; |
| 530 | typedef typename actor_type::terminal_type terminal_type; |
| 531 | typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }}; |
| 532 | return actor_type(act); |
| 533 | } |
| 534 | |
| 535 | /*! |
| 536 | * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting |
| 537 | * expression (stream output or \c format placeholder filler). |
| 538 | * |
| 539 | * \param keyword Attribute keyword |
| 540 | * \param element_format Format string for a single named scope |
| 541 | */ |
| 542 | template< typename DescriptorT, template< typename > class ActorT, typename CharT > |
| 543 | BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT > |
| 544 | format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, std::basic_string< CharT > const& element_format) |
| 545 | { |
| 546 | static_assert(is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value, |
| 547 | "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type." ); |
| 548 | |
| 549 | typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type; |
| 550 | typedef typename actor_type::terminal_type terminal_type; |
| 551 | typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }}; |
| 552 | return actor_type(act); |
| 553 | } |
| 554 | |
| 555 | /*! |
| 556 | * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting |
| 557 | * expression (stream output or \c format placeholder filler). |
| 558 | * |
| 559 | * \param placeholder Attribute placeholder |
| 560 | * \param element_format Format string for a single named scope |
| 561 | */ |
| 562 | template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT > |
| 563 | BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > |
| 564 | format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, const CharT* element_format) |
| 565 | { |
| 566 | static_assert(is_same< T, attributes::named_scope::value_type >::value, |
| 567 | "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type." ); |
| 568 | |
| 569 | typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type; |
| 570 | typedef typename actor_type::terminal_type terminal_type; |
| 571 | typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }}; |
| 572 | return actor_type(act); |
| 573 | } |
| 574 | |
| 575 | /*! |
| 576 | * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting |
| 577 | * expression (stream output or \c format placeholder filler). |
| 578 | * |
| 579 | * \param placeholder Attribute placeholder |
| 580 | * \param element_format Format string for a single named scope |
| 581 | */ |
| 582 | template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT > |
| 583 | BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > |
| 584 | format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, std::basic_string< CharT > const& element_format) |
| 585 | { |
| 586 | static_assert(is_same< T, attributes::named_scope::value_type >::value, |
| 587 | "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type." ); |
| 588 | |
| 589 | typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type; |
| 590 | typedef typename actor_type::terminal_type terminal_type; |
| 591 | typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }}; |
| 592 | return actor_type(act); |
| 593 | } |
| 594 | |
| 595 | #if !defined(BOOST_LOG_DOXYGEN_PASS) |
| 596 | |
| 597 | # define BOOST_PP_FILENAME_1 <boost/log/detail/named_scope_fmt_pp.hpp> |
| 598 | # define BOOST_PP_ITERATION_LIMITS (1, 6) |
| 599 | # include BOOST_PP_ITERATE() |
| 600 | |
| 601 | #else // BOOST_LOG_DOXYGEN_PASS |
| 602 | |
| 603 | /*! |
| 604 | * Formatter generator. Construct the named scope formatter with the specified formatting parameters. |
| 605 | * |
| 606 | * \param name Attribute name |
| 607 | * \param args An set of named parameters. Supported parameters: |
| 608 | * \li \c format - A format string for named scopes. The string can contain "%n", "%f" and "%l" placeholders for the scope name, file and line number, respectively. This parameter is mandatory. |
| 609 | * \li \c delimiter - A string that is used to delimit the formatted scope names. Default: "->" or "<-", depending on the iteration direction. |
| 610 | * \li \c incomplete_marker - A string that is used to indicate that the list was printed incomplete because of depth limitation. Default: "...". |
| 611 | * \li \c empty_marker - A string that is output in case if the scope list is empty. Default: "", i.e. nothing is output. |
| 612 | * \li \c iteration - Iteration direction, see \c scope_iteration_direction enumeration. Default: forward. |
| 613 | * \li \c depth - Iteration depth. Default: unlimited. |
| 614 | */ |
| 615 | template< typename... ArgsT > |
| 616 | unspecified format_named_scope(attribute_name const& name, ArgsT... const& args); |
| 617 | |
| 618 | /*! \overload */ |
| 619 | template< typename DescriptorT, template< typename > class ActorT, typename... ArgsT > |
| 620 | unspecified format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, ArgsT... const& args); |
| 621 | |
| 622 | /*! \overload */ |
| 623 | template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename... ArgsT > |
| 624 | unspecified format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, ArgsT... const& args); |
| 625 | |
| 626 | #endif // BOOST_LOG_DOXYGEN_PASS |
| 627 | |
| 628 | } // namespace expressions |
| 629 | |
| 630 | BOOST_LOG_CLOSE_NAMESPACE // namespace log |
| 631 | |
| 632 | #ifndef BOOST_LOG_DOXYGEN_PASS |
| 633 | |
| 634 | namespace phoenix { |
| 635 | |
| 636 | namespace result_of { |
| 637 | |
| 638 | template< typename FallbackPolicyT, typename CharT > |
| 639 | struct is_nullary< custom_terminal< boost::log::expressions::format_named_scope_terminal< FallbackPolicyT, CharT > > > : |
| 640 | public mpl::false_ |
| 641 | { |
| 642 | }; |
| 643 | |
| 644 | } // namespace result_of |
| 645 | |
| 646 | } // namespace phoenix |
| 647 | |
| 648 | #endif |
| 649 | |
| 650 | } // namespace boost |
| 651 | |
| 652 | #include <boost/log/detail/footer.hpp> |
| 653 | |
| 654 | #endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_ |
| 655 | |