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