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