• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/wrap_formatter.hpp
9  * \author Andrey Semashev
10  * \date   24.11.2012
11  *
12  * The header contains a formatter function wrapper that enables third-party functions to participate in formatting expressions.
13  */
14 
15 #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_
16 #define BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_
17 
18 #include <string>
19 #include <boost/move/core.hpp>
20 #include <boost/move/utility_core.hpp>
21 #include <boost/mpl/has_xxx.hpp>
22 #include <boost/phoenix/core/actor.hpp>
23 #include <boost/phoenix/core/terminal_fwd.hpp>
24 #include <boost/phoenix/core/is_nullary.hpp>
25 #include <boost/phoenix/core/environment.hpp>
26 #include <boost/type_traits/remove_cv.hpp>
27 #include <boost/type_traits/remove_reference.hpp>
28 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
29 #include <boost/log/detail/config.hpp>
30 #include <boost/log/detail/custom_terminal_spec.hpp>
31 #include <boost/log/detail/function_traits.hpp>
32 #include <boost/log/utility/formatting_ostream.hpp>
33 #include <boost/log/detail/header.hpp>
34 
35 #ifdef BOOST_HAS_PRAGMA_ONCE
36 #pragma once
37 #endif
38 
39 namespace boost {
40 
41 BOOST_LOG_OPEN_NAMESPACE
42 
43 namespace expressions {
44 
45 namespace aux {
46 
47 //! Wrapped formatter stream output terminal
48 template< typename LeftT, typename FunT >
49 class wrapped_formatter_output_terminal
50 {
51 private:
52     //! Self type
53     typedef wrapped_formatter_output_terminal< LeftT, FunT > this_type;
54 
55 public:
56 #ifndef BOOST_LOG_DOXYGEN_PASS
57     //! Internal typedef for type categorization
58     typedef void _is_boost_log_terminal;
59 #endif
60 
61     //! Wrapped function type
62     typedef FunT function_type;
63 
64     //! Result type definition
65     template< typename >
66     struct result;
67 
68     template< typename ThisT, typename ContextT >
69     struct result< ThisT(ContextT) >
70     {
71         typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
72         typedef typename phoenix::evaluator::impl<
73             typename LeftT::proto_base_expr&,
74             context_type,
75             phoenix::unused
76         >::result_type type;
77     };
78 
79 private:
80     //! Left argument actor
81     LeftT m_left;
82     //! Wrapped function
83     function_type m_fun;
84 
85 public:
86     //! Initializing constructor
wrapped_formatter_output_terminal(LeftT const & left,function_type const & fun)87     wrapped_formatter_output_terminal(LeftT const& left, function_type const& fun) : m_left(left), m_fun(fun)
88     {
89     }
90     //! Copy constructor
wrapped_formatter_output_terminal(wrapped_formatter_output_terminal const & that)91     wrapped_formatter_output_terminal(wrapped_formatter_output_terminal const& that) : m_left(that.m_left), m_fun(that.m_fun)
92     {
93     }
94 
95     //! Invokation operator
96     template< typename ContextT >
operator ()(ContextT const & ctx)97     typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
98     {
99         typedef typename result< this_type(ContextT const&) >::type result_type;
100         result_type strm = phoenix::eval(m_left, ctx);
101         m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
102         return strm;
103     }
104 
105     //! Invokation operator
106     template< typename ContextT >
operator ()(ContextT const & ctx) const107     typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
108     {
109         typedef typename result< const this_type(ContextT const&) >::type result_type;
110         result_type strm = phoenix::eval(m_left, ctx);
111         m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
112         return strm;
113     }
114 
115     BOOST_DELETED_FUNCTION(wrapped_formatter_output_terminal())
116 };
117 
118 BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_char_type, char_type, false)
119 
120 template<
121     typename FunT,
122     bool HasCharTypeV = has_char_type< FunT >::value,
123     bool HasSecondArgumentV = boost::log::aux::has_second_argument_type< FunT >::value,
124     bool HasArg2V = boost::log::aux::has_arg2_type< FunT >::value
125 >
126 struct default_char_type
127 {
128     // Use this char type if all detection fails
129     typedef char type;
130 };
131 
132 template< typename FunT, bool HasSecondArgumentV, bool HasArg2V >
133 struct default_char_type< FunT, true, HasSecondArgumentV, HasArg2V >
134 {
135     typedef typename FunT::char_type type;
136 };
137 
138 template< typename FunT, bool HasArg2V >
139 struct default_char_type< FunT, false, true, HasArg2V >
140 {
141     typedef typename remove_cv< typename remove_reference< typename FunT::second_argument_type >::type >::type argument_type;
142     typedef typename argument_type::char_type type;
143 };
144 
145 template< typename FunT >
146 struct default_char_type< FunT, false, false, true >
147 {
148     typedef typename remove_cv< typename remove_reference< typename FunT::arg2_type >::type >::type argument_type;
149     typedef typename argument_type::char_type type;
150 };
151 
152 } // namespace aux
153 
154 /*!
155  * Formatter function wrapper terminal.
156  */
157 template< typename FunT, typename CharT >
158 class wrapped_formatter_terminal
159 {
160 public:
161 #ifndef BOOST_LOG_DOXYGEN_PASS
162     //! Internal typedef for type categorization
163     typedef void _is_boost_log_terminal;
164 #endif
165 
166     //! Character type
167     typedef CharT char_type;
168     //! String type
169     typedef std::basic_string< char_type > string_type;
170     //! Formatting stream type
171     typedef basic_formatting_ostream< char_type > stream_type;
172     //! Wrapped function type
173     typedef FunT function_type;
174 
175     //! Formatter result type
176     typedef string_type result_type;
177 
178 private:
179     //! Wrapped function
180     function_type m_fun;
181 
182 public:
183     //! Initializing construction
wrapped_formatter_terminal(function_type const & fun)184     explicit wrapped_formatter_terminal(function_type const& fun) : m_fun(fun)
185     {
186     }
187     //! Copy constructor
wrapped_formatter_terminal(wrapped_formatter_terminal const & that)188     wrapped_formatter_terminal(wrapped_formatter_terminal const& that) : m_fun(that.m_fun)
189     {
190     }
191 
192     //! Returns the wrapped function
get_function() const193     function_type const& get_function() const
194     {
195         return m_fun;
196     }
197 
198     //! Invokation operator
199     template< typename ContextT >
operator ()(ContextT const & ctx)200     result_type operator() (ContextT const& ctx)
201     {
202         string_type str;
203         stream_type strm(str);
204         m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
205         strm.flush();
206         return BOOST_LOG_NRVO_RESULT(str);
207     }
208 
209     //! Invokation operator
210     template< typename ContextT >
operator ()(ContextT const & ctx) const211     result_type operator() (ContextT const& ctx) const
212     {
213         string_type str;
214         stream_type strm(str);
215         m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm);
216         strm.flush();
217         return BOOST_LOG_NRVO_RESULT(str);
218     }
219 };
220 
221 /*!
222  * Wrapped formatter function actor.
223  */
224 template< typename FunT, typename CharT, template< typename > class ActorT = phoenix::actor >
225 class wrapped_formatter_actor :
226     public ActorT< wrapped_formatter_terminal< FunT, CharT > >
227 {
228 public:
229     //! Character type
230     typedef CharT char_type;
231     //! Wrapped function type
232     typedef FunT function_type;
233     //! Base terminal type
234     typedef wrapped_formatter_terminal< function_type, char_type > terminal_type;
235 
236     //! Base actor type
237     typedef ActorT< terminal_type > base_type;
238 
239 public:
240     //! Initializing constructor
wrapped_formatter_actor(base_type const & act)241     explicit wrapped_formatter_actor(base_type const& act) : base_type(act)
242     {
243     }
244 
245     /*!
246      * \returns The wrapped function
247      */
get_function() const248     function_type const& get_function() const
249     {
250         return this->proto_expr_.child0.get_function();
251     }
252 };
253 
254 #ifndef BOOST_LOG_DOXYGEN_PASS
255 
256 #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
257     template< typename LeftExprT, typename FunT, typename CharT >\
258     BOOST_FORCEINLINE phoenix::actor< aux::wrapped_formatter_output_terminal< phoenix::actor< LeftExprT >, FunT > >\
259     operator<< (phoenix::actor< LeftExprT > left_ref left, wrapped_formatter_actor< FunT, CharT > right_ref right)\
260     {\
261         typedef aux::wrapped_formatter_output_terminal< phoenix::actor< LeftExprT >, FunT > terminal_type;\
262         phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_function()) }};\
263         return actor;\
264     }
265 
266 #include <boost/log/detail/generate_overloads.hpp>
267 
268 #undef BOOST_LOG_AUX_OVERLOAD
269 
270 #endif // BOOST_LOG_DOXYGEN_PASS
271 
272 /*!
273  * The function wraps a function object in order it to be able to participate in formatting expressions. The wrapped
274  * function object must be compatible with the following signature:
275  *
276  * <pre>
277  * void (record_view const&, basic_formatting_ostream< CharT >&)
278  * </pre>
279  *
280  * where \c CharT is the character type of the formatting expression.
281  */
282 template< typename FunT >
wrap_formatter(FunT const & fun)283 BOOST_FORCEINLINE wrapped_formatter_actor< FunT, typename aux::default_char_type< FunT >::type > wrap_formatter(FunT const& fun)
284 {
285     typedef wrapped_formatter_actor< FunT, typename aux::default_char_type< FunT >::type > actor_type;
286     typedef typename actor_type::terminal_type terminal_type;
287     typename actor_type::base_type act = {{ terminal_type(fun) }};
288     return actor_type(act);
289 }
290 
291 /*!
292  * The function wraps a function object in order it to be able to participate in formatting expressions. The wrapped
293  * function object must be compatible with the following signature:
294  *
295  * <pre>
296  * void (record_view const&, basic_formatting_ostream< CharT >&)
297  * </pre>
298  *
299  * where \c CharT is the character type of the formatting expression.
300  */
301 template< typename CharT, typename FunT >
wrap_formatter(FunT const & fun)302 BOOST_FORCEINLINE wrapped_formatter_actor< FunT, CharT > wrap_formatter(FunT const& fun)
303 {
304     typedef wrapped_formatter_actor< FunT, CharT > actor_type;
305     typedef typename actor_type::terminal_type terminal_type;
306     typename actor_type::base_type act = {{ terminal_type(fun) }};
307     return actor_type(act);
308 }
309 
310 } // namespace expressions
311 
312 BOOST_LOG_CLOSE_NAMESPACE // namespace log
313 
314 #ifndef BOOST_LOG_DOXYGEN_PASS
315 
316 namespace phoenix {
317 
318 namespace result_of {
319 
320 template< typename LeftT, typename FunT >
321 struct is_nullary< custom_terminal< boost::log::expressions::aux::wrapped_formatter_output_terminal< LeftT, FunT > > > :
322     public mpl::false_
323 {
324 };
325 
326 template< typename FunT, typename CharT >
327 struct is_nullary< custom_terminal< boost::log::expressions::wrapped_formatter_terminal< FunT, CharT > > > :
328     public mpl::false_
329 {
330 };
331 
332 } // namespace result_of
333 
334 } // namespace phoenix
335 
336 #endif
337 
338 } // namespace boost
339 
340 #include <boost/log/detail/footer.hpp>
341 
342 #endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_
343