• 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   value_visitation.hpp
9  * \author Andrey Semashev
10  * \date   01.03.2008
11  *
12  * The header contains implementation of convenience tools to apply visitors to an attribute value
13  * in the view.
14  */
15 
16 #ifndef BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_
17 #define BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_
18 
19 #include <boost/core/explicit_operator_bool.hpp>
20 #include <boost/log/detail/config.hpp>
21 #include <boost/log/exceptions.hpp>
22 #include <boost/log/core/record.hpp>
23 #include <boost/log/attributes/attribute_name.hpp>
24 #include <boost/log/attributes/attribute_value.hpp>
25 #include <boost/log/attributes/attribute.hpp>
26 #include <boost/log/attributes/attribute_value_set.hpp>
27 #include <boost/log/attributes/value_visitation_fwd.hpp>
28 #include <boost/log/attributes/fallback_policy.hpp>
29 #include <boost/log/expressions/keyword_fwd.hpp>
30 #include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp>
31 #include <boost/log/detail/header.hpp>
32 
33 #ifdef BOOST_HAS_PRAGMA_ONCE
34 #pragma once
35 #endif
36 
37 namespace boost {
38 
39 BOOST_LOG_OPEN_NAMESPACE
40 
41 /*!
42  * \brief The class represents attribute value visitation result
43  *
44  * The main purpose of this class is to provide a convenient interface for checking
45  * whether the attribute value visitation succeeded or not. It also allows to discover
46  * the actual cause of failure, should the operation fail.
47  */
48 class visitation_result
49 {
50 public:
51     //! Error codes for attribute value visitation
52     enum error_code
53     {
54         ok,                     //!< The attribute value has been visited successfully
55         value_not_found,        //!< The attribute value is not present in the view
56         value_has_invalid_type  //!< The attribute value is present in the view, but has an unexpected type
57     };
58 
59 private:
60     error_code m_code;
61 
62 public:
63     /*!
64      * Initializing constructor. Creates the result that is equivalent to the
65      * specified error code.
66      */
visitation_result(error_code code=ok)67     BOOST_CONSTEXPR visitation_result(error_code code = ok) BOOST_NOEXCEPT : m_code(code) {}
68 
69     /*!
70      * Checks if the visitation was successful.
71      *
72      * \return \c true if the value was visited successfully, \c false otherwise.
73      */
74     BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
75     /*!
76      * Checks if the visitation was unsuccessful.
77      *
78      * \return \c false if the value was visited successfully, \c true otherwise.
79      */
80     bool operator! () const BOOST_NOEXCEPT { return (m_code != ok); }
81 
82     /*!
83      * \return The actual result code of value visitation
84      */
code() const85     error_code code() const BOOST_NOEXCEPT { return m_code; }
86 };
87 
88 /*!
89  * \brief Generic attribute value visitor invoker
90  *
91  * Attribute value invoker is a functional object that attempts to find and extract the stored
92  * attribute value from the attribute value view or a log record. The extracted value is passed to
93  * a unary function object (the visitor) provided by user.
94  *
95  * The invoker can be specialized on one or several attribute value types that should be
96  * specified in the second template argument.
97  */
98 template< typename T, typename FallbackPolicyT >
99 class value_visitor_invoker :
100     private FallbackPolicyT
101 {
102     typedef value_visitor_invoker< T, FallbackPolicyT > this_type;
103 
104 public:
105     //! Attribute value types
106     typedef T value_type;
107 
108     //! Fallback policy
109     typedef FallbackPolicyT fallback_policy;
110 
111     //! Function object result type
112     typedef visitation_result result_type;
113 
114 public:
115     /*!
116      * Default constructor
117      */
value_visitor_invoker()118     BOOST_DEFAULTED_FUNCTION(value_visitor_invoker(), {})
119 
120     /*!
121      * Copy constructor
122      */
123     value_visitor_invoker(value_visitor_invoker const& that) : fallback_policy(static_cast< fallback_policy const& >(that))
124     {
125     }
126 
127     /*!
128      * Initializing constructor
129      *
130      * \param arg Fallback policy argument
131      */
132     template< typename U >
value_visitor_invoker(U const & arg)133     explicit value_visitor_invoker(U const& arg) : fallback_policy(arg) {}
134 
135     /*!
136      * Visitation operator. Attempts to acquire the stored value of one of the supported types. If acquisition succeeds,
137      * the value is passed to \a visitor.
138      *
139      * \param attr An attribute value to apply the visitor to.
140      * \param visitor A receiving function object to pass the attribute value to.
141      * \return The result of visitation.
142      */
143     template< typename VisitorT >
operator ()(attribute_value const & attr,VisitorT visitor) const144     result_type operator() (attribute_value const& attr, VisitorT visitor) const
145     {
146         if (!!attr)
147         {
148             static_type_dispatcher< value_type > disp(visitor);
149             if (attr.dispatch(disp) || fallback_policy::apply_default(visitor))
150             {
151                 return visitation_result::ok;
152             }
153             else
154             {
155                 fallback_policy::on_invalid_type(attr.get_type());
156                 return visitation_result::value_has_invalid_type;
157             }
158         }
159 
160         if (fallback_policy::apply_default(visitor))
161             return visitation_result::ok;
162 
163         fallback_policy::on_missing_value();
164         return visitation_result::value_not_found;
165     }
166 
167     /*!
168      * Visitation operator. Looks for an attribute value with the specified name
169      * and tries to acquire the stored value of one of the supported types. If acquisition succeeds,
170      * the value is passed to \a visitor.
171      *
172      * \param name Attribute value name.
173      * \param attrs A set of attribute values in which to look for the specified attribute value.
174      * \param visitor A receiving function object to pass the attribute value to.
175      * \return The result of visitation.
176      */
177     template< typename VisitorT >
operator ()(attribute_name const & name,attribute_value_set const & attrs,VisitorT visitor) const178     result_type operator() (attribute_name const& name, attribute_value_set const& attrs, VisitorT visitor) const
179     {
180         try
181         {
182             attribute_value_set::const_iterator it = attrs.find(name);
183             if (it != attrs.end())
184                 return operator() (it->second, visitor);
185             else
186                 return operator() (attribute_value(), visitor);
187         }
188         catch (exception& e)
189         {
190             // Attach the attribute name to the exception
191             boost::log::aux::attach_attribute_name_info(e, name);
192             throw;
193         }
194     }
195 
196     /*!
197      * Visitation operator. Looks for an attribute value with the specified name
198      * and tries to acquire the stored value of one of the supported types. If acquisition succeeds,
199      * the value is passed to \a visitor.
200      *
201      * \param name Attribute value name.
202      * \param rec A log record. The attribute value will be sought among those associated with the record.
203      * \param visitor A receiving function object to pass the attribute value to.
204      * \return The result of visitation.
205      */
206     template< typename VisitorT >
operator ()(attribute_name const & name,record const & rec,VisitorT visitor) const207     result_type operator() (attribute_name const& name, record const& rec, VisitorT visitor) const
208     {
209         return operator() (name, rec.attribute_values(), visitor);
210     }
211 
212     /*!
213      * Visitation operator. Looks for an attribute value with the specified name
214      * and tries to acquire the stored value of one of the supported types. If acquisition succeeds,
215      * the value is passed to \a visitor.
216      *
217      * \param name Attribute value name.
218      * \param rec A log record view. The attribute value will be sought among those associated with the record.
219      * \param visitor A receiving function object to pass the attribute value to.
220      * \return The result of visitation.
221      */
222     template< typename VisitorT >
operator ()(attribute_name const & name,record_view const & rec,VisitorT visitor) const223     result_type operator() (attribute_name const& name, record_view const& rec, VisitorT visitor) const
224     {
225         return operator() (name, rec.attribute_values(), visitor);
226     }
227 
228     /*!
229      * \returns Fallback policy
230      */
get_fallback_policy() const231     fallback_policy const& get_fallback_policy() const
232     {
233         return *static_cast< fallback_policy const* >(this);
234     }
235 };
236 
237 /*!
238  * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
239  * type or set of possible types of the attribute value to be visited.
240  *
241  * \param name The name of the attribute value to visit.
242  * \param attrs A set of attribute values in which to look for the specified attribute value.
243  * \param visitor A receiving function object to pass the attribute value to.
244  * \return The result of visitation.
245  */
246 template< typename T, typename VisitorT >
247 inline visitation_result
visit(attribute_name const & name,attribute_value_set const & attrs,VisitorT visitor)248 visit(attribute_name const& name, attribute_value_set const& attrs, VisitorT visitor)
249 {
250     value_visitor_invoker< T > invoker;
251     return invoker(name, attrs, visitor);
252 }
253 
254 /*!
255  * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
256  * type or set of possible types of the attribute value to be visited.
257  *
258  * \param name The name of the attribute value to visit.
259  * \param rec A log record. The attribute value will be sought among those associated with the record.
260  * \param visitor A receiving function object to pass the attribute value to.
261  * \return The result of visitation.
262  */
263 template< typename T, typename VisitorT >
264 inline visitation_result
visit(attribute_name const & name,record const & rec,VisitorT visitor)265 visit(attribute_name const& name, record const& rec, VisitorT visitor)
266 {
267     value_visitor_invoker< T > invoker;
268     return invoker(name, rec, visitor);
269 }
270 
271 /*!
272  * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
273  * type or set of possible types of the attribute value to be visited.
274  *
275  * \param name The name of the attribute value to visit.
276  * \param rec A log record view. The attribute value will be sought among those associated with the record.
277  * \param visitor A receiving function object to pass the attribute value to.
278  * \return The result of visitation.
279  */
280 template< typename T, typename VisitorT >
281 inline visitation_result
visit(attribute_name const & name,record_view const & rec,VisitorT visitor)282 visit(attribute_name const& name, record_view const& rec, VisitorT visitor)
283 {
284     value_visitor_invoker< T > invoker;
285     return invoker(name, rec, visitor);
286 }
287 
288 /*!
289  * The function applies a visitor to an attribute value. The user has to explicitly specify the
290  * type or set of possible types of the attribute value to be visited.
291  *
292  * \param value The attribute value to visit.
293  * \param visitor A receiving function object to pass the attribute value to.
294  * \return The result of visitation.
295  */
296 template< typename T, typename VisitorT >
297 inline visitation_result
visit(attribute_value const & value,VisitorT visitor)298 visit(attribute_value const& value, VisitorT visitor)
299 {
300     value_visitor_invoker< T > invoker;
301     return invoker(value, visitor);
302 }
303 
304 /*!
305  * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
306  * type or set of possible types of the attribute value to be visited.
307  *
308  * \param keyword The keyword of the attribute value to visit.
309  * \param attrs A set of attribute values in which to look for the specified attribute value.
310  * \param visitor A receiving function object to pass the attribute value to.
311  * \return The result of visitation.
312  */
313 template< typename DescriptorT, template< typename > class ActorT, typename VisitorT >
314 inline visitation_result
visit(expressions::attribute_keyword<DescriptorT,ActorT> const & keyword,attribute_value_set const & attrs,VisitorT visitor)315 visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs, VisitorT visitor)
316 {
317     value_visitor_invoker< typename DescriptorT::value_type > invoker;
318     return invoker(keyword.get_name(), attrs, visitor);
319 }
320 
321 /*!
322  * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
323  * type or set of possible types of the attribute value to be visited.
324  *
325  * \param keyword The keyword of the attribute value to visit.
326  * \param rec A log record. The attribute value will be sought among those associated with the record.
327  * \param visitor A receiving function object to pass the attribute value to.
328  * \return The result of visitation.
329  */
330 template< typename DescriptorT, template< typename > class ActorT, typename VisitorT >
331 inline visitation_result
visit(expressions::attribute_keyword<DescriptorT,ActorT> const & keyword,record const & rec,VisitorT visitor)332 visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec, VisitorT visitor)
333 {
334     value_visitor_invoker< typename DescriptorT::value_type > invoker;
335     return invoker(keyword.get_name(), rec, visitor);
336 }
337 
338 /*!
339  * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the
340  * type or set of possible types of the attribute value to be visited.
341  *
342  * \param keyword The keyword of the attribute value to visit.
343  * \param rec A log record view. The attribute value will be sought among those associated with the record.
344  * \param visitor A receiving function object to pass the attribute value to.
345  * \return The result of visitation.
346  */
347 template< typename DescriptorT, template< typename > class ActorT, typename VisitorT >
348 inline visitation_result
visit(expressions::attribute_keyword<DescriptorT,ActorT> const & keyword,record_view const & rec,VisitorT visitor)349 visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec, VisitorT visitor)
350 {
351     value_visitor_invoker< typename DescriptorT::value_type > invoker;
352     return invoker(keyword.get_name(), rec, visitor);
353 }
354 
355 
356 #if !defined(BOOST_LOG_DOXYGEN_PASS)
357 
358 template< typename T, typename VisitorT >
visit(VisitorT visitor) const359 inline visitation_result attribute_value::visit(VisitorT visitor) const
360 {
361     return boost::log::visit< T >(*this, visitor);
362 }
363 
364 #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
365 
366 BOOST_LOG_CLOSE_NAMESPACE // namespace log
367 
368 } // namespace boost
369 
370 #include <boost/log/detail/footer.hpp>
371 
372 #endif // BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_
373