/* * Copyright Andrey Semashev 2007 - 2014. * 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 record_ordering.hpp * \author Andrey Semashev * \date 23.08.2009 * * This header contains ordering predicates for logging records. */ #ifndef BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_ #define BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_ #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once #endif namespace boost { BOOST_LOG_OPEN_NAMESPACE /*! * \brief Ordering predicate, based on opaque pointers to the record view implementation data * * Since record views only refer to a shared implementation data, this predicate is able to order the views * by comparing the pointers to the data. Therefore two views are considered to be equivalent if they * refer to the same implementation data. Otherwise it is not specified whether one record is ordered before * the other until the predicate is applied. Note that the ordering may change every time the application runs. * * This kind of ordering may be useful if log records are to be stored in an associative * container with as least performance overhead as possible, when the particular order is not important. * * The \c FunT template argument is the predicate that is used to actually compare pointers. It should be * able to compare const void* pointers. The compared pointers may refer to distinct memory regions, * the pointers must not be interpreted in any way. */ template< typename FunT = less > class abstract_ordering : private FunT { public: //! Result type typedef bool result_type; public: /*! * Default constructor. Requires \c FunT to be default constructible. */ abstract_ordering() : FunT() { } /*! * Initializing constructor. Constructs \c FunT instance as a copy of the \a fun argument. */ explicit abstract_ordering(FunT const& fun) : FunT(fun) { } /*! * Ordering operator */ result_type operator() (record_view const& left, record_view const& right) const { // We rely on the fact that the attribute_values() method returns a reference to the object in the record implementation, // so we can compare pointers. return FunT::operator() (static_cast< const void* >(&left.attribute_values()), static_cast< const void* >(&right.attribute_values())); } }; /*! * \brief Ordering predicate, based on attribute values associated with records * * This predicate allows to order log records based on values of a specifically named attribute * associated with them. Two given log records being compared should both have the specified * attribute value of the specified type to be able to be ordered properly. As a special case, * if neither of the records have the value, these records are considered equivalent. Otherwise, * the ordering results are unspecified. */ template< typename ValueT, typename FunT = less > class attribute_value_ordering : private FunT { public: //! Result type typedef bool result_type; //! Compared attribute value type typedef ValueT value_type; private: template< typename LeftT > struct l2_visitor { typedef void result_type; l2_visitor(FunT const& fun, LeftT const& left, bool& result) : m_fun(fun), m_left(left), m_result(result) { } template< typename RightT > result_type operator() (RightT const& right) const { m_result = m_fun(m_left, right); } private: FunT const& m_fun; LeftT const& m_left; bool& m_result; }; struct l1_visitor; friend struct l1_visitor; struct l1_visitor { typedef void result_type; l1_visitor(attribute_value_ordering const& owner, record_view const& right, bool& result) : m_owner(owner), m_right(right), m_result(result) { } template< typename LeftT > result_type operator() (LeftT const& left) const { boost::log::visit< value_type >(m_owner.m_name, m_right, l2_visitor< LeftT >(static_cast< FunT const& >(m_owner), left, m_result)); } private: attribute_value_ordering const& m_owner; record_view const& m_right; bool& m_result; }; private: //! Attribute value name const attribute_name m_name; public: /*! * Initializing constructor. * * \param name The attribute value name to be compared * \param fun The ordering functor */ explicit attribute_value_ordering(attribute_name const& name, FunT const& fun = FunT()) : FunT(fun), m_name(name) { } /*! * Ordering operator */ result_type operator() (record_view const& left, record_view const& right) const { bool result = false; if (!boost::log::visit< value_type >(m_name, left, l1_visitor(*this, right, result))) { return !boost::log::visit< value_type >(m_name, right, nop()); } return result; } }; /*! * The function constructs a log record ordering predicate */ template< typename ValueT, typename FunT > inline attribute_value_ordering< ValueT, FunT > make_attr_ordering(attribute_name const& name, FunT const& fun) { typedef attribute_value_ordering< ValueT, FunT > ordering_t; return ordering_t(name, fun); } #if !defined(BOOST_LOG_NO_FUNCTION_TRAITS) namespace aux { //! An ordering predicate constructor that uses SFINAE to disable invalid instantiations template< typename FunT, typename ArityCheckT = typename enable_if_c< aux::arity_of< FunT >::value == 2 >::type, typename Arg1T = typename aux::first_argument_type_of< FunT >::type, typename Arg2T = typename aux::second_argument_type_of< FunT >::type, typename ArgsCheckT = typename enable_if< is_same< Arg1T, Arg2T > >::type > struct make_attr_ordering_type { typedef attribute_value_ordering< Arg1T, FunT > type; }; } // namespace aux /*! * The function constructs a log record ordering predicate */ template< typename FunT > inline typename aux::make_attr_ordering_type< FunT >::type make_attr_ordering(attribute_name const& name, FunT const& fun) { typedef typename aux::make_attr_ordering_type< FunT >::type ordering_t; return ordering_t(name, fun); } #endif // BOOST_LOG_NO_FUNCTION_TRAITS BOOST_LOG_CLOSE_NAMESPACE // namespace log } // namespace boost #include #endif // BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_