named_scope.hpp 25 KB

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