]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/if.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 17.11.2012 | |
11 | * | |
12 | * The header contains implementation of a conditional formatter. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_ | |
17 | ||
18 | #include <boost/mpl/bool.hpp> | |
19 | #include <boost/phoenix/core/actor.hpp> | |
20 | #include <boost/phoenix/core/meta_grammar.hpp> | |
21 | #include <boost/phoenix/core/terminal_fwd.hpp> | |
22 | #include <boost/phoenix/core/is_nullary.hpp> | |
23 | #include <boost/phoenix/core/environment.hpp> | |
24 | #include <boost/fusion/sequence/intrinsic/at_c.hpp> | |
25 | #include <boost/type_traits/remove_cv.hpp> | |
26 | #include <boost/type_traits/remove_reference.hpp> | |
27 | #include <boost/log/detail/config.hpp> | |
28 | #include <boost/log/detail/custom_terminal_spec.hpp> | |
29 | #include <boost/log/detail/header.hpp> | |
30 | ||
31 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
32 | #pragma once | |
33 | #endif | |
34 | ||
35 | namespace boost { | |
36 | ||
37 | BOOST_LOG_OPEN_NAMESPACE | |
38 | ||
39 | namespace expressions { | |
40 | ||
41 | namespace aux { | |
42 | ||
43 | template< typename LeftT, typename CondT, typename ThenT > | |
44 | class if_output_terminal | |
45 | { | |
46 | private: | |
47 | //! Self type | |
48 | typedef if_output_terminal this_type; | |
49 | ||
50 | public: | |
51 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
52 | //! Internal typedef for type categorization | |
53 | typedef void _is_boost_log_terminal; | |
54 | #endif | |
55 | ||
56 | //! Result type definition | |
57 | template< typename > | |
58 | struct result; | |
59 | ||
60 | template< typename ThisT, typename ContextT > | |
61 | struct result< ThisT(ContextT) > | |
62 | { | |
63 | typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; | |
64 | typedef typename phoenix::evaluator::impl< | |
65 | typename LeftT::proto_base_expr&, | |
66 | context_type, | |
67 | phoenix::unused | |
68 | >::result_type type; | |
69 | }; | |
70 | ||
71 | private: | |
72 | //! Left argument actor | |
73 | LeftT m_left; | |
74 | //! Condition expression | |
75 | CondT m_cond; | |
76 | //! Positive branch | |
77 | ThenT m_then; | |
78 | ||
79 | public: | |
80 | //! Initializing constructor | |
81 | if_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_) : m_left(left), m_cond(cond), m_then(then_) | |
82 | { | |
83 | } | |
84 | ||
85 | //! Invokation operator | |
86 | template< typename ContextT > | |
87 | typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) | |
88 | { | |
89 | typedef typename result< this_type(ContextT const&) >::type result_type; | |
90 | result_type strm = phoenix::eval(m_left, ctx); | |
91 | if (phoenix::eval(m_cond, ctx)) | |
92 | phoenix::eval(m_then, ctx); | |
93 | return strm; | |
94 | } | |
95 | ||
96 | //! Invokation operator | |
97 | template< typename ContextT > | |
98 | typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const | |
99 | { | |
100 | typedef typename result< const this_type(ContextT const&) >::type result_type; | |
101 | result_type strm = phoenix::eval(m_left, ctx); | |
102 | if (phoenix::eval(m_cond, ctx)) | |
103 | phoenix::eval(m_then, ctx); | |
104 | return strm; | |
105 | } | |
106 | ||
107 | BOOST_DELETED_FUNCTION(if_output_terminal()) | |
108 | }; | |
109 | ||
110 | template< typename LeftT, typename CondT, typename ThenT, typename ElseT > | |
111 | class if_else_output_terminal | |
112 | { | |
113 | private: | |
114 | //! Self type | |
115 | typedef if_else_output_terminal this_type; | |
116 | ||
117 | public: | |
118 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
119 | //! Internal typedef for type categorization | |
120 | typedef void _is_boost_log_terminal; | |
121 | #endif | |
122 | ||
123 | //! Result type definition | |
124 | template< typename > | |
125 | struct result; | |
126 | ||
127 | template< typename ThisT, typename ContextT > | |
128 | struct result< ThisT(ContextT) > | |
129 | { | |
130 | typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; | |
131 | typedef typename phoenix::evaluator::impl< | |
132 | typename LeftT::proto_base_expr&, | |
133 | context_type, | |
134 | phoenix::unused | |
135 | >::result_type type; | |
136 | }; | |
137 | ||
138 | private: | |
139 | //! Left argument actor | |
140 | LeftT m_left; | |
141 | //! Condition expression | |
142 | CondT m_cond; | |
143 | //! Positive branch | |
144 | ThenT m_then; | |
145 | //! Negative branch | |
146 | ElseT m_else; | |
147 | ||
148 | public: | |
149 | //! Initializing constructor | |
150 | if_else_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_, ElseT const& else_) : m_left(left), m_cond(cond), m_then(then_), m_else(else_) | |
151 | { | |
152 | } | |
153 | ||
154 | //! Invokation operator | |
155 | template< typename ContextT > | |
156 | typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) | |
157 | { | |
158 | typedef typename result< this_type(ContextT const&) >::type result_type; | |
159 | result_type strm = phoenix::eval(m_left, ctx); | |
160 | if (phoenix::eval(m_cond, ctx)) | |
161 | phoenix::eval(m_then, ctx); | |
162 | else | |
163 | phoenix::eval(m_else, ctx); | |
164 | return strm; | |
165 | } | |
166 | ||
167 | //! Invokation operator | |
168 | template< typename ContextT > | |
169 | typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const | |
170 | { | |
171 | typedef typename result< const this_type(ContextT const&) >::type result_type; | |
172 | result_type strm = phoenix::eval(m_left, ctx); | |
173 | if (phoenix::eval(m_cond, ctx)) | |
174 | phoenix::eval(m_then, ctx); | |
175 | else | |
176 | phoenix::eval(m_else, ctx); | |
177 | return strm; | |
178 | } | |
179 | ||
180 | BOOST_DELETED_FUNCTION(if_else_output_terminal()) | |
181 | }; | |
182 | ||
183 | ||
184 | template< typename CondT, typename ThenT, typename ElseT > | |
185 | struct if_then_else_gen | |
186 | { | |
187 | CondT m_cond; | |
188 | ThenT m_then; | |
189 | ElseT m_else; | |
190 | ||
191 | if_then_else_gen(CondT const& cond, ThenT const& then_, ElseT const& else_) : m_cond(cond), m_then(then_), m_else(else_) | |
192 | { | |
193 | } | |
194 | }; | |
195 | ||
196 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
197 | ||
198 | #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ | |
199 | template< typename LeftExprT, typename CondT, typename ThenT, typename ElseT >\ | |
200 | BOOST_FORCEINLINE phoenix::actor< if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > >\ | |
201 | operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_else_gen< CondT, ThenT, ElseT > right_ref right)\ | |
202 | {\ | |
203 | typedef if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > terminal_type;\ | |
204 | phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.m_cond, right.m_then, right.m_else) }};\ | |
205 | return actor;\ | |
206 | } | |
207 | ||
208 | #include <boost/log/detail/generate_overloads.hpp> | |
209 | ||
210 | #undef BOOST_LOG_AUX_OVERLOAD | |
211 | ||
212 | #endif // BOOST_LOG_DOXYGEN_PASS | |
213 | ||
214 | template< typename CondT, typename ThenT > | |
215 | struct if_then_gen | |
216 | { | |
217 | struct else_gen | |
218 | { | |
219 | CondT m_cond; | |
220 | ThenT m_then; | |
221 | ||
222 | else_gen(CondT const& cond, ThenT const& then_) : m_cond(cond), m_then(then_) | |
223 | { | |
224 | } | |
225 | ||
226 | template< typename ElseT > | |
227 | BOOST_FORCEINLINE if_then_else_gen< CondT, ThenT, ElseT > operator[] (ElseT const& el) | |
228 | { | |
229 | return if_then_else_gen< CondT, ThenT, ElseT >(m_cond, m_then, el); | |
230 | } | |
231 | } | |
232 | else_; | |
233 | ||
234 | if_then_gen(CondT const& cond, ThenT const& then_) : else_(cond, then_) {} | |
235 | }; | |
236 | ||
237 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
238 | ||
239 | #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ | |
240 | template< typename LeftExprT, typename CondT, typename ThenT >\ | |
241 | BOOST_FORCEINLINE phoenix::actor< if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > >\ | |
242 | operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_gen< CondT, ThenT > right_ref right)\ | |
243 | {\ | |
244 | typedef if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > terminal_type;\ | |
245 | phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.else_.m_cond, right.else_.m_then) }};\ | |
246 | return actor;\ | |
247 | } | |
248 | ||
249 | #include <boost/log/detail/generate_overloads.hpp> | |
250 | ||
251 | #undef BOOST_LOG_AUX_OVERLOAD | |
252 | ||
253 | #endif // BOOST_LOG_DOXYGEN_PASS | |
254 | ||
255 | template< typename CondT > | |
256 | class if_gen | |
257 | { | |
258 | private: | |
259 | CondT const& m_cond; | |
260 | ||
261 | public: | |
262 | explicit if_gen(CondT const& cond) : m_cond(cond) | |
263 | { | |
264 | } | |
265 | ||
266 | template< typename ThenT > | |
267 | BOOST_FORCEINLINE if_then_gen< CondT, ThenT > operator[] (ThenT const& then_) const | |
268 | { | |
269 | return if_then_gen< CondT, ThenT >(m_cond, then_); | |
270 | } | |
271 | }; | |
272 | ||
273 | } // namespace aux | |
274 | ||
275 | /*! | |
276 | * The function returns a conditional formatter generator object. The generator provides <tt>operator[]</tt> that can be used | |
277 | * to construct the actual formatter. The formatter must participate in a streaming expression. | |
278 | * | |
279 | * \param cond A filter expression that will be used as the condition | |
280 | */ | |
281 | template< typename CondT > | |
282 | BOOST_FORCEINLINE aux::if_gen< CondT > if_(CondT const& cond) | |
283 | { | |
284 | return aux::if_gen< CondT >(cond); | |
285 | } | |
286 | ||
287 | } // namespace expressions | |
288 | ||
289 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
290 | ||
291 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
292 | ||
293 | namespace phoenix { | |
294 | ||
295 | namespace result_of { | |
296 | ||
297 | template< typename LeftT, typename CondT, typename ThenT > | |
298 | struct is_nullary< custom_terminal< boost::log::expressions::aux::if_output_terminal< LeftT, CondT, ThenT > > > : | |
299 | public mpl::false_ | |
300 | { | |
301 | }; | |
302 | ||
303 | template< typename LeftT, typename CondT, typename ThenT, typename ElseT > | |
304 | struct is_nullary< custom_terminal< boost::log::expressions::aux::if_else_output_terminal< LeftT, CondT, ThenT, ElseT > > > : | |
305 | public mpl::false_ | |
306 | { | |
307 | }; | |
308 | ||
309 | } // namespace result_of | |
310 | ||
311 | } // namespace phoenix | |
312 | ||
313 | #endif | |
314 | ||
315 | } // namespace boost | |
316 | ||
317 | #include <boost/log/detail/footer.hpp> | |
318 | ||
319 | #endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_ |