File indexing completed on 2025-01-18 09:39:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_
0016 #define BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_
0017
0018 #include <string>
0019 #include <iterator>
0020 #include <utility>
0021 #include <boost/type_traits/is_same.hpp>
0022 #include <boost/move/core.hpp>
0023 #include <boost/move/utility_core.hpp>
0024 #include <boost/parameter/binding.hpp>
0025 #include <boost/preprocessor/iteration/iterate.hpp>
0026 #include <boost/preprocessor/repetition/enum_params.hpp>
0027 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0028 #include <boost/phoenix/core/actor.hpp>
0029 #include <boost/phoenix/core/terminal_fwd.hpp>
0030 #include <boost/phoenix/core/is_nullary.hpp>
0031 #include <boost/phoenix/core/environment.hpp>
0032 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
0033 #include <boost/log/detail/config.hpp>
0034 #include <boost/log/attributes/attribute_name.hpp>
0035 #include <boost/log/attributes/fallback_policy.hpp>
0036 #include <boost/log/attributes/named_scope.hpp>
0037 #include <boost/log/attributes/value_visitation.hpp>
0038 #include <boost/log/detail/light_function.hpp>
0039 #include <boost/log/detail/parameter_tools.hpp>
0040 #include <boost/log/detail/custom_terminal_spec.hpp>
0041 #include <boost/log/detail/deduce_char_type.hpp>
0042 #include <boost/log/detail/attr_output_terminal.hpp>
0043 #include <boost/log/expressions/attr_fwd.hpp>
0044 #include <boost/log/expressions/keyword_fwd.hpp>
0045 #include <boost/log/utility/formatting_ostream.hpp>
0046 #include <boost/log/utility/string_literal_fwd.hpp>
0047 #include <boost/log/utility/functional/bind.hpp>
0048 #include <boost/log/keywords/format.hpp>
0049 #include <boost/log/keywords/delimiter.hpp>
0050 #include <boost/log/keywords/depth.hpp>
0051 #include <boost/log/keywords/iteration.hpp>
0052 #include <boost/log/keywords/empty_marker.hpp>
0053 #include <boost/log/keywords/incomplete_marker.hpp>
0054 #include <boost/log/detail/header.hpp>
0055
0056 #ifdef BOOST_HAS_PRAGMA_ONCE
0057 #pragma once
0058 #endif
0059
0060 namespace boost {
0061
0062 BOOST_LOG_OPEN_NAMESPACE
0063
0064 namespace expressions {
0065
0066
0067 enum scope_iteration_direction
0068 {
0069 forward,
0070 reverse
0071 };
0072
0073 namespace aux {
0074
0075 #ifdef BOOST_LOG_USE_CHAR
0076
0077 BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< char >&, attributes::named_scope::value_type::value_type const&) >
0078 parse_named_scope_format(const char* begin, const char* end);
0079 #endif
0080
0081 #ifdef BOOST_LOG_USE_WCHAR_T
0082
0083 BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< wchar_t >&, attributes::named_scope::value_type::value_type const&) >
0084 parse_named_scope_format(const wchar_t* begin, const wchar_t* end);
0085 #endif
0086
0087
0088 template< typename CharT >
0089 inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
0090 parse_named_scope_format(const CharT* format)
0091 {
0092 return parse_named_scope_format(format, format + std::char_traits< CharT >::length(format));
0093 }
0094
0095
0096 template< typename CharT, typename TraitsT, typename AllocatorT >
0097 inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
0098 parse_named_scope_format(std::basic_string< CharT, TraitsT, AllocatorT > const& format)
0099 {
0100 const CharT* p = format.c_str();
0101 return parse_named_scope_format(p, p + format.size());
0102 }
0103
0104
0105 template< typename CharT, typename TraitsT >
0106 inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) >
0107 parse_named_scope_format(basic_string_literal< CharT, TraitsT > const& format)
0108 {
0109 const CharT* p = format.c_str();
0110 return parse_named_scope_format(p, p + format.size());
0111 }
0112
0113 template< typename CharT >
0114 class format_named_scope_impl
0115 {
0116 public:
0117
0118 typedef void result_type;
0119
0120
0121 typedef CharT char_type;
0122
0123 typedef std::basic_string< char_type > string_type;
0124
0125 typedef basic_formatting_ostream< char_type > stream_type;
0126
0127 typedef attributes::named_scope::value_type value_type;
0128
0129 typedef boost::log::aux::light_function< void (stream_type&, value_type::value_type const&) > element_formatter_type;
0130
0131 private:
0132
0133 element_formatter_type m_element_formatter;
0134
0135 string_type m_delimiter;
0136
0137 string_type m_incomplete_marker;
0138
0139 string_type m_empty_marker;
0140
0141 value_type::size_type m_depth;
0142
0143 scope_iteration_direction m_direction;
0144
0145 public:
0146
0147 format_named_scope_impl
0148 (
0149 element_formatter_type const& element_formatter,
0150 string_type const& delimiter,
0151 string_type const& incomplete_marker,
0152 string_type const& empty_marker,
0153 value_type::size_type depth,
0154 scope_iteration_direction direction
0155 ) :
0156 m_element_formatter(element_formatter),
0157 m_delimiter(delimiter),
0158 m_incomplete_marker(incomplete_marker),
0159 m_empty_marker(empty_marker),
0160 m_depth(depth),
0161 m_direction(direction)
0162 {
0163 }
0164
0165 format_named_scope_impl(format_named_scope_impl const& that) :
0166 m_element_formatter(that.m_element_formatter),
0167 m_delimiter(that.m_delimiter),
0168 m_incomplete_marker(that.m_incomplete_marker),
0169 m_empty_marker(that.m_empty_marker),
0170 m_depth(that.m_depth),
0171 m_direction(that.m_direction)
0172 {
0173 }
0174
0175
0176 result_type operator() (stream_type& strm, value_type const& scopes) const
0177 {
0178 if (!scopes.empty())
0179 {
0180 if (m_direction == expressions::forward)
0181 format_forward(strm, scopes);
0182 else
0183 format_reverse(strm, scopes);
0184 }
0185 else
0186 {
0187 strm << m_empty_marker;
0188 }
0189 }
0190
0191 private:
0192
0193 void format_forward(stream_type& strm, value_type const& scopes) const
0194 {
0195 value_type::const_iterator it, end = scopes.end();
0196 if (m_depth > 0)
0197 {
0198 value_type::size_type const scopes_to_iterate = (std::min)(m_depth, scopes.size());
0199 it = scopes.end();
0200 std::advance(it, -static_cast< value_type::difference_type >(scopes_to_iterate));
0201 }
0202 else
0203 {
0204 it = scopes.begin();
0205 }
0206
0207 if (it != end)
0208 {
0209 if (it != scopes.begin())
0210 strm << m_incomplete_marker;
0211
0212 m_element_formatter(strm, *it);
0213 for (++it; it != end; ++it)
0214 {
0215 strm << m_delimiter;
0216 m_element_formatter(strm, *it);
0217 }
0218 }
0219 }
0220
0221 void format_reverse(stream_type& strm, value_type const& scopes) const
0222 {
0223 value_type::const_reverse_iterator it = scopes.rbegin(), end;
0224 if (m_depth > 0)
0225 {
0226 value_type::size_type const scopes_to_iterate = (std::min)(m_depth, scopes.size());
0227 end = it;
0228 std::advance(end, static_cast< value_type::difference_type >(scopes_to_iterate));
0229 }
0230 else
0231 {
0232 end = scopes.rend();
0233 }
0234
0235 if (it != end)
0236 {
0237 m_element_formatter(strm, *it);
0238 for (++it; it != end; ++it)
0239 {
0240 strm << m_delimiter;
0241 m_element_formatter(strm, *it);
0242 }
0243
0244 if (it != scopes.rend())
0245 strm << m_incomplete_marker;
0246 }
0247 }
0248 };
0249
0250 }
0251
0252
0253
0254
0255 template< typename FallbackPolicyT, typename CharT >
0256 class format_named_scope_terminal
0257 {
0258 public:
0259 #ifndef BOOST_LOG_DOXYGEN_PASS
0260
0261 typedef void _is_boost_log_terminal;
0262 #endif
0263
0264
0265 typedef attributes::named_scope::value_type value_type;
0266
0267 typedef FallbackPolicyT fallback_policy;
0268
0269 typedef CharT char_type;
0270
0271 typedef std::basic_string< char_type > string_type;
0272
0273 typedef basic_formatting_ostream< char_type > stream_type;
0274
0275 typedef aux::format_named_scope_impl< char_type > formatter_function_type;
0276
0277
0278 typedef string_type result_type;
0279
0280 private:
0281
0282 typedef value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type;
0283
0284 private:
0285
0286 attribute_name m_name;
0287
0288 formatter_function_type m_formatter;
0289
0290 visitor_invoker_type m_visitor_invoker;
0291
0292 public:
0293
0294 template< typename FormatT >
0295 format_named_scope_terminal
0296 (
0297 attribute_name const& name,
0298 fallback_policy const& fallback,
0299 FormatT const& element_format,
0300 string_type const& delimiter,
0301 string_type const& incomplete_marker,
0302 string_type const& empty_marker,
0303 value_type::size_type depth,
0304 scope_iteration_direction direction
0305 ) :
0306 m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, incomplete_marker, empty_marker, depth, direction), m_visitor_invoker(fallback)
0307 {
0308 }
0309
0310 format_named_scope_terminal(format_named_scope_terminal const& that) :
0311 m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker)
0312 {
0313 }
0314
0315
0316 attribute_name get_name() const
0317 {
0318 return m_name;
0319 }
0320
0321
0322 fallback_policy const& get_fallback_policy() const
0323 {
0324 return m_visitor_invoker.get_fallback_policy();
0325 }
0326
0327
0328 formatter_function_type const& get_formatter_function() const
0329 {
0330 return m_formatter;
0331 }
0332
0333
0334 template< typename ContextT >
0335 result_type operator() (ContextT const& ctx)
0336 {
0337 string_type str;
0338 stream_type strm(str);
0339 m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm));
0340 strm.flush();
0341 return BOOST_LOG_NRVO_RESULT(str);
0342 }
0343
0344
0345 template< typename ContextT >
0346 result_type operator() (ContextT const& ctx) const
0347 {
0348 string_type str;
0349 stream_type strm(str);
0350 m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm));
0351 strm.flush();
0352 return BOOST_LOG_NRVO_RESULT(str);
0353 }
0354
0355 BOOST_DELETED_FUNCTION(format_named_scope_terminal())
0356 };
0357
0358
0359
0360
0361 template< typename FallbackPolicyT, typename CharT, template< typename > class ActorT = phoenix::actor >
0362 class format_named_scope_actor :
0363 public ActorT< format_named_scope_terminal< FallbackPolicyT, CharT > >
0364 {
0365 public:
0366
0367 typedef CharT char_type;
0368
0369 typedef FallbackPolicyT fallback_policy;
0370
0371 typedef format_named_scope_terminal< fallback_policy, char_type > terminal_type;
0372
0373 typedef typename terminal_type::value_type value_type;
0374
0375 typedef typename terminal_type::formatter_function_type formatter_function_type;
0376
0377
0378 typedef ActorT< terminal_type > base_type;
0379
0380 public:
0381
0382 explicit format_named_scope_actor(base_type const& act) : base_type(act)
0383 {
0384 }
0385
0386
0387
0388
0389 attribute_name get_name() const
0390 {
0391 return this->proto_expr_.child0.get_name();
0392 }
0393
0394
0395
0396
0397 fallback_policy const& get_fallback_policy() const
0398 {
0399 return this->proto_expr_.child0.get_fallback_policy();
0400 }
0401
0402
0403
0404
0405 formatter_function_type const& get_formatter_function() const
0406 {
0407 return this->proto_expr_.child0.get_formatter_function();
0408 }
0409 };
0410
0411 #ifndef BOOST_LOG_DOXYGEN_PASS
0412
0413 #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
0414 template< typename LeftExprT, typename FallbackPolicyT, typename CharT >\
0415 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 > >\
0416 operator<< (phoenix::actor< LeftExprT > left_ref left, format_named_scope_actor< FallbackPolicyT, CharT > right_ref right)\
0417 {\
0418 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;\
0419 phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_name(), right.get_formatter_function(), right.get_fallback_policy()) }};\
0420 return actor;\
0421 }
0422
0423 #include <boost/log/detail/generate_overloads.hpp>
0424
0425 #undef BOOST_LOG_AUX_OVERLOAD
0426
0427 #endif
0428
0429 namespace aux {
0430
0431
0432 template< typename CharT >
0433 struct default_named_scope_params;
0434
0435 #ifdef BOOST_LOG_USE_CHAR
0436 template< >
0437 struct default_named_scope_params< char >
0438 {
0439 static const char* forward_delimiter() { return "->"; }
0440 static const char* reverse_delimiter() { return "<-"; }
0441 static const char* incomplete_marker() { return "..."; }
0442 static const char* empty_marker() { return ""; }
0443 };
0444 #endif
0445 #ifdef BOOST_LOG_USE_WCHAR_T
0446 template< >
0447 struct default_named_scope_params< wchar_t >
0448 {
0449 static const wchar_t* forward_delimiter() { return L"->"; }
0450 static const wchar_t* reverse_delimiter() { return L"<-"; }
0451 static const wchar_t* incomplete_marker() { return L"..."; }
0452 static const wchar_t* empty_marker() { return L""; }
0453 };
0454 #endif
0455
0456 template< typename CharT, template< typename > class ActorT, typename FallbackPolicyT, typename ArgsT >
0457 BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > format_named_scope(attribute_name const& name, FallbackPolicyT const& fallback, ArgsT const& args)
0458 {
0459 typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
0460 typedef typename actor_type::terminal_type terminal_type;
0461 typedef default_named_scope_params< CharT > default_params;
0462 scope_iteration_direction dir = args[keywords::iteration | expressions::forward];
0463 const CharT* default_delimiter = (dir == expressions::forward ? default_params::forward_delimiter() : default_params::reverse_delimiter());
0464 typename actor_type::base_type act =
0465 {{
0466 terminal_type
0467 (
0468 name,
0469 fallback,
0470 args[keywords::format],
0471 args[keywords::delimiter | default_delimiter],
0472 args[keywords::incomplete_marker | default_params::incomplete_marker()],
0473 args[keywords::empty_marker | default_params::empty_marker()],
0474 args[keywords::depth | static_cast< attributes::named_scope::value_type::size_type >(0)],
0475 dir
0476 )
0477 }};
0478 return actor_type(act);
0479 }
0480
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490 template< typename CharT >
0491 BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, const CharT* element_format)
0492 {
0493 typedef format_named_scope_actor< fallback_to_none, CharT > actor_type;
0494 typedef typename actor_type::terminal_type terminal_type;
0495 typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }};
0496 return actor_type(act);
0497 }
0498
0499
0500
0501
0502
0503
0504
0505
0506 template< typename CharT >
0507 BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, std::basic_string< CharT > const& element_format)
0508 {
0509 typedef format_named_scope_actor< fallback_to_none, CharT > actor_type;
0510 typedef typename actor_type::terminal_type terminal_type;
0511 typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }};
0512 return actor_type(act);
0513 }
0514
0515
0516
0517
0518
0519
0520
0521
0522 template< typename DescriptorT, template< typename > class ActorT, typename CharT >
0523 BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT >
0524 format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, const CharT* element_format)
0525 {
0526 static_assert(is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value,
0527 "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
0528
0529 typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type;
0530 typedef typename actor_type::terminal_type terminal_type;
0531 typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }};
0532 return actor_type(act);
0533 }
0534
0535
0536
0537
0538
0539
0540
0541
0542 template< typename DescriptorT, template< typename > class ActorT, typename CharT >
0543 BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT >
0544 format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, std::basic_string< CharT > const& element_format)
0545 {
0546 static_assert(is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value,
0547 "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
0548
0549 typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type;
0550 typedef typename actor_type::terminal_type terminal_type;
0551 typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }};
0552 return actor_type(act);
0553 }
0554
0555
0556
0557
0558
0559
0560
0561
0562 template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT >
0563 BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT >
0564 format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, const CharT* element_format)
0565 {
0566 static_assert(is_same< T, attributes::named_scope::value_type >::value,
0567 "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
0568
0569 typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
0570 typedef typename actor_type::terminal_type terminal_type;
0571 typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }};
0572 return actor_type(act);
0573 }
0574
0575
0576
0577
0578
0579
0580
0581
0582 template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT >
0583 BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT >
0584 format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, std::basic_string< CharT > const& element_format)
0585 {
0586 static_assert(is_same< T, attributes::named_scope::value_type >::value,
0587 "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type.");
0588
0589 typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
0590 typedef typename actor_type::terminal_type terminal_type;
0591 typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }};
0592 return actor_type(act);
0593 }
0594
0595 #if !defined(BOOST_LOG_DOXYGEN_PASS)
0596
0597 # define BOOST_PP_FILENAME_1 <boost/log/detail/named_scope_fmt_pp.hpp>
0598 # define BOOST_PP_ITERATION_LIMITS (1, 6)
0599 # include BOOST_PP_ITERATE()
0600
0601 #else
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 template< typename... ArgsT >
0616 unspecified format_named_scope(attribute_name const& name, ArgsT... const& args);
0617
0618
0619 template< typename DescriptorT, template< typename > class ActorT, typename... ArgsT >
0620 unspecified format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, ArgsT... const& args);
0621
0622
0623 template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename... ArgsT >
0624 unspecified format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, ArgsT... const& args);
0625
0626 #endif
0627
0628 }
0629
0630 BOOST_LOG_CLOSE_NAMESPACE
0631
0632 #ifndef BOOST_LOG_DOXYGEN_PASS
0633
0634 namespace phoenix {
0635
0636 namespace result_of {
0637
0638 template< typename FallbackPolicyT, typename CharT >
0639 struct is_nullary< custom_terminal< boost::log::expressions::format_named_scope_terminal< FallbackPolicyT, CharT > > > :
0640 public mpl::false_
0641 {
0642 };
0643
0644 }
0645
0646 }
0647
0648 #endif
0649
0650 }
0651
0652 #include <boost/log/detail/footer.hpp>
0653
0654 #endif