Chris@16
|
1 /*
|
Chris@101
|
2 * Copyright Andrey Semashev 2007 - 2015.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7 /*!
|
Chris@16
|
8 * \file attribute_mapping.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 07.11.2008
|
Chris@16
|
11 *
|
Chris@16
|
12 * The header contains facilities that are used in different sinks to map attribute values
|
Chris@16
|
13 * used throughout the application to values used with the specific native logging API.
|
Chris@16
|
14 * These tools are mostly needed to map application severity levels on native levels,
|
Chris@16
|
15 * required by OS-specific sink backends.
|
Chris@16
|
16 */
|
Chris@16
|
17
|
Chris@16
|
18 #ifndef BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_
|
Chris@16
|
19 #define BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_
|
Chris@16
|
20
|
Chris@16
|
21 #include <map>
|
Chris@16
|
22 #include <boost/log/detail/config.hpp>
|
Chris@16
|
23 #include <boost/log/detail/tagged_integer.hpp>
|
Chris@16
|
24 #include <boost/log/core/record_view.hpp>
|
Chris@16
|
25 #include <boost/log/attributes/attribute_name.hpp>
|
Chris@16
|
26 #include <boost/log/attributes/attribute_value_set.hpp>
|
Chris@16
|
27 #include <boost/log/attributes/value_visitation.hpp>
|
Chris@16
|
28 #include <boost/log/detail/header.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
31 #pragma once
|
Chris@16
|
32 #endif
|
Chris@16
|
33
|
Chris@16
|
34 namespace boost {
|
Chris@16
|
35
|
Chris@16
|
36 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
37
|
Chris@16
|
38 namespace sinks {
|
Chris@16
|
39
|
Chris@16
|
40 //! Base class for attribute mapping function objects
|
Chris@16
|
41 template< typename MappedT >
|
Chris@16
|
42 struct basic_mapping
|
Chris@16
|
43 {
|
Chris@16
|
44 //! Mapped value type
|
Chris@16
|
45 typedef MappedT mapped_type;
|
Chris@16
|
46 //! Result type
|
Chris@16
|
47 typedef mapped_type result_type;
|
Chris@16
|
48 };
|
Chris@16
|
49
|
Chris@16
|
50 namespace aux {
|
Chris@16
|
51
|
Chris@16
|
52 //! Attribute value visitor
|
Chris@16
|
53 template< typename MappedT >
|
Chris@16
|
54 struct direct_mapping_visitor
|
Chris@16
|
55 {
|
Chris@16
|
56 typedef void result_type;
|
Chris@16
|
57 typedef MappedT mapped_type;
|
Chris@16
|
58
|
Chris@16
|
59 explicit direct_mapping_visitor(mapped_type& extracted) :
|
Chris@16
|
60 m_Extracted(extracted)
|
Chris@16
|
61 {
|
Chris@16
|
62 }
|
Chris@16
|
63 template< typename T >
|
Chris@16
|
64 void operator() (T const& val) const
|
Chris@16
|
65 {
|
Chris@16
|
66 m_Extracted = mapped_type(val);
|
Chris@16
|
67 }
|
Chris@16
|
68
|
Chris@16
|
69 private:
|
Chris@16
|
70 mapped_type& m_Extracted;
|
Chris@16
|
71 };
|
Chris@16
|
72 // Specialization for the tagged integer
|
Chris@16
|
73 template< typename IntT, typename TagT >
|
Chris@16
|
74 struct direct_mapping_visitor< boost::log::aux::tagged_integer< IntT, TagT > >
|
Chris@16
|
75 {
|
Chris@16
|
76 typedef void result_type;
|
Chris@16
|
77 typedef boost::log::aux::tagged_integer< IntT, TagT > mapped_type;
|
Chris@16
|
78
|
Chris@16
|
79 explicit direct_mapping_visitor(mapped_type& extracted) :
|
Chris@16
|
80 m_Extracted(extracted)
|
Chris@16
|
81 {
|
Chris@16
|
82 }
|
Chris@16
|
83 template< typename T >
|
Chris@16
|
84 void operator() (T const& val) const
|
Chris@16
|
85 {
|
Chris@16
|
86 mapped_type v = { val };
|
Chris@16
|
87 m_Extracted = v;
|
Chris@16
|
88 }
|
Chris@16
|
89
|
Chris@16
|
90 private:
|
Chris@16
|
91 mapped_type& m_Extracted;
|
Chris@16
|
92 };
|
Chris@16
|
93
|
Chris@16
|
94 } // namespace aux
|
Chris@16
|
95
|
Chris@16
|
96 /*!
|
Chris@16
|
97 * \brief Straightforward mapping
|
Chris@16
|
98 *
|
Chris@16
|
99 * This type of mapping assumes that attribute with a particular name always
|
Chris@16
|
100 * provides values that map directly onto the native values. The mapping
|
Chris@16
|
101 * simply returns the extracted attribute value converted to the native value.
|
Chris@16
|
102 */
|
Chris@16
|
103 template< typename MappedT, typename AttributeValueT = int >
|
Chris@16
|
104 class basic_direct_mapping :
|
Chris@16
|
105 public basic_mapping< MappedT >
|
Chris@16
|
106 {
|
Chris@16
|
107 //! Base type
|
Chris@16
|
108 typedef basic_direct_mapping< MappedT > base_type;
|
Chris@16
|
109
|
Chris@16
|
110 public:
|
Chris@16
|
111 //! Attribute contained value type
|
Chris@16
|
112 typedef AttributeValueT attribute_value_type;
|
Chris@16
|
113 //! Mapped value type
|
Chris@16
|
114 typedef typename base_type::mapped_type mapped_type;
|
Chris@16
|
115
|
Chris@16
|
116 private:
|
Chris@16
|
117 //! Attribute name
|
Chris@16
|
118 const attribute_name m_Name;
|
Chris@16
|
119 //! Visitor invoker for the attribute value
|
Chris@16
|
120 value_visitor_invoker< attribute_value_type > m_Invoker;
|
Chris@16
|
121 //! Default native value
|
Chris@16
|
122 mapped_type m_DefaultValue;
|
Chris@16
|
123
|
Chris@16
|
124 public:
|
Chris@16
|
125 /*!
|
Chris@16
|
126 * Constructor
|
Chris@16
|
127 *
|
Chris@16
|
128 * \param name Attribute name
|
Chris@16
|
129 * \param default_value The default native value that is returned if the attribute value is not found
|
Chris@16
|
130 */
|
Chris@16
|
131 explicit basic_direct_mapping(attribute_name const& name, mapped_type const& default_value) :
|
Chris@16
|
132 m_Name(name),
|
Chris@16
|
133 m_DefaultValue(default_value)
|
Chris@16
|
134 {
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 /*!
|
Chris@16
|
138 * Extraction operator
|
Chris@16
|
139 *
|
Chris@16
|
140 * \param rec A log record to extract value from
|
Chris@16
|
141 * \return An extracted attribute value
|
Chris@16
|
142 */
|
Chris@16
|
143 mapped_type operator() (record_view const& rec) const
|
Chris@16
|
144 {
|
Chris@16
|
145 mapped_type res = m_DefaultValue;
|
Chris@16
|
146 aux::direct_mapping_visitor< mapped_type > vis(res);
|
Chris@16
|
147 m_Invoker(m_Name, rec.attribute_values(), vis);
|
Chris@16
|
148 return res;
|
Chris@16
|
149 }
|
Chris@16
|
150 };
|
Chris@16
|
151
|
Chris@16
|
152 /*!
|
Chris@16
|
153 * \brief Customizable mapping
|
Chris@16
|
154 *
|
Chris@16
|
155 * The class allows to setup a custom mapping between an attribute and native values.
|
Chris@16
|
156 * The mapping should be initialized similarly to the standard \c map container, by using
|
Chris@16
|
157 * indexing operator and assignment.
|
Chris@16
|
158 *
|
Chris@16
|
159 * \note Unlike many other components of the library, exact type of the attribute value
|
Chris@16
|
160 * must be specified in the template parameter \c AttributeValueT. Type sequences
|
Chris@16
|
161 * are not supported.
|
Chris@16
|
162 */
|
Chris@16
|
163 template< typename MappedT, typename AttributeValueT = int >
|
Chris@16
|
164 class basic_custom_mapping :
|
Chris@16
|
165 public basic_mapping< MappedT >
|
Chris@16
|
166 {
|
Chris@16
|
167 //! Base type
|
Chris@16
|
168 typedef basic_mapping< MappedT > base_type;
|
Chris@16
|
169
|
Chris@16
|
170 public:
|
Chris@16
|
171 //! Attribute contained value type
|
Chris@16
|
172 typedef AttributeValueT attribute_value_type;
|
Chris@16
|
173 //! Mapped value type
|
Chris@16
|
174 typedef typename base_type::mapped_type mapped_type;
|
Chris@16
|
175
|
Chris@16
|
176 private:
|
Chris@16
|
177 //! \cond
|
Chris@16
|
178
|
Chris@16
|
179 //! Mapping type
|
Chris@16
|
180 typedef std::map< attribute_value_type, mapped_type > mapping_type;
|
Chris@16
|
181 //! Smart reference class for implementing insertion into the map
|
Chris@16
|
182 class reference_proxy;
|
Chris@16
|
183 friend class reference_proxy;
|
Chris@16
|
184 class reference_proxy
|
Chris@16
|
185 {
|
Chris@16
|
186 mapping_type& m_Mapping;
|
Chris@16
|
187 attribute_value_type m_Key;
|
Chris@16
|
188
|
Chris@16
|
189 public:
|
Chris@16
|
190 //! Constructor
|
Chris@16
|
191 reference_proxy(mapping_type& mapping, attribute_value_type const& key) : m_Mapping(mapping), m_Key(key) {}
|
Chris@16
|
192 //! Insertion
|
Chris@16
|
193 reference_proxy const& operator= (mapped_type const& val) const
|
Chris@16
|
194 {
|
Chris@16
|
195 m_Mapping[m_Key] = val;
|
Chris@16
|
196 return *this;
|
Chris@16
|
197 }
|
Chris@16
|
198 };
|
Chris@16
|
199
|
Chris@16
|
200 //! Attribute value visitor
|
Chris@16
|
201 struct visitor;
|
Chris@16
|
202 friend struct visitor;
|
Chris@16
|
203 struct visitor
|
Chris@16
|
204 {
|
Chris@16
|
205 typedef void result_type;
|
Chris@16
|
206
|
Chris@16
|
207 visitor(mapping_type const& mapping, mapped_type& extracted) :
|
Chris@16
|
208 m_Mapping(mapping),
|
Chris@16
|
209 m_Extracted(extracted)
|
Chris@16
|
210 {
|
Chris@16
|
211 }
|
Chris@16
|
212 template< typename T >
|
Chris@16
|
213 void operator() (T const& val) const
|
Chris@16
|
214 {
|
Chris@16
|
215 typename mapping_type::const_iterator it = m_Mapping.find(val);
|
Chris@16
|
216 if (it != m_Mapping.end())
|
Chris@16
|
217 m_Extracted = it->second;
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 private:
|
Chris@16
|
221 mapping_type const& m_Mapping;
|
Chris@16
|
222 mapped_type& m_Extracted;
|
Chris@16
|
223 };
|
Chris@16
|
224
|
Chris@16
|
225 //! \endcond
|
Chris@16
|
226
|
Chris@16
|
227 private:
|
Chris@16
|
228 //! Attribute name
|
Chris@16
|
229 const attribute_name m_Name;
|
Chris@16
|
230 //! Visitor invoker for the attribute value
|
Chris@16
|
231 value_visitor_invoker< attribute_value_type > m_Invoker;
|
Chris@16
|
232 //! Default native value
|
Chris@16
|
233 mapped_type m_DefaultValue;
|
Chris@16
|
234 //! Conversion mapping
|
Chris@16
|
235 mapping_type m_Mapping;
|
Chris@16
|
236
|
Chris@16
|
237 public:
|
Chris@16
|
238 /*!
|
Chris@16
|
239 * Constructor
|
Chris@16
|
240 *
|
Chris@16
|
241 * \param name Attribute name
|
Chris@16
|
242 * \param default_value The default native value that is returned if the conversion cannot be performed
|
Chris@16
|
243 */
|
Chris@16
|
244 explicit basic_custom_mapping(attribute_name const& name, mapped_type const& default_value) :
|
Chris@16
|
245 m_Name(name),
|
Chris@16
|
246 m_DefaultValue(default_value)
|
Chris@16
|
247 {
|
Chris@16
|
248 }
|
Chris@16
|
249 /*!
|
Chris@16
|
250 * Extraction operator. Extracts the attribute value and attempts to map it onto
|
Chris@16
|
251 * the native value.
|
Chris@16
|
252 *
|
Chris@16
|
253 * \param rec A log record to extract value from
|
Chris@16
|
254 * \return A mapped value, if mapping was successful, or the default value if
|
Chris@16
|
255 * mapping did not succeed.
|
Chris@16
|
256 */
|
Chris@16
|
257 mapped_type operator() (record_view const& rec) const
|
Chris@16
|
258 {
|
Chris@16
|
259 mapped_type res = m_DefaultValue;
|
Chris@16
|
260 visitor vis(m_Mapping, res);
|
Chris@16
|
261 m_Invoker(m_Name, rec.attribute_values(), vis);
|
Chris@16
|
262 return res;
|
Chris@16
|
263 }
|
Chris@16
|
264 /*!
|
Chris@16
|
265 * Insertion operator
|
Chris@16
|
266 *
|
Chris@16
|
267 * \param key Attribute value to be mapped
|
Chris@16
|
268 * \return An object of unspecified type that allows to insert a new mapping through assignment.
|
Chris@16
|
269 * The \a key argument becomes the key attribute value, and the assigned value becomes the
|
Chris@16
|
270 * mapped native value.
|
Chris@16
|
271 */
|
Chris@16
|
272 #ifndef BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
273 reference_proxy operator[] (attribute_value_type const& key)
|
Chris@16
|
274 #else
|
Chris@16
|
275 implementation_defined operator[] (attribute_value_type const& key)
|
Chris@16
|
276 #endif
|
Chris@16
|
277 {
|
Chris@16
|
278 return reference_proxy(m_Mapping, key);
|
Chris@16
|
279 }
|
Chris@16
|
280 };
|
Chris@16
|
281
|
Chris@16
|
282 } // namespace sinks
|
Chris@16
|
283
|
Chris@16
|
284 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
285
|
Chris@16
|
286 } // namespace boost
|
Chris@16
|
287
|
Chris@16
|
288 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
289
|
Chris@16
|
290 #endif // BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_
|