Chris@16: /* Chris@101: * Copyright Andrey Semashev 2007 - 2015. Chris@16: * Distributed under the Boost Software License, Version 1.0. Chris@16: * (See accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: */ Chris@16: /*! Chris@16: * \file attribute_mapping.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 07.11.2008 Chris@16: * Chris@16: * The header contains facilities that are used in different sinks to map attribute values Chris@16: * used throughout the application to values used with the specific native logging API. Chris@16: * These tools are mostly needed to map application severity levels on native levels, Chris@16: * required by OS-specific sink backends. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: BOOST_LOG_OPEN_NAMESPACE Chris@16: Chris@16: namespace sinks { Chris@16: Chris@16: //! Base class for attribute mapping function objects Chris@16: template< typename MappedT > Chris@16: struct basic_mapping Chris@16: { Chris@16: //! Mapped value type Chris@16: typedef MappedT mapped_type; Chris@16: //! Result type Chris@16: typedef mapped_type result_type; Chris@16: }; Chris@16: Chris@16: namespace aux { Chris@16: Chris@16: //! Attribute value visitor Chris@16: template< typename MappedT > Chris@16: struct direct_mapping_visitor Chris@16: { Chris@16: typedef void result_type; Chris@16: typedef MappedT mapped_type; Chris@16: Chris@16: explicit direct_mapping_visitor(mapped_type& extracted) : Chris@16: m_Extracted(extracted) Chris@16: { Chris@16: } Chris@16: template< typename T > Chris@16: void operator() (T const& val) const Chris@16: { Chris@16: m_Extracted = mapped_type(val); Chris@16: } Chris@16: Chris@16: private: Chris@16: mapped_type& m_Extracted; Chris@16: }; Chris@16: // Specialization for the tagged integer Chris@16: template< typename IntT, typename TagT > Chris@16: struct direct_mapping_visitor< boost::log::aux::tagged_integer< IntT, TagT > > Chris@16: { Chris@16: typedef void result_type; Chris@16: typedef boost::log::aux::tagged_integer< IntT, TagT > mapped_type; Chris@16: Chris@16: explicit direct_mapping_visitor(mapped_type& extracted) : Chris@16: m_Extracted(extracted) Chris@16: { Chris@16: } Chris@16: template< typename T > Chris@16: void operator() (T const& val) const Chris@16: { Chris@16: mapped_type v = { val }; Chris@16: m_Extracted = v; Chris@16: } Chris@16: Chris@16: private: Chris@16: mapped_type& m_Extracted; Chris@16: }; Chris@16: Chris@16: } // namespace aux Chris@16: Chris@16: /*! Chris@16: * \brief Straightforward mapping Chris@16: * Chris@16: * This type of mapping assumes that attribute with a particular name always Chris@16: * provides values that map directly onto the native values. The mapping Chris@16: * simply returns the extracted attribute value converted to the native value. Chris@16: */ Chris@16: template< typename MappedT, typename AttributeValueT = int > Chris@16: class basic_direct_mapping : Chris@16: public basic_mapping< MappedT > Chris@16: { Chris@16: //! Base type Chris@16: typedef basic_direct_mapping< MappedT > base_type; Chris@16: Chris@16: public: Chris@16: //! Attribute contained value type Chris@16: typedef AttributeValueT attribute_value_type; Chris@16: //! Mapped value type Chris@16: typedef typename base_type::mapped_type mapped_type; Chris@16: Chris@16: private: Chris@16: //! Attribute name Chris@16: const attribute_name m_Name; Chris@16: //! Visitor invoker for the attribute value Chris@16: value_visitor_invoker< attribute_value_type > m_Invoker; Chris@16: //! Default native value Chris@16: mapped_type m_DefaultValue; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Constructor Chris@16: * Chris@16: * \param name Attribute name Chris@16: * \param default_value The default native value that is returned if the attribute value is not found Chris@16: */ Chris@16: explicit basic_direct_mapping(attribute_name const& name, mapped_type const& default_value) : Chris@16: m_Name(name), Chris@16: m_DefaultValue(default_value) Chris@16: { Chris@16: } Chris@16: Chris@16: /*! Chris@16: * Extraction operator Chris@16: * Chris@16: * \param rec A log record to extract value from Chris@16: * \return An extracted attribute value Chris@16: */ Chris@16: mapped_type operator() (record_view const& rec) const Chris@16: { Chris@16: mapped_type res = m_DefaultValue; Chris@16: aux::direct_mapping_visitor< mapped_type > vis(res); Chris@16: m_Invoker(m_Name, rec.attribute_values(), vis); Chris@16: return res; Chris@16: } Chris@16: }; Chris@16: Chris@16: /*! Chris@16: * \brief Customizable mapping Chris@16: * Chris@16: * The class allows to setup a custom mapping between an attribute and native values. Chris@16: * The mapping should be initialized similarly to the standard \c map container, by using Chris@16: * indexing operator and assignment. Chris@16: * Chris@16: * \note Unlike many other components of the library, exact type of the attribute value Chris@16: * must be specified in the template parameter \c AttributeValueT. Type sequences Chris@16: * are not supported. Chris@16: */ Chris@16: template< typename MappedT, typename AttributeValueT = int > Chris@16: class basic_custom_mapping : Chris@16: public basic_mapping< MappedT > Chris@16: { Chris@16: //! Base type Chris@16: typedef basic_mapping< MappedT > base_type; Chris@16: Chris@16: public: Chris@16: //! Attribute contained value type Chris@16: typedef AttributeValueT attribute_value_type; Chris@16: //! Mapped value type Chris@16: typedef typename base_type::mapped_type mapped_type; Chris@16: Chris@16: private: Chris@16: //! \cond Chris@16: Chris@16: //! Mapping type Chris@16: typedef std::map< attribute_value_type, mapped_type > mapping_type; Chris@16: //! Smart reference class for implementing insertion into the map Chris@16: class reference_proxy; Chris@16: friend class reference_proxy; Chris@16: class reference_proxy Chris@16: { Chris@16: mapping_type& m_Mapping; Chris@16: attribute_value_type m_Key; Chris@16: Chris@16: public: Chris@16: //! Constructor Chris@16: reference_proxy(mapping_type& mapping, attribute_value_type const& key) : m_Mapping(mapping), m_Key(key) {} Chris@16: //! Insertion Chris@16: reference_proxy const& operator= (mapped_type const& val) const Chris@16: { Chris@16: m_Mapping[m_Key] = val; Chris@16: return *this; Chris@16: } Chris@16: }; Chris@16: Chris@16: //! Attribute value visitor Chris@16: struct visitor; Chris@16: friend struct visitor; Chris@16: struct visitor Chris@16: { Chris@16: typedef void result_type; Chris@16: Chris@16: visitor(mapping_type const& mapping, mapped_type& extracted) : Chris@16: m_Mapping(mapping), Chris@16: m_Extracted(extracted) Chris@16: { Chris@16: } Chris@16: template< typename T > Chris@16: void operator() (T const& val) const Chris@16: { Chris@16: typename mapping_type::const_iterator it = m_Mapping.find(val); Chris@16: if (it != m_Mapping.end()) Chris@16: m_Extracted = it->second; Chris@16: } Chris@16: Chris@16: private: Chris@16: mapping_type const& m_Mapping; Chris@16: mapped_type& m_Extracted; Chris@16: }; Chris@16: Chris@16: //! \endcond Chris@16: Chris@16: private: Chris@16: //! Attribute name Chris@16: const attribute_name m_Name; Chris@16: //! Visitor invoker for the attribute value Chris@16: value_visitor_invoker< attribute_value_type > m_Invoker; Chris@16: //! Default native value Chris@16: mapped_type m_DefaultValue; Chris@16: //! Conversion mapping Chris@16: mapping_type m_Mapping; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Constructor Chris@16: * Chris@16: * \param name Attribute name Chris@16: * \param default_value The default native value that is returned if the conversion cannot be performed Chris@16: */ Chris@16: explicit basic_custom_mapping(attribute_name const& name, mapped_type const& default_value) : Chris@16: m_Name(name), Chris@16: m_DefaultValue(default_value) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Extraction operator. Extracts the attribute value and attempts to map it onto Chris@16: * the native value. Chris@16: * Chris@16: * \param rec A log record to extract value from Chris@16: * \return A mapped value, if mapping was successful, or the default value if Chris@16: * mapping did not succeed. Chris@16: */ Chris@16: mapped_type operator() (record_view const& rec) const Chris@16: { Chris@16: mapped_type res = m_DefaultValue; Chris@16: visitor vis(m_Mapping, res); Chris@16: m_Invoker(m_Name, rec.attribute_values(), vis); Chris@16: return res; Chris@16: } Chris@16: /*! Chris@16: * Insertion operator Chris@16: * Chris@16: * \param key Attribute value to be mapped Chris@16: * \return An object of unspecified type that allows to insert a new mapping through assignment. Chris@16: * The \a key argument becomes the key attribute value, and the assigned value becomes the Chris@16: * mapped native value. Chris@16: */ Chris@16: #ifndef BOOST_LOG_DOXYGEN_PASS Chris@16: reference_proxy operator[] (attribute_value_type const& key) Chris@16: #else Chris@16: implementation_defined operator[] (attribute_value_type const& key) Chris@16: #endif Chris@16: { Chris@16: return reference_proxy(m_Mapping, key); Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace sinks Chris@16: Chris@16: BOOST_LOG_CLOSE_NAMESPACE // namespace log Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_LOG_SINKS_ATTRIBUTE_MAPPING_HPP_INCLUDED_