diff options
Diffstat (limited to 'boost/log')
235 files changed, 39172 insertions, 0 deletions
diff --git a/boost/log/attributes.hpp b/boost/log/attributes.hpp new file mode 100644 index 0000000000..92b9c259cc --- /dev/null +++ b/boost/log/attributes.hpp @@ -0,0 +1,38 @@ +/* + * 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 attributes.hpp + * \author Andrey Semashev + * \date 13.07.2009 + * + * This header includes other Boost.Log headers with all attributes. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/clock.hpp> +#include <boost/log/attributes/constant.hpp> +#include <boost/log/attributes/counter.hpp> +#include <boost/log/attributes/function.hpp> +#include <boost/log/attributes/mutable_constant.hpp> +#include <boost/log/attributes/named_scope.hpp> +#include <boost/log/attributes/timer.hpp> +#include <boost/log/attributes/current_process_name.hpp> +#include <boost/log/attributes/current_process_id.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/attributes/current_thread_id.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_ATTRIBUTES_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute.hpp b/boost/log/attributes/attribute.hpp new file mode 100644 index 0000000000..0d6ba64a17 --- /dev/null +++ b/boost/log/attributes/attribute.hpp @@ -0,0 +1,191 @@ +/* + * 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 attribute.hpp + * \author Andrey Semashev + * \date 15.04.2007 + * + * The header contains attribute interface definition. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_ + +#include <new> +#include <boost/move/core.hpp> +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/smart_ptr/intrusive_ref_counter.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +#ifndef BOOST_LOG_DOXYGEN_PASS + +class attribute_value; + +namespace aux { + +//! Reference proxy object to implement \c operator[] +class attribute_set_reference_proxy; + +} // namespace aux + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief A base class for an attribute value factory + * + * Every attribute is represented with a factory that is basically an attribute value generator. + * The sole purpose of an attribute is to return an actual value when requested. A simplest attribute + * can always return the same value that it stores internally, but more complex ones can + * perform a considerable amount of work to return a value, and the returned values may differ + * each time requested. + * + * A word about thread safety. An attribute should be prepared to be requested a value from + * multiple threads concurrently. + */ +class attribute +{ + BOOST_COPYABLE_AND_MOVABLE(attribute) + +public: + /*! + * \brief A base class for an attribute value factory + * + * All attributes must derive their implementation from this class. + */ + struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl : + public boost::intrusive_ref_counter< impl > + { + /*! + * \brief Virtual destructor + */ + virtual ~impl() {} + + /*! + * \return The actual attribute value. It shall not return empty values (exceptions + * shall be used to indicate errors). + */ + virtual attribute_value get_value() = 0; + + BOOST_LOG_API static void* operator new (std::size_t size); + BOOST_LOG_API static void operator delete (void* p, std::size_t size) BOOST_NOEXCEPT; + }; + +private: + //! Pointer to the attribute factory implementation + intrusive_ptr< impl > m_pImpl; + +public: + /*! + * Default constructor. Creates an empty attribute value factory, which is not usable until + * \c set_impl is called. + */ + BOOST_DEFAULTED_FUNCTION(attribute(), {}) + + /*! + * Copy constructor + */ + attribute(attribute const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {} + + /*! + * Move constructor + */ + attribute(BOOST_RV_REF(attribute) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); } + + /*! + * Initializing constructor + * + * \param p Pointer to the implementation. Must not be \c NULL. + */ + explicit attribute(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); } + + /*! + * Copy assignment + */ + attribute& operator= (BOOST_COPY_ASSIGN_REF(attribute) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + return *this; + } + + /*! + * Move assignment + */ + attribute& operator= (BOOST_RV_REF(attribute) that) BOOST_NOEXCEPT + { + m_pImpl.swap(that.m_pImpl); + return *this; + } + +#ifndef BOOST_LOG_DOXYGEN_PASS + attribute& operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT; +#endif + + /*! + * Verifies that the factory is not in empty state + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * Verifies that the factory is in empty state + */ + bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; } + + /*! + * \return The actual attribute value. It shall not return empty values (exceptions + * shall be used to indicate errors). + */ + attribute_value get_value() const; + + /*! + * The method swaps two factories (i.e. their implementations). + */ + void swap(attribute& that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); } + +protected: + /*! + * \returns The pointer to the implementation + */ + impl* get_impl() const BOOST_NOEXCEPT { return m_pImpl.get(); } + /*! + * Sets the pointer to the factory implementation. + * + * \param p Pointer to the implementation. Must not be \c NULL. + */ + void set_impl(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); } + + template< typename T > + friend T attribute_cast(attribute const&); +}; + +/*! + * The function swaps two attribute value factories + */ +inline void swap(attribute& left, attribute& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> +#if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_HPP_INCLUDED_) +#include <boost/log/detail/attribute_get_value_impl.hpp> +#endif + +#endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute_cast.hpp b/boost/log/attributes/attribute_cast.hpp new file mode 100644 index 0000000000..7ae1c92cf4 --- /dev/null +++ b/boost/log/attributes/attribute_cast.hpp @@ -0,0 +1,74 @@ +/* + * 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 attribute_cast.hpp + * \author Andrey Semashev + * \date 06.08.2010 + * + * The header contains utilities for casting between attribute factories. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_CAST_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_CAST_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * The class holds a reference to the attribute factory implementation being casted + */ +class cast_source +{ +private: + attribute::impl* m_pImpl; + +public: + /*! + * Initializing constructor. Creates a source that refers to the specified factory implementation. + */ + explicit cast_source(attribute::impl* p) : m_pImpl(p) + { + } + + /*! + * The function attempts to cast the aggregated pointer to the implementation to the specified type. + * + * \return The converted pointer or \c NULL, if the conversion fails. + */ + template< typename T > + T* as() const { return dynamic_cast< T* >(m_pImpl); } +}; + +} // namespace attributes + +/*! + * The function casts one attribute factory to another + */ +template< typename T > +inline T attribute_cast(attribute const& attr) +{ + return T(attributes::cast_source(attr.get_impl())); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_CAST_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute_name.hpp b/boost/log/attributes/attribute_name.hpp new file mode 100644 index 0000000000..4e283e6a28 --- /dev/null +++ b/boost/log/attributes/attribute_name.hpp @@ -0,0 +1,185 @@ +/* + * 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 attribute_name.hpp + * \author Andrey Semashev + * \date 28.06.2010 + * + * The header contains attribute name interface definition. + */ + +#ifndef BOOST_LOG_ATTRIBUTE_NAME_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTE_NAME_HPP_INCLUDED_ + +#include <iosfwd> +#include <string> +#include <boost/assert.hpp> +#include <boost/cstdint.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief The class represents an attribute name in containers used by the library + * + * The class mostly serves for optimization purposes. Each attribute name that is used + * with the library is automatically associated with a unique identifier, which is much + * lighter in terms of memory footprint and operations complexity. This is done + * transparently by this class, on object construction. Passing objects of this class + * to other library methods, such as attribute lookup functions, will not require + * this translation and/or string copying and thus will result in a more efficient code. + */ +class attribute_name +{ +public: + //! String type + typedef std::string string_type; +#ifdef BOOST_LOG_DOXYGEN_PASS + //! Associated identifier + typedef unspecified id_type; +#else + typedef uint32_t id_type; + +private: + enum { uninitialized = 0xFFFFFFFFu }; + + class repository; + friend class repository; + +private: + //! Associated identifier + id_type m_id; +#endif + +public: + /*! + * Default constructor. Creates an object that does not refer to any attribute name. + */ + BOOST_CONSTEXPR attribute_name() BOOST_NOEXCEPT : m_id(static_cast< id_type >(uninitialized)) + { + } + /*! + * Constructs an attribute name from the specified string + * + * \param name An attribute name + * \pre \a name is not NULL and points to a zero-terminated string + */ + attribute_name(const char* name) : + m_id(get_id_from_string(name)) + { + } + /*! + * Constructs an attribute name from the specified string + * + * \param name An attribute name + */ + attribute_name(string_type const& name) : + m_id(get_id_from_string(name.c_str())) + { + } + + /*! + * Compares the attribute names + * + * \return \c true if <tt>*this</tt> and \c that refer to the same attribute name, + * and \c false otherwise. + */ + bool operator== (attribute_name const& that) const BOOST_NOEXCEPT { return m_id == that.m_id; } + /*! + * Compares the attribute names + * + * \return \c true if <tt>*this</tt> and \c that refer to different attribute names, + * and \c false otherwise. + */ + bool operator!= (attribute_name const& that) const BOOST_NOEXCEPT { return m_id != that.m_id; } + + /*! + * Compares the attribute names + * + * \return \c true if <tt>*this</tt> and \c that refer to the same attribute name, + * and \c false otherwise. + */ + bool operator== (const char* that) const { return (m_id != static_cast< id_type >(uninitialized)) && (this->string() == that); } + /*! + * Compares the attribute names + * + * \return \c true if <tt>*this</tt> and \c that refer to different attribute names, + * and \c false otherwise. + */ + bool operator!= (const char* that) const { return !operator== (that); } + + /*! + * Compares the attribute names + * + * \return \c true if <tt>*this</tt> and \c that refer to the same attribute name, + * and \c false otherwise. + */ + bool operator== (string_type const& that) const { return (m_id != static_cast< id_type >(uninitialized)) && (this->string() == that); } + /*! + * Compares the attribute names + * + * \return \c true if <tt>*this</tt> and \c that refer to different attribute names, + * and \c false otherwise. + */ + bool operator!= (string_type const& that) const { return !operator== (that); } + + /*! + * Checks if the object was default-constructed + * + * \return \c true if <tt>*this</tt> was constructed with an attribute name, \c false otherwise + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + /*! + * Checks if the object was default-constructed + * + * \return \c true if <tt>*this</tt> was default-constructed and does not refer to any attribute name, + * \c false otherwise + */ + bool operator! () const BOOST_NOEXCEPT { return (m_id == static_cast< id_type >(uninitialized)); } + + /*! + * \return The associated id value + * \pre <tt>(!*this) == false</tt> + */ + id_type id() const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_id != static_cast< id_type >(uninitialized)); + return m_id; + } + /*! + * \return The attribute name string that was used during the object construction + * \pre <tt>(!*this) == false</tt> + */ + string_type const& string() const { return get_string_from_id(m_id); } + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_API id_type get_id_from_string(const char* name); + static BOOST_LOG_API string_type const& get_string_from_id(id_type id); +#endif +}; + +template< typename CharT, typename TraitsT > +BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& operator<< ( + std::basic_ostream< CharT, TraitsT >& strm, + attribute_name const& name); + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTE_NAME_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute_set.hpp b/boost/log/attributes/attribute_set.hpp new file mode 100644 index 0000000000..5481c095f4 --- /dev/null +++ b/boost/log/attributes/attribute_set.hpp @@ -0,0 +1,507 @@ +/* + * 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 attribute_set.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * This header contains definition of the attribute set container. + */ + +#ifndef BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_ + +#include <cstddef> +#include <utility> +#include <iterator> +#include <boost/mpl/if.hpp> +#include <boost/move/core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +class attribute_set; +class attribute_value_set; + +namespace aux { + +//! Reference proxy object to implement \c operator[] +class attribute_set_reference_proxy +{ +private: + //! Key type + typedef attribute_name key_type; + //! Mapped attribute type + typedef attribute mapped_type; + +private: + attribute_set* const m_pContainer; + const key_type m_key; + +public: + //! Constructor + explicit attribute_set_reference_proxy(attribute_set* pContainer, key_type const& key) BOOST_NOEXCEPT : + m_pContainer(pContainer), + m_key(key) + { + } + + //! Conversion operator (would be invoked in case of reading from the container) + operator mapped_type() const BOOST_NOEXCEPT; + //! Assignment operator (would be invoked in case of writing to the container) + mapped_type& operator= (mapped_type const& val) const; +}; + +} // namespace aux + +/*! + * \brief An attribute set class. + * + * An attribute set is an associative container with attribute name as a key and + * pointer to the attribute as a mapped value. The container allows storing only one element for each distinct + * key value. In most regards attribute set container provides interface similar to \c std::unordered_map. + * However, there are differences in \c operator[] semantics and a number of optimizations with regard to iteration. + * Besides, attribute names are stored as a read-only <tt>attribute_name</tt>'s instead of \c std::string, + * which saves memory and CPU time. + */ +class attribute_set +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_set) + + friend class attribute_value_set; + friend class aux::attribute_set_reference_proxy; + +public: + //! Key type + typedef attribute_name key_type; + //! Mapped attribute type + typedef attribute mapped_type; + + //! Value type + typedef std::pair< const key_type, mapped_type > value_type; + //! Reference type + typedef value_type& reference; + //! Const reference type + typedef value_type const& const_reference; + //! Pointer type + typedef value_type* pointer; + //! Const pointer type + typedef value_type const* const_pointer; + //! Size type + typedef std::size_t size_type; + //! Difference type + typedef std::ptrdiff_t difference_type; + +private: + //! \cond + + //! Implementation + struct implementation; + friend struct implementation; + + //! A base class for the container nodes + struct node_base + { + node_base* m_pPrev; + node_base* m_pNext; + + node_base(); + + BOOST_DELETED_FUNCTION(node_base(node_base const&)) + BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&)) + }; + + //! Container elements + struct node; + friend struct node; + struct node : + public node_base + { + value_type m_Value; + + node(key_type const& key, mapped_type const& data); + }; + + //! Iterator class +#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS + template< bool fConstV > class iter; + template< bool fConstV > friend class iter; +#endif + template< bool fConstV > + class iter + { + friend class iter< !fConstV >; + friend class attribute_set; + + public: + // Standard typedefs + typedef attribute_set::difference_type difference_type; + typedef attribute_set::value_type value_type; + typedef typename mpl::if_c< + fConstV, + attribute_set::const_reference, + attribute_set::reference + >::type reference; + typedef typename mpl::if_c< + fConstV, + attribute_set::const_pointer, + attribute_set::pointer + >::type pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + public: + // Constructors + BOOST_CONSTEXPR iter() : m_pNode(NULL) {} + explicit iter(node_base* pNode) BOOST_NOEXCEPT : m_pNode(pNode) {} + iter(iter< false > const& that) BOOST_NOEXCEPT : m_pNode(that.m_pNode) {} + + //! Assignment + template< bool f > + iter& operator= (iter< f > const& that) BOOST_NOEXCEPT + { + m_pNode = that.m_pNode; + return *this; + } + + // Comparison + template< bool f > + bool operator== (iter< f > const& that) const BOOST_NOEXCEPT { return (m_pNode == that.m_pNode); } + template< bool f > + bool operator!= (iter< f > const& that) const BOOST_NOEXCEPT { return (m_pNode != that.m_pNode); } + + // Modification + iter& operator++ () BOOST_NOEXCEPT + { + m_pNode = m_pNode->m_pNext; + return *this; + } + iter& operator-- () BOOST_NOEXCEPT + { + m_pNode = m_pNode->m_pPrev; + return *this; + } + iter operator++ (int) BOOST_NOEXCEPT + { + iter tmp(*this); + m_pNode = m_pNode->m_pNext; + return tmp; + } + iter operator-- (int) BOOST_NOEXCEPT + { + iter tmp(*this); + m_pNode = m_pNode->m_pPrev; + return tmp; + } + + // Dereferencing + pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); } + reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; } + + node_base* base() const BOOST_NOEXCEPT { return m_pNode; } + + private: + node_base* m_pNode; + }; + + //! \endcond + +public: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! Iterator type + typedef iter< false > iterator; + //! Const iterator type + typedef iter< true > const_iterator; +#else + /*! + * Iterator type. The iterator complies to the bidirectional iterator requirements. + */ + typedef implementation_defined iterator; + /*! + * Constant iterator type. The iterator complies to the bidirectional iterator requirements with read-only capabilities. + */ + typedef implementation_defined const_iterator; +#endif // BOOST_LOG_DOXYGEN_PASS + +private: + //! Pointer to implementation + implementation* m_pImpl; + +public: + /*! + * Default constructor. + * + * \post <tt>empty() == true</tt> + */ + BOOST_LOG_API attribute_set(); + + /*! + * Copy constructor. + * + * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt> + */ + BOOST_LOG_API attribute_set(attribute_set const& that); + + /*! + * Move constructor + */ + attribute_set(BOOST_RV_REF(attribute_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) + { + that.m_pImpl = NULL; + } + + /*! + * Destructor. All stored references to attributes are released. + */ + BOOST_LOG_API ~attribute_set() BOOST_NOEXCEPT; + + /*! + * Copy assignment operator. + * + * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt> + */ + attribute_set& operator= (attribute_set that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + + /*! + * Swaps two instances of the container. + * + * \b Throws: Nothing. + */ + void swap(attribute_set& that) BOOST_NOEXCEPT + { + implementation* const p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } + + /*! + * \return Iterator to the first element of the container. + */ + BOOST_LOG_API iterator begin() BOOST_NOEXCEPT; + /*! + * \return Iterator to the after-the-last element of the container. + */ + BOOST_LOG_API iterator end() BOOST_NOEXCEPT; + /*! + * \return Constant iterator to the first element of the container. + */ + BOOST_LOG_API const_iterator begin() const BOOST_NOEXCEPT; + /*! + * \return Constant iterator to the after-the-last element of the container. + */ + BOOST_LOG_API const_iterator end() const BOOST_NOEXCEPT; + + /*! + * \return Number of elements in the container. + */ + BOOST_LOG_API size_type size() const BOOST_NOEXCEPT; + /*! + * \return true if there are no elements in the container, false otherwise. + */ + bool empty() const BOOST_NOEXCEPT { return (this->size() == 0); } + + /*! + * The method finds the attribute by name. + * + * \param key Attribute name. + * \return Iterator to the found element or end() if the attribute with such name is not found. + */ + BOOST_LOG_API iterator find(key_type key) BOOST_NOEXCEPT; + /*! + * The method finds the attribute by name. + * + * \param key Attribute name. + * \return Iterator to the found element or \c end() if the attribute with such name is not found. + */ + const_iterator find(key_type key) const BOOST_NOEXCEPT + { + return const_iterator(const_cast< attribute_set* >(this)->find(key)); + } + /*! + * The method counts the number of the attribute occurrences in the container. Since there can be only one + * attribute with a particular key, the method always return 0 or 1. + * + * \param key Attribute name. + * \return The number of times the attribute is found in the container. + */ + size_type count(key_type key) const BOOST_NOEXCEPT { return size_type(this->find(key) != this->end()); } + + /*! + * Combined lookup/insertion operator. The operator semantics depends on the further usage of the returned reference. + * \li If the reference is used as an assignment target, the assignment expression is equivalent to element insertion, + * where the element is composed of the second argument of the \c operator[] as a key and the second argument of assignment + * as a mapped value. + * \li If the returned reference is used in context where a conversion to the mapped type is required, + * the result of the conversion is equivalent to the mapped value found with the second argument of the \c operator[] as a key, + * if such an element exists in the container, or a default-constructed mapped value, if an element does not exist in the + * container. + * + * \param key Attribute name. + * \return A smart reference object of unspecified type. + */ + aux::attribute_set_reference_proxy operator[] (key_type key) BOOST_NOEXCEPT + { + return aux::attribute_set_reference_proxy(this, key); + } + /*! + * Lookup operator + * + * \param key Attribute name. + * \return If an element with the corresponding attribute name is found in the container, its mapped value + * is returned. Otherwise a default-constructed mapped value is returned. + */ + mapped_type operator[] (key_type key) const BOOST_NOEXCEPT + { + const_iterator it = this->find(key); + if (it != end()) + return it->second; + else + return mapped_type(); + } + + /*! + * Insertion method + * + * \param key Attribute name. + * \param data Pointer to the attribute. Must not be NULL. + * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the + * inserted element. Otherwise the first component points to the element that prevents insertion. + */ + BOOST_LOG_API std::pair< iterator, bool > insert(key_type key, mapped_type const& data); + + /*! + * Insertion method + * + * \param value An element to be inserted. + * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the + * inserted element. Otherwise the first component points to the element that prevents insertion. + */ + std::pair< iterator, bool > insert(const_reference value) + { + return this->insert(value.first, value.second); + } + + /*! + * Mass insertion method. + * + * \param begin A forward iterator that points to the first element to be inserted. + * \param end A forward iterator that points to the after-the-last element to be inserted. + */ + template< typename FwdIteratorT > + void insert(FwdIteratorT begin, FwdIteratorT end) + { + for (; begin != end; ++begin) + this->insert(*begin); + } + + /*! + * Mass insertion method with ability to acquire iterators to the inserted elements. + * + * \param begin A forward iterator that points to the first element to be inserted. + * \param end A forward iterator that points to the after-the-last element to be inserted. + * \param out An output iterator that receives results of insertion of the elements + */ + template< typename FwdIteratorT, typename OutputIteratorT > + void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out) + { + for (; begin != end; ++begin, ++out) + *out = this->insert(*begin); + } + + /*! + * The method erases all attributes with the specified name + * + * \post All iterators to the erased elements become invalid. + * \param key Attribute name. + * \return Tne number of erased elements + */ + BOOST_LOG_API size_type erase(key_type key) BOOST_NOEXCEPT; + /*! + * The method erases the specified attribute + * + * \post All iterators to the erased element become invalid. + * \param it A valid iterator to the element to be erased. + * \return Tne number of erased elements + */ + BOOST_LOG_API void erase(iterator it) BOOST_NOEXCEPT; + /*! + * The method erases all attributes within the specified range + * + * \pre \a end is reachable from \a begin with a finite number of increments. + * \post All iterators to the erased elements become invalid. + * \param begin An iterator that points to the first element to be erased. + * \param end An iterator that points to the after-the-last element to be erased. + */ + BOOST_LOG_API void erase(iterator begin, iterator end) BOOST_NOEXCEPT; + + /*! + * The method removes all elements from the container + * + * \post <tt>empty() == true</tt> + */ + BOOST_LOG_API void clear() BOOST_NOEXCEPT; +}; + +/*! + * Free swap overload + */ +inline void swap(attribute_set& left, attribute_set& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +namespace aux { + +//! Conversion operator (would be invoked in case of reading from the container) +inline attribute_set_reference_proxy::operator mapped_type() const BOOST_NOEXCEPT +{ + attribute_set::iterator it = m_pContainer->find(m_key); + if (it != m_pContainer->end()) + return it->second; + else + return mapped_type(); +} + +//! Assignment operator (would be invoked in case of writing to the container) +inline attribute_set_reference_proxy::mapped_type& attribute_set_reference_proxy::operator= (mapped_type const& val) const +{ + std::pair< attribute_set::iterator, bool > res = m_pContainer->insert(m_key, val); + if (!res.second) + res.first->second = val; + return res.first->second; +} + +} // namespace aux + +#ifndef BOOST_LOG_DOXYGEN_PASS +inline attribute& attribute::operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT +{ + attribute attr = that; + this->swap(attr); + return *this; +} +#endif + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute_value.hpp b/boost/log/attributes/attribute_value.hpp new file mode 100644 index 0000000000..972093d9b7 --- /dev/null +++ b/boost/log/attributes/attribute_value.hpp @@ -0,0 +1,380 @@ +/* + * 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 attribute_value.hpp + * \author Andrey Semashev + * \date 21.05.2010 + * + * The header contains \c attribute_value class definition. + */ + +#ifndef BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/utility/type_info_wrapper.hpp> +#include <boost/log/utility/type_dispatch/type_dispatcher.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/value_extraction_fwd.hpp> +#include <boost/log/attributes/value_visitation_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief An attribute value class + * + * An attribute value is an object that contains a piece of data that represents an attribute state + * at the point of the value acquisition. All major operations with log records, such as filtering and + * formatting, involve attribute values contained in a single view. Most likely an attribute value is + * implemented as a simple holder of some typed value. This holder implements the + * \c attribute_value::implementation interface and acts as a pimpl for the \c attribute_value + * object. The \c attribute_value class provides type dispatching support in order to allow + * to extract the value from the holder. + * + * Normally, attributes and their values shall be designed in order to exclude as much interference as + * reasonable. Such approach allows to have more than one attribute value simultaneously, which improves + * scalability and allows to implement generating attributes. + * + * However, there are cases when this approach does not help to achieve the required level of independency + * of attribute values and attribute itself from each other at a reasonable performance tradeoff. + * For example, an attribute or its values may use thread-specific data, which is global and shared + * between all the instances of the attribute/value. Passing such an attribute value to another thread + * would be a disaster. To solve this the library defines an additional method for attribute values, + * namely \c detach_from_thread. The \c attribute_value class forwards the call to its pimpl, + * which is supposed to ensure that it no longer refers to any thread-specific data after the call. + * The pimpl can create a new holder as a result of this method and return it to the \c attribute_value + * wrapper, which will keep the returned reference for any further calls. + * This method is called for all attribute values that are passed to another thread. + */ +class attribute_value +{ + BOOST_COPYABLE_AND_MOVABLE(attribute_value) + +public: + /*! + * \brief A base class for an attribute value implementation + * + * All attribute value holders should derive from this interface. + */ + struct BOOST_LOG_NO_VTABLE impl : + public attribute::impl + { + public: + /*! + * The method dispatches the value to the given object. + * + * \param dispatcher The object that attempts to dispatch the stored value. + * \return true if \a dispatcher was capable to consume the real attribute value type and false otherwise. + */ + virtual bool dispatch(type_dispatcher& dispatcher) = 0; + + /*! + * The method is called when the attribute value is passed to another thread (e.g. + * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data. + * + * \return An actual pointer to the attribute value. It may either point to this object or another. + * In the latter case the returned pointer replaces the pointer used by caller to invoke this + * method and is considered to be a functional equivalent to the previous pointer. + */ + virtual intrusive_ptr< impl > detach_from_thread() + { + return this; + } + + /*! + * \return The attribute value that refers to self implementation. + */ + virtual attribute_value get_value() { return attribute_value(this); } + + /*! + * \return The attribute value type + */ + virtual type_info_wrapper get_type() const { return type_info_wrapper(); } + }; + +private: + //! Pointer to the value implementation + intrusive_ptr< impl > m_pImpl; + +public: + /*! + * Default constructor. Creates an empty (absent) attribute value. + */ + BOOST_DEFAULTED_FUNCTION(attribute_value(), {}) + + /*! + * Copy constructor + */ + attribute_value(attribute_value const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {} + + /*! + * Move constructor + */ + attribute_value(BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); } + + /*! + * Initializing constructor. Creates an attribute value that refers to the specified holder. + * + * \param p A pointer to the attribute value holder. + */ + explicit attribute_value(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); } + + /*! + * Copy assignment + */ + attribute_value& operator= (BOOST_COPY_ASSIGN_REF(attribute_value) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + return *this; + } + + /*! + * Move assignment + */ + attribute_value& operator= (BOOST_RV_REF(attribute_value) that) BOOST_NOEXCEPT + { + m_pImpl.swap(that.m_pImpl); + return *this; + } + + /*! + * The operator checks if the attribute value is empty + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + /*! + * The operator checks if the attribute value is empty + */ + bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; } + + /*! + * The method returns the type information of the stored value of the attribute. + * The returned type info wrapper may be empty if the attribute value is empty or + * the information cannot be provided. If the returned value is not empty, the type + * can be used for value extraction. + */ + type_info_wrapper get_type() const + { + if (m_pImpl.get()) + return m_pImpl->get_type(); + else + return type_info_wrapper(); + } + + /*! + * The method is called when the attribute value is passed to another thread (e.g. + * in case of asynchronous logging). The value should ensure it properly owns all thread-specific data. + * + * \post The attribute value no longer refers to any thread-specific resources. + */ + void detach_from_thread() + { + if (m_pImpl.get()) + m_pImpl->detach_from_thread().swap(m_pImpl); + } + + /*! + * The method dispatches the value to the given object. This method is a low level interface for + * attribute value visitation and extraction. For typical usage these interfaces may be more convenient. + * + * \param dispatcher The object that attempts to dispatch the stored value. + * \return \c true if the value is not empty and the \a dispatcher was capable to consume + * the real attribute value type and \c false otherwise. + */ + bool dispatch(type_dispatcher& dispatcher) const + { + if (m_pImpl.get()) + return m_pImpl->dispatch(dispatcher); + else + return false; + } + +#if !defined(BOOST_LOG_DOXYGEN_PASS) +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) +#define BOOST_LOG_AUX_VOID_DEFAULT = void +#else +#define BOOST_LOG_AUX_VOID_DEFAULT +#endif +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise returns an empty value. See description of the \c result_of::extract + * metafunction for information on the nature of the result value. + */ + template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > + typename result_of::extract< T, TagT >::type extract() const; + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw + * metafunction for information on the nature of the result value. + */ + template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > + typename result_of::extract_or_throw< T, TagT >::type extract_or_throw() const; + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. If extraction fails, the default value is returned. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \param def_value Default value. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default + * metafunction for information on the nature of the result value. + */ + template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > + typename result_of::extract_or_default< T, T, TagT >::type extract_or_default(T const& def_value) const; + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. If extraction fails, the default value is returned. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \param def_value Default value. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default + * metafunction for information on the nature of the result value. + */ + template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT > + typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(DefaultT const& def_value) const; + +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise returns an empty value. See description of the \c result_of::extract + * metafunction for information on the nature of the result value. + */ + template< typename T > + typename result_of::extract< T >::type extract() const; + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise an exception is thrown. See description of the \c result_of::extract_or_throw + * metafunction for information on the nature of the result value. + */ + template< typename T > + typename result_of::extract_or_throw< T >::type extract_or_throw() const; + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. If extraction fails, the default value is returned. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \param def_value Default value. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default + * metafunction for information on the nature of the result value. + */ + template< typename T > + typename result_of::extract_or_default< T, T >::type extract_or_default(T const& def_value) const; + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. If extraction fails, the default value is returned. + * + * \note Include <tt>value_extraction.hpp</tt> prior to using this method. + * + * \param def_value Default value. + * + * \return The extracted value, if the attribute value is not empty and the value is the same + * as specified. Otherwise returns the default value. See description of the \c result_of::extract_or_default + * metafunction for information on the nature of the result value. + */ + template< typename T, typename DefaultT > + typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(DefaultT const& def_value) const; +#endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + +#undef BOOST_LOG_AUX_VOID_DEFAULT + + /*! + * The method attempts to extract the stored value, assuming the value has the specified type, + * and pass it to the \a visitor function object. + * One can specify either a single type or an MPL type sequence, in which case the stored value + * is checked against every type in the sequence. + * + * \note Include <tt>value_visitation.hpp</tt> prior to using this method. + * + * \param visitor A function object that will be invoked on the extracted attribute value. + * The visitor should be capable to be called with a single argument of + * any type of the specified types in \c T. + * + * \return The result of visitation. + */ + template< typename T, typename VisitorT > + visitation_result visit(VisitorT visitor) const; + + /*! + * The method swaps two attribute values + */ + void swap(attribute_value& that) BOOST_NOEXCEPT + { + m_pImpl.swap(that.m_pImpl); + } +}; + +/*! + * The function swaps two attribute values + */ +inline void swap(attribute_value& left, attribute_value& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> +#if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_) +#include <boost/log/detail/attribute_get_value_impl.hpp> +#endif + +#endif // BOOST_LOG_ATTRIBUTE_VALUE_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute_value_impl.hpp b/boost/log/attributes/attribute_value_impl.hpp new file mode 100644 index 0000000000..405c346861 --- /dev/null +++ b/boost/log/attributes/attribute_value_impl.hpp @@ -0,0 +1,136 @@ +/* + * 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 attribute_value_impl.hpp + * \author Andrey Semashev + * \date 24.06.2007 + * + * The header contains an implementation of a basic attribute value implementation class. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/utility/type_dispatch/type_dispatcher.hpp> +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include <boost/type_traits/remove_reference.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief Basic attribute value implementation class + * + * This class can be used as a boilerplate for simple attribute values. The class implements all needed + * interfaces of attribute values and allows to store a single value of the type specified as a template parameter. + * The stored value can be dispatched with type dispatching mechanism. + */ +template< typename T > +class attribute_value_impl : + public attribute_value::impl +{ +public: + //! Value type + typedef T value_type; + +private: + //! Attribute value + const value_type m_value; + +public: + /*! + * Constructor with initialization of the stored value + */ + explicit attribute_value_impl(value_type const& v) : m_value(v) {} + /*! + * Constructor with initialization of the stored value + */ + explicit attribute_value_impl(BOOST_RV_REF(value_type) v) : m_value(v) {} + + /*! + * Attribute value dispatching method. + * + * \param dispatcher The dispatcher that receives the stored value + * + * \return \c true if the value has been dispatched, \c false otherwise + */ + virtual bool dispatch(type_dispatcher& dispatcher) + { + type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >(); + if (callback) + { + callback(m_value); + return true; + } + else + return false; + } + + /*! + * \return The attribute value type + */ + type_info_wrapper get_type() const { return type_info_wrapper(typeid(value_type)); } + + /*! + * \return Reference to the contained value. + */ + value_type const& get() const { return m_value; } +}; + +/*! + * The function creates an attribute value from the specified object. + */ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T > +inline attribute_value make_attribute_value(T&& v) +{ + typedef typename remove_cv< typename remove_reference< T >::type >::type value_type; + return attribute_value(new attribute_value_impl< value_type >(boost::forward< T >(v))); +} + +#else // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T > +inline attribute_value make_attribute_value(T const& v) +{ + typedef typename remove_cv< T >::type value_type; + return attribute_value(new attribute_value_impl< value_type >(v)); +} + +template< typename T > +inline attribute_value make_attribute_value(rv< T > const& v) +{ + typedef typename remove_cv< T >::type value_type; + return attribute_value(new attribute_value_impl< value_type >(v)); +} + +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_IMPL_HPP_INCLUDED_ diff --git a/boost/log/attributes/attribute_value_set.hpp b/boost/log/attributes/attribute_value_set.hpp new file mode 100644 index 0000000000..0ca635909c --- /dev/null +++ b/boost/log/attributes/attribute_value_set.hpp @@ -0,0 +1,480 @@ +/* + * 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 attribute_value_set.hpp + * \author Andrey Semashev + * \date 21.04.2007 + * + * This header file contains definition of attribute value set. The set is constructed from + * three attribute sets (global, thread-specific and source-specific) and contains attribute + * values. + */ + +#ifndef BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_ + +#include <cstddef> +#include <utility> +#include <iterator> +#include <boost/move/core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/attributes/attribute_set.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief A set of attribute values + * + * The set of attribute values is an associative container with attribute name as a key and + * a pointer to attribute value object as a mapped type. This is a collection of elements with unique + * keys, that is, there can be only one attribute value with a given name in the set. With respect to + * read-only capabilities, the set interface is close to \c std::unordered_map. + * + * The set is designed to be only capable of adding elements to it. Once added, the attribute value + * cannot be removed from the set. + * + * An instance of attribute value set can be constructed from three attribute sets. The constructor attempts to + * accommodate values of all attributes from the sets. The situation when a same-named attribute is found + * in more than one attribute set is possible. This problem is solved on construction of the value set: the three + * attribute sets have different priorities when it comes to solving conflicts. + * + * From the library perspective the three source attribute sets are global, thread-specific and source-specific + * attributes, with the latter having the highest priority. This feature allows to override attributes of wider scopes + * with the more specific ones. + * + * For sake of performance, the attribute values are not immediately acquired from attribute sets at construction. + * Instead, on-demand acquisition is performed either on iterator dereferencing or on call to the \c freeze method. + * Once acquired, the attribute value stays within the set until its destruction. This nuance does not affect + * other set properties, such as size or lookup ability. The logging core automatically freezes the set + * at the right point, so users should not be bothered unless they manually create attribute value sets. + * + * \note The attribute sets that were used for the value set construction must not be modified or destroyed + * until the value set is frozen. Otherwise the behavior is undefined. + */ +class attribute_value_set +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_value_set) + +public: + //! Key type + typedef attribute_name key_type; + //! Mapped attribute type + typedef attribute_value mapped_type; + + //! Value type + typedef std::pair< const key_type, mapped_type > value_type; + //! Reference type + typedef value_type& reference; + //! Const reference type + typedef value_type const& const_reference; + //! Pointer type + typedef value_type* pointer; + //! Const pointer type + typedef value_type const* const_pointer; + //! Size type + typedef std::size_t size_type; + //! Pointer difference type + typedef std::ptrdiff_t difference_type; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +private: + struct implementation; + friend struct implementation; + + //! A base class for the container nodes + struct node_base + { + node_base* m_pPrev; + node_base* m_pNext; + + node_base(); + + BOOST_DELETED_FUNCTION(node_base(node_base const&)) + BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&)) + }; + + //! Container elements + struct node; + friend struct node; + struct node : + public node_base + { + value_type m_Value; + bool m_DynamicallyAllocated; + + node(key_type const& key, mapped_type& data, bool dynamic); + }; + +public: + class const_iterator; + friend class const_iterator; + class const_iterator + { + public: + // Standard typedefs + typedef attribute_value_set::difference_type difference_type; + typedef attribute_value_set::value_type value_type; + typedef attribute_value_set::const_reference reference; + typedef attribute_value_set::const_pointer pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + public: + // Constructors + BOOST_CONSTEXPR const_iterator() : m_pNode(NULL), m_pContainer(NULL) {} + explicit const_iterator(node_base* n, attribute_value_set* cont) BOOST_NOEXCEPT : + m_pNode(n), + m_pContainer(cont) + { + } + + // Comparison + bool operator== (const_iterator const& that) const BOOST_NOEXCEPT + { + return (m_pNode == that.m_pNode); + } + bool operator!= (const_iterator const& that) const BOOST_NOEXCEPT + { + return (m_pNode != that.m_pNode); + } + + // Modification + const_iterator& operator++ () + { + m_pContainer->freeze(); + m_pNode = m_pNode->m_pNext; + return *this; + } + const_iterator& operator-- () + { + m_pContainer->freeze(); + m_pNode = m_pNode->m_pPrev; + return *this; + } + const_iterator operator++ (int) + { + const_iterator tmp(*this); + m_pContainer->freeze(); + m_pNode = m_pNode->m_pNext; + return tmp; + } + const_iterator operator-- (int) + { + const_iterator tmp(*this); + m_pContainer->freeze(); + m_pNode = m_pNode->m_pPrev; + return tmp; + } + + // Dereferencing + pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); } + reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; } + + private: + node_base* m_pNode; + attribute_value_set* m_pContainer; + }; + +#else + + /*! + * Constant iterator type with bidirectional capabilities. + */ + typedef implementation_defined const_iterator; + +#endif // BOOST_LOG_DOXYGEN_PASS + +private: + //! Pointer to the container implementation + implementation* m_pImpl; + +public: + /*! + * Default constructor + * + * The constructor creates an empty set which can be filled later by subsequent + * calls of \c insert method. Optionally, the amount of storage reserved for elements + * to be inserted may be passed to the constructor. + * The constructed set is frozen. + * + * \param reserve_count Number of elements to reserve space for. + */ + BOOST_LOG_API explicit attribute_value_set(size_type reserve_count = 8); + + /*! + * Move constructor + */ + attribute_value_set(BOOST_RV_REF(attribute_value_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) + { + that.m_pImpl = NULL; + } + + /*! + * The constructor adopts three attribute sets into the value set. + * The \a source_attrs attributes have the greatest preference when a same-named + * attribute is found in several sets, \a global_attrs has the least. + * The constructed set is not frozen. + * + * \param source_attrs A set of source-specific attributes. + * \param thread_attrs A set of thread-specific attributes. + * \param global_attrs A set of global attributes. + * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided. + */ + BOOST_LOG_API attribute_value_set( + attribute_set const& source_attrs, + attribute_set const& thread_attrs, + attribute_set const& global_attrs, + size_type reserve_count = 8); + + /*! + * The constructor adopts three attribute sets into the value set. + * The \a source_attrs attributes have the greatest preference when a same-named + * attribute is found in several sets, \a global_attrs has the least. + * The constructed set is not frozen. + * + * \pre The \a source_attrs set is frozen. + * + * \param source_attrs A set of source-specific attributes. + * \param thread_attrs A set of thread-specific attributes. + * \param global_attrs A set of global attributes. + * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided. + */ + BOOST_LOG_API attribute_value_set( + attribute_value_set const& source_attrs, + attribute_set const& thread_attrs, + attribute_set const& global_attrs, + size_type reserve_count = 8); + + /*! + * The constructor adopts three attribute sets into the value set. + * The \a source_attrs attributes have the greatest preference when a same-named + * attribute is found in several sets, \a global_attrs has the least. + * The constructed set is not frozen. + * + * \pre The \a source_attrs set is frozen. + * + * \param source_attrs A set of source-specific attributes. + * \param thread_attrs A set of thread-specific attributes. + * \param global_attrs A set of global attributes. + * \param reserve_count Amount of elements to reserve space for, in addition to the elements in the three attribute sets provided. + */ + attribute_value_set( + BOOST_RV_REF(attribute_value_set) source_attrs, + attribute_set const& thread_attrs, + attribute_set const& global_attrs, + size_type reserve_count = 8) : m_pImpl(NULL) + { + construct(static_cast< attribute_value_set& >(source_attrs), thread_attrs, global_attrs, reserve_count); + } + + /*! + * Copy constructor. + * + * \pre The original set is frozen. + * \post The constructed set is frozen, <tt>std::equal(begin(), end(), that.begin()) == true</tt> + */ + BOOST_LOG_API attribute_value_set(attribute_value_set const& that); + + /*! + * Destructor. Releases all referenced attribute values. + */ + BOOST_LOG_API ~attribute_value_set() BOOST_NOEXCEPT; + + /*! + * Assignment operator + */ + attribute_value_set& operator= (attribute_value_set that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + + /*! + * Swaps two sets + * + * \b Throws: Nothing. + */ + void swap(attribute_value_set& that) BOOST_NOEXCEPT + { + implementation* const p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } + + /*! + * \return Iterator to the first element of the set. + */ + BOOST_LOG_API const_iterator begin() const; + /*! + * \return Iterator to the after-the-last element of the set. + */ + BOOST_LOG_API const_iterator end() const; + + /*! + * \return Number of elements in the set. + */ + BOOST_LOG_API size_type size() const; + /*! + * \return true if there are no elements in the container, false otherwise. + */ + bool empty() const { return (this->size() == 0); } + + /*! + * The method finds the attribute value by name. + * + * \param key Attribute name. + * \return Iterator to the found element or \c end() if the attribute with such name is not found. + */ + BOOST_LOG_API const_iterator find(key_type key) const; + + /*! + * Alternative lookup syntax. + * + * \param key Attribute name. + * \return A pointer to the attribute value if it is found with \a key, default-constructed mapped value otherwise. + */ + mapped_type operator[] (key_type key) const + { + const_iterator it = this->find(key); + if (it != this->end()) + return it->second; + else + return mapped_type(); + } + + /*! + * Alternative lookup syntax. + * + * \param keyword Attribute keyword. + * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise. + */ + template< typename DescriptorT, template< typename > class ActorT > + typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type + operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const + { + typedef typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type attr_value_type; + typedef typename result_of::extract< attr_value_type, DescriptorT >::type result_type; + const_iterator it = this->find(keyword.get_name()); + if (it != this->end()) + return it->second.extract< attr_value_type, DescriptorT >(); + else + return result_type(); + } + + /*! + * The method counts the number of the attribute value occurrences in the set. Since there can be only one + * attribute value with a particular key, the method always return 0 or 1. + * + * \param key Attribute name. + * \return The number of times the attribute value is found in the container. + */ + size_type count(key_type key) const { return size_type(this->find(key) != this->end()); } + + /*! + * The method acquires values of all adopted attributes. + * + * \post The set is frozen. + */ + BOOST_LOG_API void freeze(); + + /*! + * Inserts an element into the set. The complexity of the operation is amortized constant. + * + * \pre The set is frozen. + * + * \param key The attribute name. + * \param mapped The attribute value. + * + * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise, + * if the set already contains a same-named attribute value, iterator to the + * existing element and \c false. + */ + BOOST_LOG_API std::pair< const_iterator, bool > insert(key_type key, mapped_type const& mapped); + + /*! + * Inserts an element into the set. The complexity of the operation is amortized constant. + * + * \pre The set is frozen. + * + * \param value The attribute name and value. + * + * \returns An iterator to the inserted element and \c true if insertion succeeded. Otherwise, + * if the set already contains a same-named attribute value, iterator to the + * existing element and \c false. + */ + std::pair< const_iterator, bool > insert(const_reference value) { return this->insert(value.first, value.second); } + + /*! + * Mass insertion method. The complexity of the operation is linear to the number of elements inserted. + * + * \pre The set is frozen. + * + * \param begin A forward iterator that points to the first element to be inserted. + * \param end A forward iterator that points to the after-the-last element to be inserted. + */ + template< typename FwdIteratorT > + void insert(FwdIteratorT begin, FwdIteratorT end) + { + for (; begin != end; ++begin) + this->insert(*begin); + } + + /*! + * Mass insertion method with ability to acquire iterators to the inserted elements. + * The complexity of the operation is linear to the number of elements inserted times the complexity + * of filling the \a out iterator. + * + * \pre The set is frozen. + * + * \param begin A forward iterator that points to the first element to be inserted. + * \param end A forward iterator that points to the after-the-last element to be inserted. + * \param out An output iterator that receives results of insertion of the elements. + */ + template< typename FwdIteratorT, typename OutputIteratorT > + void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out) + { + for (; begin != end; ++begin, ++out) + *out = this->insert(*begin); + } + +#ifndef BOOST_LOG_DOXYGEN_PASS +private: + //! Constructs the object by moving from \a source_attrs. This function is mostly needed to maintain ABI stable between C++03 and C++11. + BOOST_LOG_API void construct( + attribute_value_set& source_attrs, + attribute_set const& thread_attrs, + attribute_set const& global_attrs, + size_type reserve_count); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +/*! + * Free swap overload + */ +inline void swap(attribute_value_set& left, attribute_value_set& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTE_VALUE_SET_HPP_INCLUDED_ diff --git a/boost/log/attributes/clock.hpp b/boost/log/attributes/clock.hpp new file mode 100644 index 0000000000..c28da5a877 --- /dev/null +++ b/boost/log/attributes/clock.hpp @@ -0,0 +1,95 @@ +/* + * 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 clock.hpp + * \author Andrey Semashev + * \date 01.12.2007 + * + * The header contains wall clock attribute implementation and typedefs. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_CLOCK_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_CLOCK_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/attributes/time_traits.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief A class of an attribute that makes an attribute value of the current date and time + * + * The attribute generates current time stamp as a value. The type of the attribute value + * is determined with time traits passed to the class template as a template parameter. + * The time traits provided by the library use \c boost::posix_time::ptime as the time type. + * + * Time traits also determine the way time is acquired. There are two types of time traits + * provided by the library: \c utc_time_traits and \c local_time_traits. The first returns UTC time, + * the second returns local time. + */ +template< typename TimeTraitsT > +class basic_clock : + public attribute +{ +public: + //! Generated value type + typedef typename TimeTraitsT::time_type value_type; + +protected: + //! Attribute factory implementation + struct BOOST_SYMBOL_VISIBLE impl : + public attribute::impl + { + attribute_value get_value() + { + typedef attribute_value_impl< value_type > result_value; + return attribute_value(new result_value(TimeTraitsT::get_clock())); + } + }; + +public: + /*! + * Default constructor + */ + basic_clock() : attribute(new impl()) + { + } + /*! + * Constructor for casting support + */ + explicit basic_clock(cast_source const& source) : attribute(source.as< impl >()) + { + } +}; + +//! Attribute that returns current UTC time +typedef basic_clock< utc_time_traits > utc_clock; +//! Attribute that returns current local time +typedef basic_clock< local_time_traits > local_clock; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_CLOCK_HPP_INCLUDED_ diff --git a/boost/log/attributes/constant.hpp b/boost/log/attributes/constant.hpp new file mode 100644 index 0000000000..f2ae0a7847 --- /dev/null +++ b/boost/log/attributes/constant.hpp @@ -0,0 +1,122 @@ +/* + * 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 constant.hpp + * \author Andrey Semashev + * \date 15.04.2007 + * + * The header contains implementation of a constant attribute. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/embedded_string_type.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief A class of an attribute that holds a single constant value + * + * The constant is a simplest and one of the most frequently used types of attributes. + * It stores a constant value, which it eventually returns as its value each time + * requested. + */ +template< typename T > +class constant : + public attribute +{ +public: + //! Attribute value type + typedef T value_type; + +protected: + //! Factory implementation + class BOOST_SYMBOL_VISIBLE impl : + public attribute_value_impl< value_type > + { + //! Base type + typedef attribute_value_impl< value_type > base_type; + + public: + /*! + * Constructor with the stored value initialization + */ + explicit impl(value_type const& value) : base_type(value) {} + /*! + * Constructor with the stored value initialization + */ + explicit impl(BOOST_RV_REF(value_type) value) : base_type(boost::move(value)) {} + }; + +public: + /*! + * Constructor with the stored value initialization + */ + explicit constant(value_type const& value) : attribute(new impl(value)) {} + /*! + * Constructor with the stored value initialization + */ + explicit constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) {} + /*! + * Constructor for casting support + */ + explicit constant(cast_source const& source) : attribute(source.as< impl >()) + { + } + + /*! + * \return Reference to the contained value. + */ + value_type const& get() const + { + return static_cast< impl* >(this->get_impl())->get(); + } +}; + +/*! + * The function constructs a \c constant attribute containing the provided value. + * The function automatically converts C string arguments to \c std::basic_string objects. + */ +template< typename T > +inline constant< + typename boost::log::aux::make_embedded_string_type< + typename remove_reference< T >::type + >::type +> make_constant(BOOST_FWD_REF(T) val) +{ + typedef typename boost::log::aux::make_embedded_string_type< + typename remove_reference< T >::type + >::type value_type; + return constant< value_type >(boost::forward< T >(val)); +} + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_ diff --git a/boost/log/attributes/counter.hpp b/boost/log/attributes/counter.hpp new file mode 100644 index 0000000000..a4722714c9 --- /dev/null +++ b/boost/log/attributes/counter.hpp @@ -0,0 +1,218 @@ +/* + * 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 counter.hpp + * \author Andrey Semashev + * \date 01.05.2007 + * + * The header contains implementation of the counter attribute. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#ifndef BOOST_LOG_NO_THREADS +#include <boost/detail/atomic_count.hpp> +#endif // BOOST_LOG_NO_THREADS +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief A class of an attribute that counts an integral value + * + * This type of attribute acts as a counter, that is, it returns a monotonously + * changing value each time requested. The attribute value type can be specified + * as a template parameter. However, the type must be an integral type of size no + * more than <tt>sizeof(long)</tt>. + */ +template< typename T > +class counter : + public attribute +{ + // For now only integral types up to long are supported + BOOST_STATIC_ASSERT_MSG(is_integral< T >::value && sizeof(T) <= sizeof(long), "Boost.Log: Only integral types up to long are supported by counter attribute"); + +public: + //! A counter value type + typedef T value_type; + +protected: + //! Base class for factory implementation + class BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl : + public attribute::impl + { + }; + + //! Generic factory implementation + class impl_generic; +#ifndef BOOST_LOG_NO_THREADS + //! Increment-by-one factory implementation + class impl_inc; + //! Decrement-by-one factory implementation + class impl_dec; +#endif + +public: + /*! + * Constructor + * + * \param initial Initial value of the counter + * \param step Changing step of the counter. Each value acquired from the attribute + * will be greater than the previous one to this amount. + */ + explicit counter(value_type initial = (value_type)0, long step = 1) : +#ifndef BOOST_LOG_NO_THREADS + attribute() + { + if (step == 1) + this->set_impl(new impl_inc(initial)); + else if (step == -1) + this->set_impl(new impl_dec(initial)); + else + this->set_impl(new impl_generic(initial, step)); + } +#else + attribute(new impl_generic(initial, step)) + { + } +#endif + /*! + * Constructor for casting support + */ + explicit counter(cast_source const& source) : + attribute(source.as< impl >()) + { + } +}; + +#ifndef BOOST_LOG_NO_THREADS + +template< typename T > +class counter< T >::impl_generic : + public impl +{ +private: + //! Initial value + const value_type m_Initial; + //! Step value + const long m_Step; + //! The counter + boost::detail::atomic_count m_Counter; + +public: + /*! + * Initializing constructor + */ + impl_generic(value_type initial, long step) : m_Initial(initial), m_Step(step), m_Counter(-1) + { + } + + attribute_value get_value() + { + const unsigned long next_counter = static_cast< unsigned long >(++m_Counter); + value_type next = static_cast< value_type >(m_Initial + (next_counter * m_Step)); + return make_attribute_value(next); + } +}; + +template< typename T > +class counter< T >::impl_inc : + public impl +{ +private: + //! The counter + boost::detail::atomic_count m_Counter; + +public: + /*! + * Initializing constructor + */ + explicit impl_inc(value_type initial) : m_Counter(initial - 1) + { + } + + attribute_value get_value() + { + return make_attribute_value(static_cast< value_type >(++m_Counter)); + } +}; + +template< typename T > +class counter< T >::impl_dec : + public impl +{ +private: + //! The counter + boost::detail::atomic_count m_Counter; + +public: + /*! + * Initializing constructor + */ + explicit impl_dec(value_type initial) : m_Counter(initial + 1) + { + } + + attribute_value get_value() + { + return make_attribute_value(static_cast< value_type >(--m_Counter)); + } +}; + +#else // BOOST_LOG_NO_THREADS + +template< typename T > +class counter< T >::impl_generic : + public impl +{ +private: + //! Step value + const long m_Step; + //! The counter + value_type m_Counter; + +public: + /*! + * Initializing constructor + */ + impl_generic(value_type initial, long step) : m_Step(step), m_Counter(initial - step) + { + } + + attribute_value get_value() + { + m_Counter += m_Step; + return make_attribute_value(m_Counter); + } +}; + +#endif // BOOST_LOG_NO_THREADS + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ diff --git a/boost/log/attributes/current_process_id.hpp b/boost/log/attributes/current_process_id.hpp new file mode 100644 index 0000000000..d528b7d8f4 --- /dev/null +++ b/boost/log/attributes/current_process_id.hpp @@ -0,0 +1,67 @@ +/* + * 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 current_process_id.hpp + * \author Andrey Semashev + * \date 12.09.2009 + * + * The header contains implementation of a current process id attribute + */ + +#ifndef BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_ID_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_ID_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/process_id.hpp> +#include <boost/log/attributes/constant.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Process identifier type used by the library +typedef boost::log::aux::process::id process_id; + +namespace attributes { + +/*! + * \brief A class of an attribute that holds the current process identifier + */ +class current_process_id : + public constant< process_id > +{ + typedef constant< process_id > base_type; + +public: + /*! + * Constructor. Initializes the attribute with the current process identifier. + */ + current_process_id() : base_type(boost::log::aux::this_process::get_id()) {} + /*! + * Constructor for casting support + */ + explicit current_process_id(cast_source const& source) : + base_type(source) + { + } +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_ID_HPP_INCLUDED_ diff --git a/boost/log/attributes/current_process_name.hpp b/boost/log/attributes/current_process_name.hpp new file mode 100644 index 0000000000..92e78592ba --- /dev/null +++ b/boost/log/attributes/current_process_name.hpp @@ -0,0 +1,71 @@ +/* + * 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 current_process_name.hpp + * \author Andrey Semashev + * \date 29.07.2012 + * + * The header contains implementation of a current process name attribute + */ + +#ifndef BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_NAME_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_NAME_HPP_INCLUDED_ + +#include <string> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/constant.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The function returns the current process name +BOOST_LOG_API std::string get_process_name(); + +} // namespace aux + +namespace attributes { + +/*! + * \brief A class of an attribute that holds the current process name + */ +class current_process_name : + public constant< std::string > +{ + typedef constant< std::string > base_type; + +public: + /*! + * Constructor. Initializes the attribute with the current process name. + */ + current_process_name() : base_type(boost::log::aux::get_process_name()) {} + /*! + * Constructor for casting support + */ + explicit current_process_name(cast_source const& source) : + base_type(source) + { + } +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_CURRENT_PROCESS_NAME_HPP_INCLUDED_ diff --git a/boost/log/attributes/current_thread_id.hpp b/boost/log/attributes/current_thread_id.hpp new file mode 100644 index 0000000000..6b8488f5f5 --- /dev/null +++ b/boost/log/attributes/current_thread_id.hpp @@ -0,0 +1,109 @@ +/* + * 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 current_thread_id.hpp + * \author Andrey Semashev + * \date 12.09.2009 + * + * The header contains implementation of a current thread id attribute + */ + +#ifndef BOOST_LOG_ATTRIBUTES_CURRENT_THREAD_ID_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_CURRENT_THREAD_ID_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: The current_thread_id attribute is only available in multithreaded builds +#endif + +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/log/detail/thread_id.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Thread identifier type +typedef boost::log::aux::thread::id thread_id; + +namespace attributes { + +/*! + * \brief A class of an attribute that always returns the current thread identifier + * + * \note This attribute can be registered globally, it will still return the correct + * thread identifier, no matter which thread emits the log record. + */ +class current_thread_id : + public attribute +{ +public: + //! A held attribute value type + typedef thread_id value_type; + +protected: + //! Factory implementation + class BOOST_SYMBOL_VISIBLE impl : + public attribute_value::impl + { + public: + bool dispatch(type_dispatcher& dispatcher) + { + type_dispatcher::callback< value_type > callback = + dispatcher.get_callback< value_type >(); + if (callback) + { + callback(boost::log::aux::this_thread::get_id()); + return true; + } + else + return false; + } + + intrusive_ptr< attribute_value::impl > detach_from_thread() + { + typedef attribute_value_impl< value_type > detached_value; + return new detached_value(boost::log::aux::this_thread::get_id()); + } + + type_info_wrapper get_type() const { return type_info_wrapper(typeid(value_type)); } + }; + +public: + /*! + * Default constructor + */ + current_thread_id() : attribute(new impl()) + { + } + /*! + * Constructor for casting support + */ + explicit current_thread_id(cast_source const& source) : + attribute(source.as< impl >()) + { + } +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_CURRENT_THREAD_ID_HPP_INCLUDED_ diff --git a/boost/log/attributes/fallback_policy.hpp b/boost/log/attributes/fallback_policy.hpp new file mode 100644 index 0000000000..8a3c648001 --- /dev/null +++ b/boost/log/attributes/fallback_policy.hpp @@ -0,0 +1,186 @@ +/* + * 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 fallback_policy.hpp + * \author Andrey Semashev + * \date 18.08.2012 + * + * The header contains definition of fallback policies when attribute value visitation or extraction fails. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_ + +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/exceptions.hpp> +#include <boost/log/utility/type_info_wrapper.hpp> +#include <boost/log/attributes/fallback_policy_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * The \c fallback_to_none policy results in returning an empty value reference if the attribute value cannot be extracted. + */ +struct fallback_to_none +{ + enum { guaranteed_result = false }; + + /*! + * The method is called in order to apply a function object to the default value. + */ + template< typename FunT > + static bool apply_default(FunT&) + { + return false; + } + + /*! + * The method is called in order to apply a function object to the default value. + */ + template< typename FunT > + static bool apply_default(FunT const&) + { + return false; + } + + /*! + * The method is called when value extraction failed because the attribute value has different type than requested. + */ + static void on_invalid_type(type_info_wrapper const&) + { + } + + /*! + * The method is called when value extraction failed because the attribute value was not found. + */ + static void on_missing_value() + { + } +}; + +/*! + * The \c fallback_to_throw policy results in throwing an exception if the attribute value cannot be extracted. + */ +struct fallback_to_throw +{ + enum { guaranteed_result = true }; + + /*! + * The method is called in order to apply a function object to the default value. + */ + template< typename FunT > + static bool apply_default(FunT&) + { + return false; + } + + /*! + * The method is called in order to apply a function object to the default value. + */ + template< typename FunT > + static bool apply_default(FunT const&) + { + return false; + } + + /*! + * The method is called when value extraction failed because the attribute value has different type than requested. + */ + static void on_invalid_type(type_info_wrapper const& t) + { + BOOST_LOG_THROW_DESCR_PARAMS(invalid_type, "Attribute value has incompatible type", (t)); + } + + /*! + * The method is called when value extraction failed because the attribute value was not found. + */ + static void on_missing_value() + { + BOOST_LOG_THROW_DESCR(missing_value, "Attribute value not found"); + } +}; + +/*! + * The \c fallback_to_default policy results in a default value if the attribute value cannot be extracted. + */ +template< typename DefaultT > +struct fallback_to_default +{ + enum { guaranteed_result = true }; + + //! Default value type + typedef typename remove_cv< typename remove_reference< DefaultT >::type >::type default_type; + + /*! + * Default constructor. + */ + fallback_to_default() : m_default() + { + } + + /*! + * Initializing constructor. + */ + explicit fallback_to_default(default_type const& def_val) : m_default(def_val) + { + } + + /*! + * The method is called in order to apply a function object to the default value. + */ + template< typename FunT > + bool apply_default(FunT& fun) const + { + fun(m_default); + return true; + } + + /*! + * The method is called in order to apply a function object to the default value. + */ + template< typename FunT > + bool apply_default(FunT const& fun) const + { + fun(m_default); + return true; + } + + /*! + * The method is called when value extraction failed because the attribute value has different type than requested. + */ + static void on_invalid_type(type_info_wrapper const&) + { + } + + /*! + * The method is called when value extraction failed because the attribute value was not found. + */ + static void on_missing_value() + { + } + +private: + //! Default value + DefaultT m_default; +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_HPP_INCLUDED_ diff --git a/boost/log/attributes/fallback_policy_fwd.hpp b/boost/log/attributes/fallback_policy_fwd.hpp new file mode 100644 index 0000000000..b6b01e3f4f --- /dev/null +++ b/boost/log/attributes/fallback_policy_fwd.hpp @@ -0,0 +1,48 @@ +/* + * 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 fallback_policy_fwd.hpp + * \author Andrey Semashev + * \date 18.08.2012 + * + * The header contains forward declaration of fallback policies when attribute value visitation or extraction fails. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_FWD_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * The \c fallback_to_none policy results in returning an empty value reference if the attribute value cannot be extracted. + */ +struct fallback_to_none; + +/*! + * The \c fallback_to_throw policy results in throwing an exception if the attribute value cannot be extracted. + */ +struct fallback_to_throw; + +/*! + * The \c fallback_to_default policy results in a default value if the attribute value cannot be extracted. + */ +template< typename DefaultT > +struct fallback_to_default; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_ATTRIBUTES_FALLBACK_POLICY_FWD_HPP_INCLUDED_ diff --git a/boost/log/attributes/function.hpp b/boost/log/attributes/function.hpp new file mode 100644 index 0000000000..4333e321ce --- /dev/null +++ b/boost/log/attributes/function.hpp @@ -0,0 +1,170 @@ +/* + * 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 function.hpp + * \author Andrey Semashev + * \date 24.06.2007 + * + * The header contains implementation of an attribute that calls a third-party function on value acquisition. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_FUNCTION_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_FUNCTION_HPP_INCLUDED_ + +#include <boost/static_assert.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief A class of an attribute that acquires its value from a third-party function object + * + * The attribute calls a stored nullary function object to acquire each value. + * The result type of the function object is the attribute value type. + * + * It is not recommended to use this class directly. Use \c make_function convenience functions + * to construct the attribute instead. + */ +template< typename R > +class function : + public attribute +{ + BOOST_STATIC_ASSERT_MSG(!is_void< R >::value, "Boost.Log: Function object return type must not be void"); + +public: + //! The attribute value type + typedef R value_type; + +protected: + //! Base class for factory implementation + class BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl : + public attribute::impl + { + }; + + //! Factory implementation + template< typename T > + class impl_template : + public impl + { + private: + //! Functor that returns attribute values + /*! + * \note The constness signifies that the function object should avoid + * modifying its state since it's not protected against concurrent calls. + */ + const T m_Functor; + + public: + /*! + * Constructor with the stored delegate initialization + */ + explicit impl_template(T const& fun) : m_Functor(fun) {} + + attribute_value get_value() + { + return attributes::make_attribute_value(m_Functor()); + } + }; + +public: + /*! + * Initializing constructor + */ + template< typename T > + explicit function(T const& fun) : attribute(new impl_template< T >(fun)) + { + } + /*! + * Constructor for casting support + */ + explicit function(cast_source const& source) : + attribute(source.as< impl >()) + { + } +}; + +#ifndef BOOST_NO_RESULT_OF + +/*! + * The function constructs \c function attribute instance with the provided function object. + * + * \param fun Nullary functional object that returns an actual stored value for an attribute value. + * \return Pointer to the attribute instance + */ +template< typename T > +inline function< + typename remove_cv< + typename remove_reference< + typename boost::result_of< T() >::type + >::type + >::type +> make_function(T const& fun) +{ + typedef typename remove_cv< + typename remove_reference< + typename boost::result_of< T() >::type + >::type + >::type result_type; + + typedef function< result_type > function_type; + return function_type(fun); +} + +#endif // BOOST_NO_RESULT_OF + +#ifndef BOOST_LOG_DOXYGEN_PASS + +/*! + * The function constructs \c function attribute instance with the provided function object. + * Use this version if your compiler fails to determine the result type of the function object. + * + * \param fun Nullary functional object that returns an actual stored value for an attribute value. + * \return Pointer to the attribute instance + */ +template< typename R, typename T > +inline function< + typename remove_cv< + typename remove_reference< R >::type + >::type +> make_function(T const& fun) +{ + typedef typename remove_cv< + typename remove_reference< R >::type + >::type result_type; + + typedef function< result_type > function_type; + return function_type(fun); +} + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_FUNCTOR_HPP_INCLUDED_ diff --git a/boost/log/attributes/mutable_constant.hpp b/boost/log/attributes/mutable_constant.hpp new file mode 100644 index 0000000000..a668256f6a --- /dev/null +++ b/boost/log/attributes/mutable_constant.hpp @@ -0,0 +1,332 @@ +/* + * 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 mutable_constant.hpp + * \author Andrey Semashev + * \date 06.11.2007 + * + * The header contains implementation of a mutable constant attribute. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ + +#include <boost/static_assert.hpp> +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/mpl/if.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/locks.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief A class of an attribute that holds a single constant value with ability to change it + * + * The mutable_constant attribute stores a single value of type, specified as the first template argument. + * This value is returned on each attribute value acquisition. + * + * The attribute also allows to modify the stored value, even if the attribute is registered in an attribute set. + * In order to ensure thread safety of such modifications the \c mutable_constant class is also parametrized + * with three additional template arguments: mutex type, scoped write and scoped read lock types. If not specified, + * the lock types are automatically deduced based on the mutex type. + * + * The implementation may avoid using these types to actually create and use the mutex, if a more efficient synchronization method is + * available (such as atomic operations on the value type). By default no synchronization is done. + */ +#ifdef BOOST_LOG_DOXYGEN_PASS +template< typename T, typename MutexT = void, typename ScopedWriteLockT = auto, typename ScopedReadLockT = auto > +#else // BOOST_LOG_DOXYGEN_PASS +template< + typename T, + typename MutexT = void, + typename ScopedWriteLockT = +#ifndef BOOST_LOG_NO_THREADS + typename mpl::if_c< + boost::log::aux::is_exclusively_lockable< MutexT >::value, + boost::log::aux::exclusive_lock_guard< MutexT >, + void + >::type, +#else + void, +#endif // BOOST_LOG_NO_THREADS + typename ScopedReadLockT = +#ifndef BOOST_LOG_NO_THREADS + typename mpl::if_c< + boost::log::aux::is_shared_lockable< MutexT >::value, + boost::log::aux::shared_lock_guard< MutexT >, + ScopedWriteLockT + >::type +#else + ScopedWriteLockT +#endif // BOOST_LOG_NO_THREADS +#endif // BOOST_LOG_DOXYGEN_PASS +> +class mutable_constant : + public attribute +{ +public: + //! The attribute value type + typedef T value_type; + +protected: + //! Factory implementation + class BOOST_SYMBOL_VISIBLE impl : + public attribute::impl + { + private: + //! Mutex type + typedef MutexT mutex_type; + //! Shared lock type + typedef ScopedReadLockT scoped_read_lock; + //! Exclusive lock type + typedef ScopedWriteLockT scoped_write_lock; + BOOST_STATIC_ASSERT_MSG(!(is_void< mutex_type >::value || is_void< scoped_read_lock >::value || is_void< scoped_write_lock >::value), "Boost.Log: Mutex and both lock types either must not be void or must all be void"); + //! Attribute value wrapper + typedef attribute_value_impl< value_type > attr_value; + + private: + //! Thread protection mutex + mutable mutex_type m_Mutex; + //! Pointer to the actual attribute value + intrusive_ptr< attr_value > m_Value; + + public: + /*! + * Initializing constructor + */ + explicit impl(value_type const& value) : m_Value(new attr_value(value)) + { + } + /*! + * Initializing constructor + */ + explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value))) + { + } + + attribute_value get_value() + { + scoped_read_lock lock(m_Mutex); + return attribute_value(m_Value); + } + + void set(value_type const& value) + { + intrusive_ptr< attr_value > p = new attr_value(value); + scoped_write_lock lock(m_Mutex); + m_Value.swap(p); + } + + void set(BOOST_RV_REF(value_type) value) + { + intrusive_ptr< attr_value > p = new attr_value(boost::move(value)); + scoped_write_lock lock(m_Mutex); + m_Value.swap(p); + } + + value_type get() const + { + scoped_read_lock lock(m_Mutex); + return m_Value->get(); + } + }; + +public: + /*! + * Constructor with the stored value initialization + */ + explicit mutable_constant(value_type const& value) : attribute(new impl(value)) + { + } + /*! + * Constructor with the stored value initialization + */ + explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) + { + } + /*! + * Constructor for casting support + */ + explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >()) + { + } + + /*! + * The method sets a new attribute value. The implementation exclusively locks the mutex in order + * to protect the value assignment. + */ + void set(value_type const& value) + { + get_impl()->set(value); + } + + /*! + * The method sets a new attribute value. + */ + void set(BOOST_RV_REF(value_type) value) + { + get_impl()->set(boost::move(value)); + } + + /*! + * The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order + * to protect the value acquisition. + */ + value_type get() const + { + return get_impl()->get(); + } + +protected: + /*! + * \returns Pointer to the factory implementation + */ + impl* get_impl() const + { + return static_cast< impl* >(attribute::get_impl()); + } +}; + + +/*! + * \brief Specialization for unlocked case + * + * This version of attribute does not perform thread synchronization to access the stored value. + */ +template< typename T > +class mutable_constant< T, void, void, void > : + public attribute +{ +public: + //! The attribute value type + typedef T value_type; + +protected: + //! Factory implementation + class BOOST_SYMBOL_VISIBLE impl : + public attribute::impl + { + private: + //! Attribute value wrapper + typedef attribute_value_impl< value_type > attr_value; + + private: + //! The actual value + intrusive_ptr< attr_value > m_Value; + + public: + /*! + * Initializing constructor + */ + explicit impl(value_type const& value) : m_Value(new attr_value(value)) + { + } + /*! + * Initializing constructor + */ + explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value))) + { + } + + attribute_value get_value() + { + return attribute_value(m_Value); + } + + void set(value_type const& value) + { + m_Value = new attr_value(value); + } + void set(BOOST_RV_REF(value_type) value) + { + m_Value = new attr_value(boost::move(value)); + } + + value_type get() const + { + return m_Value->get(); + } + }; + +public: + /*! + * Constructor with the stored value initialization + */ + explicit mutable_constant(value_type const& value) : attribute(new impl(value)) + { + } + /*! + * Constructor with the stored value initialization + */ + explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) + { + } + /*! + * Constructor for casting support + */ + explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >()) + { + } + + /*! + * The method sets a new attribute value. + */ + void set(value_type const& value) + { + get_impl()->set(value); + } + + /*! + * The method sets a new attribute value. + */ + void set(BOOST_RV_REF(value_type) value) + { + get_impl()->set(boost::move(value)); + } + + /*! + * The method acquires the current attribute value. + */ + value_type get() const + { + return get_impl()->get(); + } + +protected: + /*! + * \returns Pointer to the factory implementation + */ + impl* get_impl() const + { + return static_cast< impl* >(attribute::get_impl()); + } +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ diff --git a/boost/log/attributes/named_scope.hpp b/boost/log/attributes/named_scope.hpp new file mode 100644 index 0000000000..7b75c3d73c --- /dev/null +++ b/boost/log/attributes/named_scope.hpp @@ -0,0 +1,474 @@ +/* + * 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 + * \author Andrey Semashev + * \date 24.06.2007 + * + * The header contains implementation of named scope container and an attribute that allows to + * put the named scope to log. A number of convenience macros are also provided. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_ + +#include <ostream> +#include <memory> +#include <iterator> +#include <cstddef> +#include <boost/log/detail/config.hpp> +#include <boost/current_function.hpp> +#include <boost/mpl/if.hpp> +#include <boost/log/utility/string_literal.hpp> +#include <boost/log/utility/unique_identifier_name.hpp> +#include <boost/log/utility/unused_variable.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +namespace aux { + + //! Double-linked list node + struct named_scope_list_node + { + mutable named_scope_list_node* _m_pPrev; + mutable named_scope_list_node* _m_pNext; + + named_scope_list_node() BOOST_NOEXCEPT { _m_pPrev = _m_pNext = this; } + }; + +} // namespace aux + +/*! + * \brief The structure contains all information about a named scope + * + * The named scope entries are stored as elements of \c basic_named_scope_list container, which + * in turn can be acquired either from the \c basic_named_scope attribute value or from a thread-local + * instance. + */ +struct named_scope_entry + //! \cond + : public aux::named_scope_list_node + //! \endcond +{ + /*! + * \brief Scope entry type + * + * Describes scope name specifics + */ + enum scope_name_type + { + general, //!< The scope name contains some unstructured string that should not be interpreted by the library + function //!< The scope name contains a function signature + }; + + /*! + * The scope name (e.g. a function signature) + */ + string_literal scope_name; + /*! + * The source file name + */ + string_literal file_name; + /*! + * The line number in the source file + */ + unsigned int line; + /*! + * The scope name type + */ + scope_name_type type; + + /*! + * Initializing constructor + * + * \post <tt>scope_name == sn && file_name == fn && line == ln</tt> + * + * \b Throws: Nothing. + */ + named_scope_entry(string_literal const& sn, string_literal const& fn, unsigned int ln, scope_name_type t = general) BOOST_NOEXCEPT : + scope_name(sn), + file_name(fn), + line(ln), + type(t) + { + } +}; + +/*! + * \brief The class implements the list of scopes + * + * The scope list provides a read-only access to a doubly-linked list of scopes. + */ +class named_scope_list + //! \cond + : protected std::allocator< named_scope_entry > + //! \endcond +{ +public: + //! Allocator type + typedef std::allocator< named_scope_entry > allocator_type; + + // Standard types + typedef allocator_type::value_type value_type; + typedef allocator_type::reference reference; + typedef allocator_type::const_reference const_reference; + typedef allocator_type::pointer pointer; + typedef allocator_type::const_pointer const_pointer; + typedef allocator_type::size_type size_type; + typedef allocator_type::difference_type difference_type; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +protected: + //! Iterator class +#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS + template< bool fConstV > class iter; + template< bool fConstV > friend class iter; +#endif + template< bool fConstV > + class iter + { + friend class iter< !fConstV >; + + public: + // Standard typedefs + typedef named_scope_list::difference_type difference_type; + typedef named_scope_list::value_type value_type; + typedef typename mpl::if_c< + fConstV, + named_scope_list::const_reference, + named_scope_list::reference + >::type reference; + typedef typename mpl::if_c< + fConstV, + named_scope_list::const_pointer, + named_scope_list::pointer + >::type pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + public: + // Constructors + iter() : m_pNode(NULL) {} + explicit iter(aux::named_scope_list_node* pNode) : m_pNode(pNode) {} + iter(iter< false > const& that) : m_pNode(that.m_pNode) {} + + //! Assignment + template< bool f > + iter& operator= (iter< f > const& that) + { + m_pNode = that.m_pNode; + return *this; + } + + // Comparison + template< bool f > + bool operator== (iter< f > const& that) const { return (m_pNode == that.m_pNode); } + template< bool f > + bool operator!= (iter< f > const& that) const { return (m_pNode != that.m_pNode); } + + // Modification + iter& operator++ () + { + m_pNode = m_pNode->_m_pNext; + return *this; + } + iter& operator-- () + { + m_pNode = m_pNode->_m_pPrev; + return *this; + } + iter operator++ (int) + { + iter tmp(*this); + m_pNode = m_pNode->_m_pNext; + return tmp; + } + iter operator-- (int) + { + iter tmp(*this); + m_pNode = m_pNode->_m_pPrev; + return tmp; + } + + // Dereferencing + pointer operator-> () const { return static_cast< pointer >(m_pNode); } + reference operator* () const { return *static_cast< pointer >(m_pNode); } + + private: + aux::named_scope_list_node* m_pNode; + }; + +public: + typedef iter< true > const_iterator; + typedef iter< false > iterator; + typedef std::reverse_iterator< const_iterator > const_reverse_iterator; + typedef std::reverse_iterator< iterator > reverse_iterator; + +protected: + //! The root node of the container + aux::named_scope_list_node m_RootNode; + //! The size of the container + size_type m_Size; + //! The flag shows if the contained elements are dynamically allocated + bool m_fNeedToDeallocate; + +#else // BOOST_LOG_DOXYGEN_PASS + + /*! + * A constant iterator to the sequence of scopes. Complies to bidirectional iterator requirements. + */ + typedef implementation_defined const_iterator; + /*! + * An iterator to the sequence of scopes. Complies to bidirectional iterator requirements. + */ + typedef implementation_defined iterator; + /*! + * A constant reverse iterator to the sequence of scopes. Complies to bidirectional iterator requirements. + */ + typedef implementation_defined const_reverse_iterator; + /*! + * A reverse iterator to the sequence of scopes. Complies to bidirectional iterator requirements. + */ + typedef implementation_defined reverse_iterator; + +#endif // BOOST_LOG_DOXYGEN_PASS + +public: + /*! + * Default constructor + * + * \post <tt>empty() == true</tt> + */ + named_scope_list() : m_Size(0), m_fNeedToDeallocate(false) {} + /*! + * Copy constructor + * + * \post <tt>std::equal(begin(), end(), that.begin()) == true</tt> + */ + BOOST_LOG_API named_scope_list(named_scope_list const& that); + /*! + * Destructor. Destroys the stored entries. + */ + BOOST_LOG_API ~named_scope_list(); + + /*! + * Assignment operator + * + * \post <tt>std::equal(begin(), end(), that.begin()) == true</tt> + */ + named_scope_list& operator= (named_scope_list const& that) + { + if (this != &that) + { + named_scope_list tmp(that); + swap(tmp); + } + return *this; + } + + /*! + * \return Constant iterator to the first element of the container. + */ + const_iterator begin() const { return const_iterator(m_RootNode._m_pNext); } + /*! + * \return Constant iterator to the after-the-last element of the container. + */ + const_iterator end() const { return const_iterator(const_cast< aux::named_scope_list_node* >(&m_RootNode)); } + /*! + * \return Constant iterator to the last element of the container. + */ + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + /*! + * \return Constant iterator to the before-the-first element of the container. + */ + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + /*! + * \return The number of elements in the container + */ + size_type size() const { return m_Size; } + /*! + * \return true if the container is empty and false otherwise + */ + bool empty() const { return (m_Size == 0); } + + /*! + * Swaps two instances of the container + */ + BOOST_LOG_API void swap(named_scope_list& that); + + /*! + * \return Last pushed scope entry + */ + const_reference back() const { return *rbegin(); } + /*! + * \return First pushed scope entry + */ + const_reference front() const { return *begin(); } +}; + +//! Stream output operator +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, named_scope_list const& sl) +{ + if (strm.good()) + { + named_scope_list::const_iterator it = sl.begin(), end = sl.end(); + if (it != end) + { + strm << it->scope_name.c_str(); + for (++it; it != end; ++it) + strm << "->" << it->scope_name.c_str(); + } + } + return strm; +} + +/*! + * \brief A class of an attribute that holds stack of named scopes of the current thread + * + * The basic_named_scope attribute is essentially a hook to the thread-specific instance of + * scope list. This means that the attribute will generate different values if get_value is + * called in different threads. The attribute generates value with stored type + * <tt>basic_named_scope_list< CharT ></tt>. + * + * The attribute class can also be used to gain access to the scope stack instance, e.g. to + * get its copy or to push or pop a scope entry. However, it is highly not recommended to + * maintain scope list manually. Use \c BOOST_LOG_NAMED_SCOPE or \c BOOST_LOG_FUNCTION macros instead. + */ +class BOOST_LOG_API named_scope : + public attribute +{ +public: + //! Scope names stack (the attribute value type) + typedef named_scope_list value_type; + //! Scope entry + typedef value_type::value_type scope_entry; + + //! Sentry object class to automatically push and pop scopes + struct sentry + { + /*! + * Constructor. Pushes the specified scope to the end of the thread-local list of scopes. + * + * \param sn Scope name. + * \param fn File name, in which the scope is located. + * \param ln Line number in the file. + */ + sentry(string_literal const& sn, string_literal const& fn, unsigned int ln, scope_entry::scope_name_type t = scope_entry::general) BOOST_NOEXCEPT : + m_Entry(sn, fn, ln, t) + { + named_scope::push_scope(m_Entry); + } + + /*! + * Destructor. Removes the last pushed scope from the thread-local list of scopes. + */ + ~sentry() BOOST_NOEXCEPT + { + named_scope::pop_scope(); + } + + BOOST_DELETED_FUNCTION(sentry(sentry const&)) + BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&)) + + private: + scope_entry m_Entry; + }; + +private: + //! Attribute implementation class + struct BOOST_SYMBOL_VISIBLE impl; + +public: + /*! + * Constructor. Creates an attribute. + */ + named_scope(); + /*! + * Constructor for casting support + */ + explicit named_scope(cast_source const& source); + + /*! + * The method pushes the scope to the back of the current thread's scope list + * + * \b Throws: Nothing. + */ + static void push_scope(scope_entry const& entry) BOOST_NOEXCEPT; + /*! + * The method pops the last pushed scope from the current thread's scope list + * + * \b Throws: Nothing. + */ + static void pop_scope() BOOST_NOEXCEPT; + + /*! + * \return The current thread's list of scopes + * + * \note The returned reference is only valid until the current thread ends. The scopes in the + * returned container may change if the execution scope is changed (i.e. either \c push_scope + * or \c pop_scope is called). User has to copy the stack if he wants to keep it intact regardless + * of the execution scope. + */ + static value_type const& get_scopes(); +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_NAMED_SCOPE_INTERNAL(var, name, file, line, type)\ + BOOST_LOG_UNUSED_VARIABLE(::boost::log::attributes::named_scope::sentry, var, (name, file, line, type)); + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * Macro for scope markup. The specified scope name is pushed to the end of the current thread scope list. + */ +#define BOOST_LOG_NAMED_SCOPE(name)\ + BOOST_LOG_NAMED_SCOPE_INTERNAL(BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_named_scope_sentry_), name, __FILE__, __LINE__, ::boost::log::attributes::named_scope_entry::general) + +/*! + * Macro for function scope markup. The scope name is constructed with help of compiler and contains the current function signature. + * The scope name is pushed to the end of the current thread scope list. + * + * Not all compilers have support for this macro. The exact form of the scope name may vary from one compiler to another. + */ +#define BOOST_LOG_FUNCTION()\ + BOOST_LOG_NAMED_SCOPE_INTERNAL(BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_named_scope_sentry_), BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, ::boost::log::attributes::named_scope_entry::function) + +/*! + * Macro for function scope markup. The scope name is constructed with help of compiler and contains the current function name. It may be shorter than what \c BOOST_LOG_FUNCTION macro produces. + * The scope name is pushed to the end of the current thread scope list. + * + * Not all compilers have support for this macro. The exact form of the scope name may vary from one compiler to another. + */ +#if defined(_MSC_VER) || defined(__GNUC__) +#define BOOST_LOG_FUNC() BOOST_LOG_NAMED_SCOPE(__FUNCTION__) +#else +#define BOOST_LOG_FUNC() BOOST_LOG_FUNCTION() +#endif + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_ diff --git a/boost/log/attributes/scoped_attribute.hpp b/boost/log/attributes/scoped_attribute.hpp new file mode 100644 index 0000000000..33b1c395fe --- /dev/null +++ b/boost/log/attributes/scoped_attribute.hpp @@ -0,0 +1,253 @@ +/* + * 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 scoped_attribute.hpp + * \author Andrey Semashev + * \date 13.05.2007 + * + * The header contains definition of facilities to define scoped attributes. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_ + +#include <utility> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/core/core.hpp> +#include <boost/log/sources/basic_logger.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_set.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/constant.hpp> +#include <boost/log/utility/unused_variable.hpp> +#include <boost/log/utility/unique_identifier_name.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A base class for all scoped attribute guards +class attribute_scope_guard +{ +}; + +} // namespace aux + +//! Scoped attribute guard type +typedef aux::attribute_scope_guard const& scoped_attribute; + +namespace aux { + +//! A scoped logger attribute guard +template< typename LoggerT > +class scoped_logger_attribute : + public attribute_scope_guard +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(scoped_logger_attribute) + +private: + //! Logger type + typedef LoggerT logger_type; + +private: + //! A reference to the logger + logger_type* m_pLogger; + //! An iterator to the added attribute + attribute_set::iterator m_itAttribute; + +public: + //! Constructor + scoped_logger_attribute(logger_type& l, attribute_name const& name, attribute const& attr) : + m_pLogger(boost::addressof(l)) + { + std::pair< + attribute_set::iterator, + bool + > res = l.add_attribute(name, attr); + if (res.second) + m_itAttribute = res.first; + else + m_pLogger = 0; // if there already is a same-named attribute, don't register anything + } + //! Move constructor + scoped_logger_attribute(BOOST_RV_REF(scoped_logger_attribute) that) : + m_pLogger(that.m_pLogger), + m_itAttribute(that.m_itAttribute) + { + that.m_pLogger = 0; + } + + //! Destructor + ~scoped_logger_attribute() + { + if (m_pLogger) + m_pLogger->remove_attribute(m_itAttribute); + } + +#ifndef BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT + BOOST_DELETED_FUNCTION(scoped_logger_attribute(scoped_logger_attribute const&)) +#else // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT + scoped_logger_attribute(scoped_logger_attribute const& that) : m_pLogger(that.m_pLogger), m_itAttribute(that.m_itAttribute) + { + const_cast< scoped_logger_attribute& >(that).m_pLogger = 0; + } +#endif // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT + + BOOST_DELETED_FUNCTION(scoped_logger_attribute& operator= (scoped_logger_attribute const&)) +}; + +} // namespace aux + +// Generator helper functions +/*! + * Registers an attribute in the logger + * + * \param l Logger to register the attribute in + * \param name Attribute name + * \param attr The attribute. Must not be NULL. + * \return An unspecified guard object which may be used to initialize a \c scoped_attribute variable. + */ +template< typename LoggerT > +BOOST_FORCEINLINE aux::scoped_logger_attribute< LoggerT > add_scoped_logger_attribute(LoggerT& l, attribute_name const& name, attribute const& attr) +{ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + return aux::scoped_logger_attribute< LoggerT >(l, name, attr); +#else + aux::scoped_logger_attribute< LoggerT > guard(l, name, attr); + return boost::move(guard); +#endif +} + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_SCOPED_LOGGER_ATTR_INTERNAL(logger, attr_name, attr, sentry_var_name)\ + BOOST_LOG_UNUSED_VARIABLE(::boost::log::scoped_attribute, sentry_var_name,\ + = ::boost::log::add_scoped_logger_attribute(logger, attr_name, (attr))); + +#endif // BOOST_LOG_DOXYGEN_PASS + +//! The macro sets a scoped logger-wide attribute in a more compact way +#define BOOST_LOG_SCOPED_LOGGER_ATTR(logger, attr_name, attr)\ + BOOST_LOG_SCOPED_LOGGER_ATTR_INTERNAL(\ + logger,\ + attr_name,\ + attr,\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_scoped_logger_attr_sentry_)) + +//! The macro sets a scoped logger-wide tag in a more compact way +#define BOOST_LOG_SCOPED_LOGGER_TAG(logger, attr_name, attr_value)\ + BOOST_LOG_SCOPED_LOGGER_ATTR(logger, attr_name, ::boost::log::attributes::make_constant(attr_value)) + +namespace aux { + +//! A scoped thread-specific attribute guard +class scoped_thread_attribute : + public attribute_scope_guard +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(scoped_thread_attribute) + +private: + //! A pointer to the logging core + core_ptr m_pCore; + //! An iterator to the added attribute + attribute_set::iterator m_itAttribute; + +public: + //! Constructor + scoped_thread_attribute(attribute_name const& name, attribute const& attr) : + m_pCore(core::get()) + { + std::pair< + attribute_set::iterator, + bool + > res = m_pCore->add_thread_attribute(name, attr); + if (res.second) + m_itAttribute = res.first; + else + m_pCore.reset(); // if there already is a same-named attribute, don't register anything + } + //! Move constructor + scoped_thread_attribute(BOOST_RV_REF(scoped_thread_attribute) that) : m_itAttribute(that.m_itAttribute) + { + m_pCore.swap(that.m_pCore); + } + + //! Destructor + ~scoped_thread_attribute() + { + if (!!m_pCore) + m_pCore->remove_thread_attribute(m_itAttribute); + } + +#ifndef BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT + BOOST_DELETED_FUNCTION(scoped_thread_attribute(scoped_thread_attribute const&)) +#else // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT + scoped_thread_attribute(scoped_thread_attribute const& that) : m_itAttribute(that.m_itAttribute) + { + m_pCore.swap(const_cast< scoped_thread_attribute& >(that).m_pCore); + } +#endif // BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT + + BOOST_DELETED_FUNCTION(scoped_thread_attribute& operator= (scoped_thread_attribute const&)) +}; + +} // namespace aux + +// Generator helper functions +/*! + * Registers a thread-specific attribute + * + * \param name Attribute name + * \param attr The attribute. Must not be NULL. + * \return An unspecified guard object which may be used to initialize a \c scoped_attribute variable. + */ +BOOST_FORCEINLINE aux::scoped_thread_attribute add_scoped_thread_attribute(attribute_name const& name, attribute const& attr) +{ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + return aux::scoped_thread_attribute(name, attr); +#else + aux::scoped_thread_attribute guard(name, attr); + return boost::move(guard); +#endif +} + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_SCOPED_THREAD_ATTR_INTERNAL(attr_name, attr, sentry_var_name)\ + BOOST_LOG_UNUSED_VARIABLE(::boost::log::scoped_attribute, sentry_var_name,\ + = ::boost::log::add_scoped_thread_attribute(attr_name, (attr))); + +#endif // BOOST_LOG_DOXYGEN_PASS + +//! The macro sets a scoped thread-wide attribute in a more compact way +#define BOOST_LOG_SCOPED_THREAD_ATTR(attr_name, attr)\ + BOOST_LOG_SCOPED_THREAD_ATTR_INTERNAL(\ + attr_name,\ + attr,\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_scoped_thread_attr_sentry_)) + +//! The macro sets a scoped thread-wide tag in a more compact way +#define BOOST_LOG_SCOPED_THREAD_TAG(attr_name, attr_value)\ + BOOST_LOG_SCOPED_THREAD_ATTR(attr_name, ::boost::log::attributes::make_constant(attr_value)) + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_SCOPED_ATTRIBUTE_HPP_INCLUDED_ diff --git a/boost/log/attributes/time_traits.hpp b/boost/log/attributes/time_traits.hpp new file mode 100644 index 0000000000..9a967f8cb8 --- /dev/null +++ b/boost/log/attributes/time_traits.hpp @@ -0,0 +1,81 @@ +/* + * 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 time_traits.hpp + * \author Andrey Semashev + * \date 01.12.2007 + * + * The header contains implementation of time traits that are used in various parts of the + * library to acquire current time. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_TIME_TRAITS_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_TIME_TRAITS_HPP_INCLUDED_ + +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +//! Base class for time traits involving Boost.DateTime. +struct basic_time_traits +{ + //! Time type + typedef posix_time::ptime time_type; + + //! Current time source +#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + typedef posix_time::microsec_clock clock_source; +#else + typedef posix_time::second_clock clock_source; +#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) +}; + +//! Time traits that describes UTC time acquirement via Boost.DateTime facilities +struct utc_time_traits : + public basic_time_traits +{ + /*! + * \return Current time stamp + */ + static time_type get_clock() + { + return clock_source::universal_time(); + } +}; + +//! Time traits that describes local time acquirement via Boost.DateTime facilities +struct local_time_traits : + public basic_time_traits +{ + /*! + * \return Current time stamp + */ + static time_type get_clock() + { + return clock_source::local_time(); + } +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_TIME_TRAITS_HPP_INCLUDED_ diff --git a/boost/log/attributes/timer.hpp b/boost/log/attributes/timer.hpp new file mode 100644 index 0000000000..ae7d65ebfd --- /dev/null +++ b/boost/log/attributes/timer.hpp @@ -0,0 +1,83 @@ +/* + * 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 timer.hpp + * \author Andrey Semashev + * \date 02.12.2007 + * + * The header contains implementation of a stop watch attribute. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_TIMER_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_TIMER_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/time_traits.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace attributes { + +/*! + * \brief A class of an attribute that makes an attribute value of the time interval since construction + * + * The timer attribute calculates the time passed since its construction and returns it on value acquisition. + * The attribute value type is <tt>boost::posix_time::time_duration</tt>. + * + * On Windows platform there are two implementations of the attribute. The default one is more precise but + * a bit slower. This version uses <tt>QueryPerformanceFrequence</tt>/<tt>QueryPerformanceCounter</tt> API + * to calculate elapsed time. + * + * There are known problems with these functions when used with some CPUs, notably AMD Athlon with + * Cool'n'Quiet technology enabled. See the following links for more information and possible resolutions: + * + * http://support.microsoft.com/?scid=kb;en-us;895980 + * http://support.microsoft.com/?id=896256 + * + * In case if none of these solutions apply, you are free to define <tt>BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER</tt> macro to + * fall back to another implementation based on Boost.DateTime. + */ +class BOOST_LOG_API timer : + public attribute +{ +public: + //! Attribute value type + typedef utc_time_traits::time_type::time_duration_type value_type; + +private: + //! Factory implementation + class BOOST_SYMBOL_VISIBLE impl; + +public: + /*! + * Constructor. Starts time counting. + */ + timer(); + /*! + * Constructor for casting support + */ + explicit timer(cast_source const& source); +}; + +} // namespace attributes + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_TIMER_HPP_INCLUDED_ diff --git a/boost/log/attributes/value_extraction.hpp b/boost/log/attributes/value_extraction.hpp new file mode 100644 index 0000000000..84ee3ddf8d --- /dev/null +++ b/boost/log/attributes/value_extraction.hpp @@ -0,0 +1,816 @@ +/* + * 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 value_extraction.hpp + * \author Andrey Semashev + * \date 01.03.2008 + * + * The header contains implementation of tools for extracting an attribute value + * from the view. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_HPP_INCLUDED_ + +#include <boost/mpl/vector.hpp> +#include <boost/mpl/joint_view.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/is_sequence.hpp> +#include <boost/mpl/contains.hpp> +#include <boost/mpl/push_back.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/exceptions.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/attributes/value_extraction_fwd.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/utility/value_ref.hpp> +#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace result_of { + +/*! + * \brief A metafunction that allows to acquire the result of the value extraction + * + * The metafunction results in a type that is in form of <tt>T const&</tt>, if \c T is + * not an MPL type sequence and <tt>DefaultT</tt> is the same as <tt>T</tt>, + * or <tt>value_ref< TypesT, TagT ></tt> otherwise, with + * \c TypesT being a type sequence comprising the types from sequence \c T and \c DefaultT, + * if it is not present in \c T already. + */ +template< typename T, typename DefaultT, typename TagT > +struct extract_or_default +{ + typedef typename mpl::eval_if< + mpl::is_sequence< T >, + mpl::eval_if< + mpl::contains< T, DefaultT >, + mpl::identity< T >, + mpl::push_back< T, DefaultT > + >, + mpl::if_< + is_same< T, DefaultT >, + T, + mpl::vector2< T, DefaultT > + > + >::type extracted_type; + + typedef typename mpl::if_< + mpl::is_sequence< extracted_type >, + value_ref< extracted_type, TagT >, + extracted_type const& + >::type type; +}; + +/*! + * \brief A metafunction that allows to acquire the result of the value extraction + * + * The metafunction results in a type that is in form of <tt>T const&</tt>, if \c T is + * not an MPL type sequence, or <tt>value_ref< T, TagT ></tt> otherwise. In the latter + * case the value reference shall never be empty. + */ +template< typename T, typename TagT > +struct extract_or_throw +{ + typedef typename mpl::if_< + mpl::is_sequence< T >, + value_ref< T, TagT >, + T const& + >::type type; +}; + +/*! + * \brief A metafunction that allows to acquire the result of the value extraction + * + * The metafunction results in a type that is in form of <tt>value_ref< T, TagT ></tt>. + */ +template< typename T, typename TagT > +struct extract +{ + typedef value_ref< T, TagT > type; +}; + +} // namespace result_of + +namespace aux { + +//! The function object initializes the value reference +template< typename RefT > +struct value_ref_initializer +{ + typedef void result_type; + + value_ref_initializer(RefT& ref) : m_ref(ref) + { + } + + template< typename ArgT > + result_type operator() (ArgT const& arg) const + { + m_ref = RefT(arg); + } + +private: + RefT& m_ref; +}; + +//! The function unwraps \c value_ref, if possible +template< typename T, typename TagT > +BOOST_FORCEINLINE typename enable_if< mpl::is_sequence< T >, value_ref< T, TagT > >::type +unwrap_value_ref(value_ref< T, TagT > const& r) +{ + return r; +} + +template< typename T, typename TagT > +BOOST_FORCEINLINE typename disable_if< mpl::is_sequence< T >, T const& >::type +unwrap_value_ref(value_ref< T, TagT > const& r) +{ + return r.get(); +} + +} // namespace aux + +/*! + * \brief Generic attribute value extractor + * + * Attribute value extractor is a functional object that attempts to find and extract the stored + * attribute value from the attribute values view or a log record. The extracted value is returned + * from the extractor. + */ +template< typename T, typename FallbackPolicyT, typename TagT > +class value_extractor : + private FallbackPolicyT +{ +public: + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + //! Attribute value types + typedef T value_type; + //! Function object result type + typedef value_ref< value_type, TagT > result_type; + +public: + /*! + * Default constructor + */ + BOOST_DEFAULTED_FUNCTION(value_extractor(), {}) + + /*! + * Copy constructor + */ + value_extractor(value_extractor const& that) : fallback_policy(static_cast< fallback_policy const& >(that)) + { + } + + /*! + * Constructor + * + * \param arg Fallback policy constructor argument + */ + template< typename U > + explicit value_extractor(U const& arg) : fallback_policy(arg) {} + + /*! + * Extraction operator. Attempts to acquire the stored value of one of the supported types. If extraction succeeds, + * the extracted value is returned. + * + * \param attr The attribute value to extract from. + * \return The extracted value, if extraction succeeded, an empty value otherwise. + */ + result_type operator() (attribute_value const& attr) const + { + result_type res; + aux::value_ref_initializer< result_type > initializer(res); + if (!!attr) + { + static_type_dispatcher< value_type > disp(initializer); + if (!attr.dispatch(disp) && !fallback_policy::apply_default(initializer)) + fallback_policy::on_invalid_type(attr.get_type()); + } + else if (!fallback_policy::apply_default(initializer)) + { + fallback_policy::on_missing_value(); + } + return res; + } + + /*! + * Extraction operator. Looks for an attribute value with the specified name + * and tries to acquire the stored value of one of the supported types. If extraction succeeds, + * the extracted value is returned. + * + * \param name Attribute value name. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \return The extracted value, if extraction succeeded, an empty value otherwise. + */ + result_type operator() (attribute_name const& name, attribute_value_set const& attrs) const + { + try + { + attribute_value_set::const_iterator it = attrs.find(name); + if (it != attrs.end()) + return operator() (it->second); + else + return operator() (attribute_value()); + } + catch (exception& e) + { + // Attach the attribute name to the exception + boost::log::aux::attach_attribute_name_info(e, name); + throw; + } + } + + /*! + * Extraction operator. Looks for an attribute value with the specified name + * and tries to acquire the stored value of one of the supported types. If extraction succeeds, + * the extracted value is returned. + * + * \param name Attribute value name. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \return The extracted value, if extraction succeeded, an empty value otherwise. + */ + result_type operator() (attribute_name const& name, record const& rec) const + { + return operator() (name, rec.attribute_values()); + } + + /*! + * Extraction operator. Looks for an attribute value with the specified name + * and tries to acquire the stored value of one of the supported types. If extraction succeeds, + * the extracted value is returned. + * + * \param name Attribute value name. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \return The extracted value, if extraction succeeded, an empty value otherwise. + */ + result_type operator() (attribute_name const& name, record_view const& rec) const + { + return operator() (name, rec.attribute_values()); + } + + /*! + * \returns Fallback policy + */ + fallback_policy const& get_fallback_policy() const + { + return *static_cast< fallback_policy const* >(this); + } +}; + +#if !defined(BOOST_LOG_DOXYGEN_PASS) +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) +#define BOOST_LOG_AUX_VOID_DEFAULT = void +#else +#define BOOST_LOG_AUX_VOID_DEFAULT +#endif +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param name The name of the attribute value to extract. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract< T, TagT >::type extract(attribute_name const& name, attribute_value_set const& attrs) +{ + value_extractor< T, fallback_to_none, TagT > extractor; + return extractor(name, attrs); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param name The name of the attribute value to extract. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract< T, TagT >::type extract(attribute_name const& name, record const& rec) +{ + value_extractor< T, fallback_to_none, TagT > extractor; + return extractor(name, rec); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param name The name of the attribute value to extract. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract< T, TagT >::type extract(attribute_name const& name, record_view const& rec) +{ + value_extractor< T, fallback_to_none, TagT > extractor; + return extractor(name, rec); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param value Attribute value. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract< T, TagT >::type extract(attribute_value const& value) +{ + value_extractor< T, fallback_to_none, TagT > extractor; + return extractor(value); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param name The name of the attribute value to extract. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_name const& name, attribute_value_set const& attrs) +{ + value_extractor< T, fallback_to_throw, TagT > extractor; + return aux::unwrap_value_ref(extractor(name, attrs)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param name The name of the attribute value to extract. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_name const& name, record const& rec) +{ + value_extractor< T, fallback_to_throw, TagT > extractor; + return aux::unwrap_value_ref(extractor(name, rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param name The name of the attribute value to extract. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_name const& name, record_view const& rec) +{ + value_extractor< T, fallback_to_throw, TagT > extractor; + return aux::unwrap_value_ref(extractor(name, rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param value Attribute value. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT > +inline typename result_of::extract_or_throw< T, TagT >::type extract_or_throw(attribute_value const& value) +{ + value_extractor< T, fallback_to_throw, TagT > extractor; + return aux::unwrap_value_ref(extractor(value)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param name The name of the attribute value to extract. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT, TagT >::type +extract_or_default(attribute_name const& name, attribute_value_set const& attrs, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val); + return aux::unwrap_value_ref(extractor(name, attrs)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param name The name of the attribute value to extract. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT, TagT >::type +extract_or_default(attribute_name const& name, record const& rec, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val); + return aux::unwrap_value_ref(extractor(name, rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param name The name of the attribute value to extract. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT, TagT >::type +extract_or_default(attribute_name const& name, record_view const& rec, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val); + return aux::unwrap_value_ref(extractor(name, rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param value Attribute value. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename T, typename TagT BOOST_LOG_AUX_VOID_DEFAULT, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT, TagT >::type extract_or_default(attribute_value const& value, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT, TagT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, TagT > extractor(def_val); + return aux::unwrap_value_ref(extractor(value)); +} + +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + +template< typename T > +inline typename result_of::extract< T >::type extract(attribute_name const& name, attribute_value_set const& attrs) +{ + value_extractor< T, fallback_to_none > extractor; + return extractor(name, attrs); +} + +template< typename T > +inline typename result_of::extract< T >::type extract(attribute_name const& name, record const& rec) +{ + value_extractor< T, fallback_to_none > extractor; + return extractor(name, rec); +} + +template< typename T > +inline typename result_of::extract< T >::type extract(attribute_name const& name, record_view const& rec) +{ + value_extractor< T, fallback_to_none > extractor; + return extractor(name, rec); +} + +template< typename T > +inline typename result_of::extract< T >::type extract(attribute_value const& value) +{ + value_extractor< T, fallback_to_none > extractor; + return extractor(value); +} + +template< typename T > +inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_name const& name, attribute_value_set const& attrs) +{ + value_extractor< T, fallback_to_throw > extractor; + return aux::unwrap_value_ref(extractor(name, attrs)); +} + +template< typename T > +inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_name const& name, record const& rec) +{ + value_extractor< T, fallback_to_throw > extractor; + return aux::unwrap_value_ref(extractor(name, rec)); +} + +template< typename T > +inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_name const& name, record_view const& rec) +{ + value_extractor< T, fallback_to_throw > extractor; + return aux::unwrap_value_ref(extractor(name, rec)); +} + +template< typename T > +inline typename result_of::extract_or_throw< T >::type extract_or_throw(attribute_value const& value) +{ + value_extractor< T, fallback_to_throw > extractor; + return aux::unwrap_value_ref(extractor(value)); +} + +template< typename T, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default( + attribute_name const& name, attribute_value_set const& attrs, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val); + return aux::unwrap_value_ref(extractor(name, attrs)); +} + +template< typename T, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default( + attribute_name const& name, record const& rec, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val); + return aux::unwrap_value_ref(extractor(name, rec)); +} + +template< typename T, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default( + attribute_name const& name, record_view const& rec, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val); + return aux::unwrap_value_ref(extractor(name, rec)); +} + +template< typename T, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT >::type extract_or_default(attribute_value const& value, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< T, DefaultT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& > > extractor(def_val); + return aux::unwrap_value_ref(extractor(value)); +} + +#endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param keyword The keyword of the attribute value to extract. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename DescriptorT, template< typename > class ActorT > +inline typename result_of::extract< typename DescriptorT::value_type, DescriptorT >::type +extract(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs) +{ + value_extractor< typename DescriptorT::value_type, fallback_to_none, DescriptorT > extractor; + return extractor(keyword.get_name(), attrs); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param keyword The keyword of the attribute value to extract. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename DescriptorT, template< typename > class ActorT > +inline typename result_of::extract< typename DescriptorT::value_type, DescriptorT >::type +extract(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec) +{ + value_extractor< typename DescriptorT::value_type, fallback_to_none, DescriptorT > extractor; + return extractor(keyword.get_name(), rec); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param keyword The keyword of the attribute value to extract. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \return A \c value_ref that refers to the extracted value, if found. An empty value otherwise. + */ +template< typename DescriptorT, template< typename > class ActorT > +inline typename result_of::extract< typename DescriptorT::value_type, DescriptorT >::type +extract(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec) +{ + value_extractor< typename DescriptorT::value_type, fallback_to_none, DescriptorT > extractor; + return extractor(keyword.get_name(), rec); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param keyword The keyword of the attribute value to extract. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename DescriptorT, template< typename > class ActorT > +inline typename result_of::extract_or_throw< typename DescriptorT::value_type, DescriptorT >::type +extract_or_throw(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs) +{ + value_extractor< typename DescriptorT::value_type, fallback_to_throw, DescriptorT > extractor; + return aux::unwrap_value_ref(extractor(keyword.get_name(), attrs)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param keyword The keyword of the attribute value to extract. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename DescriptorT, template< typename > class ActorT > +inline typename result_of::extract_or_throw< typename DescriptorT::value_type, DescriptorT >::type +extract_or_throw(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec) +{ + value_extractor< typename DescriptorT::value_type, fallback_to_throw, DescriptorT > extractor; + return aux::unwrap_value_ref(extractor(keyword.get_name(), rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \param keyword The keyword of the attribute value to extract. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \return The extracted value or a non-empty \c value_ref that refers to the value. + * \throws An exception is thrown if the requested value cannot be extracted. + */ +template< typename DescriptorT, template< typename > class ActorT > +inline typename result_of::extract_or_throw< typename DescriptorT::value_type, DescriptorT >::type +extract_or_throw(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec) +{ + value_extractor< typename DescriptorT::value_type, fallback_to_throw, DescriptorT > extractor; + return aux::unwrap_value_ref(extractor(keyword.get_name(), rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be extracted. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param keyword The keyword of the attribute value to extract. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename DescriptorT, template< typename > class ActorT, typename DefaultT > +inline typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::type +extract_or_default(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, DescriptorT > extractor(def_val); + return aux::unwrap_value_ref(extractor(keyword.get_name(), attrs)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param keyword The keyword of the attribute value to extract. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename DescriptorT, template< typename > class ActorT, typename DefaultT > +inline typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::type +extract_or_default(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, DescriptorT > extractor(def_val); + return aux::unwrap_value_ref(extractor(keyword.get_name(), rec)); +} + +/*! + * The function extracts an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \note Caution must be exercised if the default value is a temporary object. Because the function returns + * a reference, if the temporary object is destroyed, the reference may become dangling. + * + * \param keyword The keyword of the attribute value to extract. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \param def_val The default value + * \return The extracted value, if found. The default value otherwise. + */ +template< typename DescriptorT, template< typename > class ActorT, typename DefaultT > +inline typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::type +extract_or_default(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec, DefaultT const& def_val) +{ + typedef typename result_of::extract_or_default< typename DescriptorT::value_type, DefaultT, DescriptorT >::extracted_type extracted_type; + value_extractor< extracted_type, fallback_to_default< DefaultT const& >, DescriptorT > extractor(def_val); + return aux::unwrap_value_ref(extractor(keyword.get_name(), rec)); +} + +#if !defined(BOOST_LOG_DOXYGEN_PASS) + +template< typename T, typename TagT > +inline typename result_of::extract< T, TagT >::type attribute_value::extract() const +{ + return boost::log::extract< T, TagT >(*this); +} + +template< typename T, typename TagT > +inline typename result_of::extract_or_throw< T, TagT >::type attribute_value::extract_or_throw() const +{ + return boost::log::extract_or_throw< T, TagT >(*this); +} + +template< typename T, typename TagT > +inline typename result_of::extract_or_default< T, T, TagT >::type attribute_value::extract_or_default(T const& def_value) const +{ + return boost::log::extract_or_default< T, TagT >(*this, def_value); +} + +template< typename T, typename TagT, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT, TagT >::type attribute_value::extract_or_default(DefaultT const& def_value) const +{ + return boost::log::extract_or_default< T, TagT >(*this, def_value); +} + +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + +template< typename T > +inline typename result_of::extract< T >::type attribute_value::extract() const +{ + return boost::log::extract< T >(*this); +} + +template< typename T > +inline typename result_of::extract_or_throw< T >::type attribute_value::extract_or_throw() const +{ + return boost::log::extract_or_throw< T >(*this); +} + +template< typename T > +inline typename result_of::extract_or_default< T, T >::type attribute_value::extract_or_default(T const& def_value) const +{ + return boost::log::extract_or_default< T >(*this, def_value); +} + +template< typename T, typename DefaultT > +inline typename result_of::extract_or_default< T, DefaultT >::type attribute_value::extract_or_default(DefaultT const& def_value) const +{ + return boost::log::extract_or_default< T >(*this, def_value); +} + +#endif // defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +#undef BOOST_LOG_AUX_VOID_DEFAULT + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_HPP_INCLUDED_ diff --git a/boost/log/attributes/value_extraction_fwd.hpp b/boost/log/attributes/value_extraction_fwd.hpp new file mode 100644 index 0000000000..2cc5583019 --- /dev/null +++ b/boost/log/attributes/value_extraction_fwd.hpp @@ -0,0 +1,62 @@ +/* + * 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 value_extraction_fwd.hpp + * \author Andrey Semashev + * \date 01.03.2008 + * + * The header contains forward declaration of tools for extracting attribute values + * from the view. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_FWD_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/fallback_policy_fwd.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace result_of { + +/*! + * \brief A metafunction that allows to acquire the result of the value extraction + */ +template< typename T, typename DefaultT = T, typename TagT = void > +struct extract_or_default; + +/*! + * \brief A metafunction that allows to acquire the result of the value extraction + */ +template< typename T, typename TagT = void > +struct extract_or_throw; + +/*! + * \brief A metafunction that allows to acquire the result of the value extraction + */ +template< typename T, typename TagT = void > +struct extract; + +} // namespace result_of + +/*! + * \brief Generic attribute value extractor + */ +template< typename T, typename FallbackPolicyT = fallback_to_none, typename TagT = void > +class value_extractor; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_ATTRIBUTES_VALUE_EXTRACTION_FWD_HPP_INCLUDED_ diff --git a/boost/log/attributes/value_visitation.hpp b/boost/log/attributes/value_visitation.hpp new file mode 100644 index 0000000000..6a8205fcf3 --- /dev/null +++ b/boost/log/attributes/value_visitation.hpp @@ -0,0 +1,372 @@ +/* + * 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 value_visitation.hpp + * \author Andrey Semashev + * \date 01.03.2008 + * + * The header contains implementation of convenience tools to apply visitors to an attribute value + * in the view. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/exceptions.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/attributes/value_visitation_fwd.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/utility/type_dispatch/static_type_dispatcher.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief The class represents attribute value visitation result + * + * The main purpose of this class is to provide a convenient interface for checking + * whether the attribute value visitation succeeded or not. It also allows to discover + * the actual cause of failure, should the operation fail. + */ +class visitation_result +{ +public: + //! Error codes for attribute value visitation + enum error_code + { + ok, //!< The attribute value has been visited successfully + value_not_found, //!< The attribute value is not present in the view + value_has_invalid_type //!< The attribute value is present in the view, but has an unexpected type + }; + +private: + error_code m_code; + +public: + /*! + * Initializing constructor. Creates the result that is equivalent to the + * specified error code. + */ + BOOST_CONSTEXPR visitation_result(error_code code = ok) BOOST_NOEXCEPT : m_code(code) {} + + /*! + * Checks if the visitation was successful. + * + * \return \c true if the value was visited successfully, \c false otherwise. + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + /*! + * Checks if the visitation was unsuccessful. + * + * \return \c false if the value was visited successfully, \c true otherwise. + */ + bool operator! () const BOOST_NOEXCEPT { return (m_code != ok); } + + /*! + * \return The actual result code of value visitation + */ + error_code code() const BOOST_NOEXCEPT { return m_code; } +}; + +/*! + * \brief Generic attribute value visitor invoker + * + * Attribute value invoker is a functional object that attempts to find and extract the stored + * attribute value from the attribute value view or a log record. The extracted value is passed to + * a unary function object (the visitor) provided by user. + * + * The invoker can be specialized on one or several attribute value types that should be + * specified in the second template argument. + */ +template< typename T, typename FallbackPolicyT > +class value_visitor_invoker : + private FallbackPolicyT +{ + typedef value_visitor_invoker< T, FallbackPolicyT > this_type; + +public: + //! Attribute value types + typedef T value_type; + + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + + //! Function object result type + typedef visitation_result result_type; + +public: + /*! + * Default constructor + */ + BOOST_DEFAULTED_FUNCTION(value_visitor_invoker(), {}) + + /*! + * Copy constructor + */ + value_visitor_invoker(value_visitor_invoker const& that) : fallback_policy(static_cast< fallback_policy const& >(that)) + { + } + + /*! + * Initializing constructor + * + * \param arg Fallback policy argument + */ + template< typename U > + explicit value_visitor_invoker(U const& arg) : fallback_policy(arg) {} + + /*! + * Visitation operator. Attempts to acquire the stored value of one of the supported types. If acquisition succeeds, + * the value is passed to \a visitor. + * + * \param attr An attribute value to apply the visitor to. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ + template< typename VisitorT > + result_type operator() (attribute_value const& attr, VisitorT visitor) const + { + if (!!attr) + { + static_type_dispatcher< value_type > disp(visitor); + if (attr.dispatch(disp) || fallback_policy::apply_default(visitor)) + { + return visitation_result::ok; + } + else + { + fallback_policy::on_invalid_type(attr.get_type()); + return visitation_result::value_has_invalid_type; + } + } + + if (fallback_policy::apply_default(visitor)) + return visitation_result::ok; + + fallback_policy::on_missing_value(); + return visitation_result::value_not_found; + } + + /*! + * Visitation operator. Looks for an attribute value with the specified name + * and tries to acquire the stored value of one of the supported types. If acquisition succeeds, + * the value is passed to \a visitor. + * + * \param name Attribute value name. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ + template< typename VisitorT > + result_type operator() (attribute_name const& name, attribute_value_set const& attrs, VisitorT visitor) const + { + try + { + attribute_value_set::const_iterator it = attrs.find(name); + if (it != attrs.end()) + return operator() (it->second, visitor); + else + return operator() (attribute_value(), visitor); + } + catch (exception& e) + { + // Attach the attribute name to the exception + boost::log::aux::attach_attribute_name_info(e, name); + throw; + } + } + + /*! + * Visitation operator. Looks for an attribute value with the specified name + * and tries to acquire the stored value of one of the supported types. If acquisition succeeds, + * the value is passed to \a visitor. + * + * \param name Attribute value name. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ + template< typename VisitorT > + result_type operator() (attribute_name const& name, record const& rec, VisitorT visitor) const + { + return operator() (name, rec.attribute_values(), visitor); + } + + /*! + * Visitation operator. Looks for an attribute value with the specified name + * and tries to acquire the stored value of one of the supported types. If acquisition succeeds, + * the value is passed to \a visitor. + * + * \param name Attribute value name. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ + template< typename VisitorT > + result_type operator() (attribute_name const& name, record_view const& rec, VisitorT visitor) const + { + return operator() (name, rec.attribute_values(), visitor); + } + + /*! + * \returns Fallback policy + */ + fallback_policy const& get_fallback_policy() const + { + return *static_cast< fallback_policy const* >(this); + } +}; + +/*! + * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param name The name of the attribute value to visit. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename T, typename VisitorT > +inline visitation_result +visit(attribute_name const& name, attribute_value_set const& attrs, VisitorT visitor) +{ + value_visitor_invoker< T > invoker; + return invoker(name, attrs, visitor); +} + +/*! + * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param name The name of the attribute value to visit. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename T, typename VisitorT > +inline visitation_result +visit(attribute_name const& name, record const& rec, VisitorT visitor) +{ + value_visitor_invoker< T > invoker; + return invoker(name, rec, visitor); +} + +/*! + * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param name The name of the attribute value to visit. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename T, typename VisitorT > +inline visitation_result +visit(attribute_name const& name, record_view const& rec, VisitorT visitor) +{ + value_visitor_invoker< T > invoker; + return invoker(name, rec, visitor); +} + +/*! + * The function applies a visitor to an attribute value. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param value The attribute value to visit. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename T, typename VisitorT > +inline visitation_result +visit(attribute_value const& value, VisitorT visitor) +{ + value_visitor_invoker< T > invoker; + return invoker(value, visitor); +} + +/*! + * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param keyword The keyword of the attribute value to visit. + * \param attrs A set of attribute values in which to look for the specified attribute value. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename DescriptorT, template< typename > class ActorT, typename VisitorT > +inline visitation_result +visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, attribute_value_set const& attrs, VisitorT visitor) +{ + value_visitor_invoker< typename DescriptorT::value_type > invoker; + return invoker(keyword.get_name(), attrs, visitor); +} + +/*! + * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param keyword The keyword of the attribute value to visit. + * \param rec A log record. The attribute value will be sought among those associated with the record. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename DescriptorT, template< typename > class ActorT, typename VisitorT > +inline visitation_result +visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record const& rec, VisitorT visitor) +{ + value_visitor_invoker< typename DescriptorT::value_type > invoker; + return invoker(keyword.get_name(), rec, visitor); +} + +/*! + * The function applies a visitor to an attribute value from the view. The user has to explicitly specify the + * type or set of possible types of the attribute value to be visited. + * + * \param keyword The keyword of the attribute value to visit. + * \param rec A log record view. The attribute value will be sought among those associated with the record. + * \param visitor A receiving function object to pass the attribute value to. + * \return The result of visitation. + */ +template< typename DescriptorT, template< typename > class ActorT, typename VisitorT > +inline visitation_result +visit(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, record_view const& rec, VisitorT visitor) +{ + value_visitor_invoker< typename DescriptorT::value_type > invoker; + return invoker(keyword.get_name(), rec, visitor); +} + + +#if !defined(BOOST_LOG_DOXYGEN_PASS) + +template< typename T, typename VisitorT > +inline visitation_result attribute_value::visit(VisitorT visitor) const +{ + return boost::log::visit< T >(*this, visitor); +} + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_HPP_INCLUDED_ diff --git a/boost/log/attributes/value_visitation_fwd.hpp b/boost/log/attributes/value_visitation_fwd.hpp new file mode 100644 index 0000000000..5917c22a95 --- /dev/null +++ b/boost/log/attributes/value_visitation_fwd.hpp @@ -0,0 +1,45 @@ +/* + * 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 value_visitation_fwd.hpp + * \author Andrey Semashev + * \date 01.03.2008 + * + * The header contains forward declaration of convenience tools to apply visitors to an attribute value + * in the view. + */ + +#ifndef BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_FWD_HPP_INCLUDED_ +#define BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/fallback_policy_fwd.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief The class represents attribute value visitation result + */ +class visitation_result; + +/*! + * \brief Generic attribute value visitor invoker + */ +template< typename T, typename FallbackPolicyT = fallback_to_none > +class value_visitor_invoker; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_ATTRIBUTES_VALUE_VISITATION_FWD_HPP_INCLUDED_ diff --git a/boost/log/common.hpp b/boost/log/common.hpp new file mode 100644 index 0000000000..bc62893d8b --- /dev/null +++ b/boost/log/common.hpp @@ -0,0 +1,41 @@ +/* + * 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 common.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * This header includes other Boost.Log headers that are commonly used in logging applications. + * Note that the header does not include any headers required to setup the library, as usually + * they aren't needed in more than one translation unit of the application. + */ + +#ifndef BOOST_LOG_COMMON_HPP_INCLUDED_ +#define BOOST_LOG_COMMON_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/core.hpp> + +#include <boost/log/sources/global_logger_storage.hpp> +#include <boost/log/sources/record_ostream.hpp> + +#include <boost/log/sources/basic_logger.hpp> +#include <boost/log/sources/severity_logger.hpp> +#include <boost/log/sources/channel_logger.hpp> +#include <boost/log/sources/severity_channel_logger.hpp> +#include <boost/log/sources/exception_handler_feature.hpp> + +#include <boost/log/attributes/constant.hpp> +#include <boost/log/attributes/named_scope.hpp> +#include <boost/log/attributes/scoped_attribute.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_COMMON_HPP_INCLUDED_ diff --git a/boost/log/core.hpp b/boost/log/core.hpp new file mode 100644 index 0000000000..159e5b9177 --- /dev/null +++ b/boost/log/core.hpp @@ -0,0 +1,28 @@ +/* + * 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 log/core.hpp + * \author Andrey Semashev + * \date 19.04.2007 + * + * This header includes Boost.Log headers related to the logging core. + */ + +#ifndef BOOST_LOG_CORE_HPP_INCLUDED_ +#define BOOST_LOG_CORE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/core/core.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/core/record_view.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_CORE_HPP_INCLUDED_ diff --git a/boost/log/core/core.hpp b/boost/log/core/core.hpp new file mode 100644 index 0000000000..e3475299c4 --- /dev/null +++ b/boost/log/core/core.hpp @@ -0,0 +1,329 @@ +/* + * 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 core/core.hpp + * \author Andrey Semashev + * \date 19.04.2007 + * + * This header contains logging core class definition. + */ + +#ifndef BOOST_LOG_CORE_CORE_HPP_INCLUDED_ +#define BOOST_LOG_CORE_CORE_HPP_INCLUDED_ + +#include <utility> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/move/core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/attributes/attribute_set.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/expressions/filter.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace sinks { + +class sink; + +} // namespace sinks + +#endif // BOOST_LOG_DOXYGEN_PASS + +class core; + +typedef shared_ptr< core > core_ptr; + +/*! + * \brief Logging library core class + * + * The logging core is used to interconnect log sources and sinks. It also provides + * a number of basic features, like global filtering and global and thread-specific attribute storage. + * + * The logging core is a singleton. Users can acquire the core instance by calling the static method <tt>get</tt>. + */ +class core +{ +public: + //! Exception handler function type + typedef boost::log::aux::light_function< void () > exception_handler_type; + +private: + //! Implementation type + struct implementation; + friend struct implementation; + +private: + //! A pointer to the implementation + implementation* m_impl; + +private: + //! \cond + core(); + //! \endcond + +public: + /*! + * Destructor. Destroys the core, releases any sinks and attributes that were registered. + */ + ~core(); + + /*! + * \return The method returns a pointer to the logging core singleton instance. + */ + BOOST_LOG_API static core_ptr get(); + + /*! + * The method enables or disables logging. + * + * Setting this status to \c false allows you to completely wipe out any logging activity, including + * filtering and generation of attribute values. It is useful if you want to completely disable logging + * in a running application. The state of logging does not alter any other properties of the logging + * library, such as filters or sinks, so you can enable logging with the very same settings that you had + * when the logging was disabled. + * This feature may also be useful if you want to perform major changes to logging configuration and + * don't want your application to block on opening or pushing a log record. + * + * By default logging is enabled. + * + * \param enabled The actual flag of logging activity. + * \return The previous value of enabled/disabled logging flag + */ + BOOST_LOG_API bool set_logging_enabled(bool enabled = true); + /*! + * The method allows to detect if logging is enabled. See the comment for \c set_logging_enabled. + */ + BOOST_LOG_API bool get_logging_enabled() const; + + /*! + * The method sets the global logging filter. The filter is applied to every log record that is processed. + * + * \param filter The filter function object to be installed. + */ + BOOST_LOG_API void set_filter(filter const& filter); + /*! + * The method removes the global logging filter. All log records are passed to sinks without global filtering applied. + */ + BOOST_LOG_API void reset_filter(); + + /*! + * The method adds a new sink. The sink is included into logging process immediately after being added and until being removed. + * No sink can be added more than once at the same time. If the sink is already registered, the call is ignored. + * + * \param s The sink to be registered. + */ + BOOST_LOG_API void add_sink(shared_ptr< sinks::sink > const& s); + /*! + * The method removes the sink from the output. The sink will not receive any log records after removal. + * The call has no effect if the sink is not registered. + * + * \param s The sink to be unregistered. + */ + BOOST_LOG_API void remove_sink(shared_ptr< sinks::sink > const& s); + /*! + * The method removes all registered sinks from the output. The sinks will not receive any log records after removal. + */ + BOOST_LOG_API void remove_all_sinks(); + + /*! + * The method performs flush on all registered sinks. + * + * \note This method may take long time to complete as it may block until all sinks manage to process all buffered log records. + * The call will also block all logging attempts until the operation completes. + */ + BOOST_LOG_API void flush(); + + /*! + * The method adds an attribute to the global attribute set. The attribute will be implicitly added to every log record. + * + * \param name The attribute name. + * \param attr The attribute factory. + * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the + * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents + * addition. + */ + BOOST_LOG_API std::pair< attribute_set::iterator, bool > add_global_attribute(attribute_name const& name, attribute const& attr); + /*! + * The method removes an attribute from the global attribute set. + * + * \pre The attribute was added with the \c add_global_attribute call. + * \post The attribute is no longer registered as a global attribute. The iterator is invalidated after removal. + * + * \param it Iterator to the previously added attribute. + */ + BOOST_LOG_API void remove_global_attribute(attribute_set::iterator it); + + /*! + * The method returns a copy of the complete set of currently registered global attributes. + */ + BOOST_LOG_API attribute_set get_global_attributes() const; + /*! + * The method replaces the complete set of currently registered global attributes with the provided set. + * + * \note The method invalidates all iterators and references that may have been returned + * from the \c add_global_attribute method. + * + * \param attrs The set of attributes to be installed. + */ + BOOST_LOG_API void set_global_attributes(attribute_set const& attrs); + + /*! + * The method adds an attribute to the thread-specific attribute set. The attribute will be implicitly added to + * every log record made in the current thread. + * + * \note In single-threaded build the effect is the same as adding the attribute globally. This, however, does + * not imply that iterators to thread-specific and global attributes are interchangeable. + * + * \param name The attribute name. + * \param attr The attribute factory. + * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the + * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents + * addition. + */ + BOOST_LOG_API std::pair< attribute_set::iterator, bool > add_thread_attribute(attribute_name const& name, attribute const& attr); + /*! + * The method removes an attribute from the thread-specific attribute set. + * + * \pre The attribute was added with the \c add_thread_attribute call. + * \post The attribute is no longer registered as a thread-specific attribute. The iterator is invalidated after removal. + * + * \param it Iterator to the previously added attribute. + */ + BOOST_LOG_API void remove_thread_attribute(attribute_set::iterator it); + + /*! + * The method returns a copy of the complete set of currently registered thread-specific attributes. + */ + BOOST_LOG_API attribute_set get_thread_attributes() const; + /*! + * The method replaces the complete set of currently registered thread-specific attributes with the provided set. + * + * \note The method invalidates all iterators and references that may have been returned + * from the \c add_thread_attribute method. + * + * \param attrs The set of attributes to be installed. + */ + BOOST_LOG_API void set_thread_attributes(attribute_set const& attrs); + + /*! + * The method sets exception handler function. The function will be called with no arguments + * in case if an exception occurs during either \c open_record or \c push_record method + * execution. Since exception handler is called from a \c catch statement, the exception + * can be rethrown in order to determine its type. + * + * By default no handler is installed, thus any exception is propagated as usual. + * + * \sa See also: <tt>utility/exception_handler.hpp</tt> + * \param handler Exception handling function + * + * \note The exception handler can be invoked in several threads concurrently. + * Thread interruptions are not affected by exception handlers. + */ + BOOST_LOG_API void set_exception_handler(exception_handler_type const& handler); + + /*! + * The method attempts to open a new record to be written. While attempting to open a log record all filtering is applied. + * A successfully opened record can be pushed further to sinks by calling the \c push_record method or simply destroyed by + * destroying the returned object. + * + * More than one open records are allowed, such records exist independently. All attribute values are acquired during opening + * the record and do not interact between records. + * + * The returned records can be copied, however, they must not be passed between different threads. + * + * \param source_attributes The set of source-specific attributes to be attached to the record to be opened. + * \return A valid log record if the record is opened, an invalid record object if not (e.g. because it didn't pass filtering). + * + * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may + * throw if one of the sinks throws, or some system resource limitation is reached. + */ + BOOST_LOG_API record open_record(attribute_set const& source_attributes); + /*! + * The method attempts to open a new record to be written. While attempting to open a log record all filtering is applied. + * A successfully opened record can be pushed further to sinks by calling the \c push_record method or simply destroyed by + * destroying the returned object. + * + * More than one open records are allowed, such records exist independently. All attribute values are acquired during opening + * the record and do not interact between records. + * + * The returned records can be copied, however, they must not be passed between different threads. + * + * \param source_attributes The set of source-specific attribute values to be attached to the record to be opened. + * \return A valid log record if the record is opened, an invalid record object if not (e.g. because it didn't pass filtering). + * + * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may + * throw if one of the sinks throws, or some system resource limitation is reached. + */ + BOOST_LOG_API record open_record(attribute_value_set const& source_attributes); + /*! + * The method attempts to open a new record to be written. While attempting to open a log record all filtering is applied. + * A successfully opened record can be pushed further to sinks by calling the \c push_record method or simply destroyed by + * destroying the returned object. + * + * More than one open records are allowed, such records exist independently. All attribute values are acquired during opening + * the record and do not interact between records. + * + * The returned records can be copied, however, they must not be passed between different threads. + * + * \param source_attributes The set of source-specific attribute values to be attached to the record to be opened. The contents + * of this container are unspecified after this call. + * \return A valid log record if the record is opened, an invalid record object if not (e.g. because it didn't pass filtering). + * + * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may + * throw if one of the sinks throws, or some system resource limitation is reached. + */ + BOOST_FORCEINLINE record open_record(BOOST_RV_REF(attribute_value_set) source_attributes) + { + return open_record_move(static_cast< attribute_value_set& >(source_attributes)); + } + + /*! + * The method pushes the record to sinks. The record is moved from in the process. + * + * \pre <tt>!!rec == true</tt> + * \post <tt>!rec == true</tt> + * \param rec A previously successfully opened log record. + * + * \b Throws: If an exception handler is installed, only throws if the handler throws. Otherwise may + * throw if one of the sinks throws. + */ + BOOST_FORCEINLINE void push_record(BOOST_RV_REF(record) rec) + { + push_record_move(static_cast< record& >(rec)); + } + + BOOST_DELETED_FUNCTION(core(core const&)) + BOOST_DELETED_FUNCTION(core& operator= (core const&)) + +#ifndef BOOST_LOG_DOXYGEN_PASS +private: + //! Opens log record. This function is mostly needed to maintain ABI stable between C++03 and C++11. + BOOST_LOG_API record open_record_move(attribute_value_set& source_attributes); + //! The method pushes the record to sinks. + BOOST_LOG_API void push_record_move(record& rec); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_CORE_CORE_HPP_INCLUDED_ diff --git a/boost/log/core/record.hpp b/boost/log/core/record.hpp new file mode 100644 index 0000000000..758e44aadb --- /dev/null +++ b/boost/log/core/record.hpp @@ -0,0 +1,207 @@ +/* + * 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.hpp + * \author Andrey Semashev + * \date 09.03.2009 + * + * This header contains a logging record class definition. + */ + +#ifndef BOOST_LOG_CORE_RECORD_HPP_INCLUDED_ +#define BOOST_LOG_CORE_RECORD_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +class core; + +/*! + * \brief Logging record class + * + * The logging record encapsulates all information related to a single logging statement, + * in particular, attribute values view and the log message string. The record can be updated before pushing + * for further processing to the logging core. + */ +class record +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(record) + + friend class core; + +#ifndef BOOST_LOG_DOXYGEN_PASS +private: + //! Private data + typedef record_view::public_data public_data; + +private: + //! A pointer to the log record implementation + public_data* m_impl; + +#endif // BOOST_LOG_DOXYGEN_PASS + +public: + /*! + * Default constructor. Creates an empty record that is equivalent to the invalid record handle. + * + * \post <tt>!*this == true</tt> + */ + record() : m_impl(NULL) {} + + /*! + * Move constructor. Source record contents unspecified after the operation. + */ + record(BOOST_RV_REF(record) that) BOOST_NOEXCEPT : m_impl(that.m_impl) + { + that.m_impl = NULL; + } + + /*! + * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record. + */ + ~record() BOOST_NOEXCEPT + { + reset(); + } + + /*! + * Move assignment. Source record contents unspecified after the operation. + */ + record& operator= (BOOST_RV_REF(record) that) BOOST_NOEXCEPT + { + swap(static_cast< record& >(that)); + return *this; + } + + /*! + * \return A reference to the set of attribute values attached to this record + * + * \pre <tt>!!*this</tt> + */ + attribute_value_set& attribute_values() BOOST_NOEXCEPT + { + return m_impl->m_attribute_values; + } + + /*! + * \return A reference to the set of attribute values attached to this record + * + * \pre <tt>!!*this</tt> + */ + attribute_value_set const& attribute_values() const BOOST_NOEXCEPT + { + return m_impl->m_attribute_values; + } + + /*! + * Conversion to an unspecified boolean type + * + * \return \c true, if the <tt>*this</tt> identifies a log record, \c false, if the <tt>*this</tt> is not valid + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * Inverted conversion to an unspecified boolean type + * + * \return \c false, if the <tt>*this</tt> identifies a log record, \c true, if the <tt>*this</tt> is not valid + */ + bool operator! () const BOOST_NOEXCEPT + { + return !m_impl; + } + + /*! + * Swaps two handles + * + * \param that Another record to swap with + * <b>Throws:</b> Nothing + */ + void swap(record& that) BOOST_NOEXCEPT + { + public_data* p = m_impl; + m_impl = that.m_impl; + that.m_impl = p; + } + + /*! + * Resets the log record handle. If there are no other handles left, the log record is closed + * and all resources referenced by the record are released. + * + * \post <tt>!*this == true</tt> + */ + void reset() BOOST_NOEXCEPT + { + if (m_impl) + { + public_data::destroy(m_impl); + m_impl = NULL; + } + } + + /*! + * Attribute value lookup. + * + * \param name Attribute name. + * \return An \c attribute_value, non-empty if it is found, empty otherwise. + */ + attribute_value_set::mapped_type operator[] (attribute_value_set::key_type name) const + { + return m_impl->m_attribute_values[name]; + } + + /*! + * Attribute value lookup. + * + * \param keyword Attribute keyword. + * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise. + */ + template< typename DescriptorT, template< typename > class ActorT > + typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type + operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const + { + return m_impl->m_attribute_values[keyword]; + } + + /*! + * The function ensures that the log record does not depend on any thread-specific data. Then the record contents + * are used to construct a \c record_view which is returned from the function. The record is no longer valid after the call. + * + * \pre <tt>!!*this</tt> + * \post <tt>!*this</tt> + * \returns The record view that contains all attribute values from the original record. + */ + BOOST_LOG_API record_view lock(); +}; + +/*! + * A free-standing swap function overload for \c record + */ +inline void swap(record& left, record& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_CORE_RECORD_HPP_INCLUDED_ diff --git a/boost/log/core/record_view.hpp b/boost/log/core/record_view.hpp new file mode 100644 index 0000000000..58f2a1b778 --- /dev/null +++ b/boost/log/core/record_view.hpp @@ -0,0 +1,260 @@ +/* + * 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_view.hpp + * \author Andrey Semashev + * \date 09.03.2009 + * + * This header contains a logging record view class definition. + */ + +#ifndef BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_ +#define BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_ + +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/move/core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#ifndef BOOST_LOG_NO_THREADS +#include <boost/detail/atomic_count.hpp> +#endif // BOOST_LOG_NO_THREADS +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +#ifndef BOOST_LOG_DOXYGEN_PASS +class core; +class record; +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Logging record view class + * + * The logging record encapsulates all information related to a single logging statement, + * in particular, attribute values view and the log message string. The view is immutable, + * it is implemented as a wrapper around a reference-counted implementation. + */ +class record_view +{ + BOOST_COPYABLE_AND_MOVABLE(record_view) + + friend class core; + friend class record; + +#ifndef BOOST_LOG_DOXYGEN_PASS +private: + //! Private data + struct private_data; + friend struct private_data; + + //! Publicly available record data + struct public_data + { + //! Reference counter +#ifndef BOOST_LOG_NO_THREADS + mutable boost::detail::atomic_count m_ref_counter; +#else + mutable unsigned int m_ref_counter; +#endif // BOOST_LOG_NO_THREADS + + //! Attribute values view + attribute_value_set m_attribute_values; + + //! Constructor from the attribute sets + explicit public_data(BOOST_RV_REF(attribute_value_set) values) : + m_ref_counter(1), + m_attribute_values(values) + { + } + + //! Destructor + BOOST_LOG_API static void destroy(const public_data* p) BOOST_NOEXCEPT; + + protected: + ~public_data() {} + + BOOST_DELETED_FUNCTION(public_data(public_data const&)) + BOOST_DELETED_FUNCTION(public_data& operator= (public_data const&)) + + friend void intrusive_ptr_add_ref(const public_data* p) { ++p->m_ref_counter; } + friend void intrusive_ptr_release(const public_data* p) { if (--p->m_ref_counter == 0) public_data::destroy(p); } + }; + +private: + //! A pointer to the log record implementation + intrusive_ptr< public_data > m_impl; + +private: + // A private constructor, accessible from record + explicit record_view(public_data* impl) : m_impl(impl, false) {} + +#endif // BOOST_LOG_DOXYGEN_PASS + +public: + /*! + * Default constructor. Creates an empty record view that is equivalent to the invalid record handle. + * + * \post <tt>!*this == true</tt> + */ + BOOST_DEFAULTED_FUNCTION(record_view(), {}) + + /*! + * Copy constructor + */ + record_view(record_view const& that) BOOST_NOEXCEPT : m_impl(that.m_impl) {} + + /*! + * Move constructor. Source record contents unspecified after the operation. + */ + record_view(BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT + { + m_impl.swap(that.m_impl); + } + + /*! + * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record. + */ + ~record_view() BOOST_NOEXCEPT {} + + /*! + * Copy assignment + */ + record_view& operator= (BOOST_COPY_ASSIGN_REF(record_view) that) BOOST_NOEXCEPT + { + m_impl = that.m_impl; + return *this; + } + + /*! + * Move assignment. Source record contents unspecified after the operation. + */ + record_view& operator= (BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT + { + m_impl.swap(that.m_impl); + return *this; + } + + /*! + * \return A reference to the set of attribute values attached to this record + * + * \pre <tt>!!*this</tt> + */ + attribute_value_set const& attribute_values() const BOOST_NOEXCEPT + { + return m_impl->m_attribute_values; + } + + /*! + * Equality comparison + * + * \param that Comparand + * \return \c true if both <tt>*this</tt> and \a that identify the same log record or both do not + * identify any record, \c false otherwise. + */ + bool operator== (record_view const& that) const BOOST_NOEXCEPT + { + return m_impl == that.m_impl; + } + + /*! + * Inequality comparison + * + * \param that Comparand + * \return <tt>!(*this == that)</tt> + */ + bool operator!= (record_view const& that) const BOOST_NOEXCEPT + { + return !operator== (that); + } + + /*! + * Conversion to an unspecified boolean type + * + * \return \c true, if the <tt>*this</tt> identifies a log record, \c false, if the <tt>*this</tt> is not valid + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * Inverted conversion to an unspecified boolean type + * + * \return \c false, if the <tt>*this</tt> identifies a log record, \c true, if the <tt>*this</tt> is not valid + */ + bool operator! () const BOOST_NOEXCEPT + { + return !m_impl; + } + + /*! + * Swaps two handles + * + * \param that Another record to swap with + * <b>Throws:</b> Nothing + */ + void swap(record_view& that) BOOST_NOEXCEPT + { + m_impl.swap(that.m_impl); + } + + /*! + * Resets the log record handle. If there are no other handles left, the log record is closed + * and all resources referenced by the record are released. + * + * \post <tt>!*this == true</tt> + */ + void reset() BOOST_NOEXCEPT + { + m_impl.reset(); + } + + /*! + * Attribute value lookup. + * + * \param name Attribute name. + * \return An \c attribute_value, non-empty if it is found, empty otherwise. + */ + attribute_value_set::mapped_type operator[] (attribute_value_set::key_type name) const + { + return m_impl->m_attribute_values[name]; + } + + /*! + * Attribute value lookup. + * + * \param keyword Attribute keyword. + * \return A \c value_ref with extracted attribute value if it is found, empty \c value_ref otherwise. + */ + template< typename DescriptorT, template< typename > class ActorT > + typename result_of::extract< typename expressions::attribute_keyword< DescriptorT, ActorT >::value_type, DescriptorT >::type + operator[] (expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) const + { + return m_impl->m_attribute_values[keyword]; + } +}; + +/*! + * A free-standing swap function overload for \c record_view + */ +inline void swap(record_view& left, record_view& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_CORE_RECORD_VIEW_HPP_INCLUDED_ diff --git a/boost/log/detail/asio_fwd.hpp b/boost/log/detail/asio_fwd.hpp new file mode 100644 index 0000000000..e284c24eed --- /dev/null +++ b/boost/log/detail/asio_fwd.hpp @@ -0,0 +1,43 @@ +/* + * 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 asio_fwd.hpp + * \author Andrey Semashev + * \date 20.04.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + * + * The header provides forward declarations of Boost.ASIO that are required for the user's + * code to compile with Boost.Log. The forward declarations allow to avoid including the major + * part of Boost.ASIO and system headers into user's code. + */ + +#ifndef BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +namespace asio { + +namespace ip { + +class address; + +} // namespace ip + +} // namespace asio + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_ diff --git a/boost/log/detail/attachable_sstream_buf.hpp b/boost/log/detail/attachable_sstream_buf.hpp new file mode 100644 index 0000000000..9b0a05316d --- /dev/null +++ b/boost/log/detail/attachable_sstream_buf.hpp @@ -0,0 +1,172 @@ +/* + * 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 attachable_sstream_buf.hpp + * \author Andrey Semashev + * \date 29.07.2007 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_ +#define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_ + +#include <memory> +#include <string> +#include <streambuf> +#include <boost/assert.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A streambuf that puts the formatted data to an external string +template< + typename CharT, + typename TraitsT = std::char_traits< CharT >, + typename AllocatorT = std::allocator< CharT > +> +class basic_ostringstreambuf : + public std::basic_streambuf< CharT, TraitsT > +{ + //! Self type + typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type; + //! Base type + typedef std::basic_streambuf< CharT, TraitsT > base_type; + + //! Buffer size + enum { buffer_size = 16 }; + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! Traits type + typedef typename base_type::traits_type traits_type; + //! String type + typedef std::basic_string< char_type, traits_type, AllocatorT > string_type; + //! Int type + typedef typename base_type::int_type int_type; + +private: + //! A reference to the string that will be filled + string_type* m_Storage; + //! A buffer used to temporarily store output + char_type m_Buffer[buffer_size]; + +public: + //! Constructor + explicit basic_ostringstreambuf() : m_Storage(0) + { + base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer))); + } + //! Constructor + explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage)) + { + base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer))); + } + + //! Clears the buffer to the initial state + void clear() + { + char_type* pBase = this->pbase(); + char_type* pPtr = this->pptr(); + if (pBase != pPtr) + this->pbump(static_cast< int >(pBase - pPtr)); + } + + //! Detaches the buffer from the string + void detach() + { + if (m_Storage) + { + this_type::sync(); + m_Storage = 0; + } + } + + //! Attaches the buffer to another string + void attach(string_type& storage) + { + detach(); + m_Storage = boost::addressof(storage); + } + + //! Returns a pointer to the attached string + string_type* storage() const { return m_Storage; } + +protected: + //! Puts all buffered data to the string + int sync() + { + BOOST_ASSERT(m_Storage != 0); + char_type* pBase = this->pbase(); + char_type* pPtr = this->pptr(); + if (pBase != pPtr) + { + m_Storage->append(pBase, pPtr); + this->pbump(static_cast< int >(pBase - pPtr)); + } + return 0; + } + //! Puts an unbuffered character to the string + int_type overflow(int_type c) + { + BOOST_ASSERT(m_Storage != 0); + basic_ostringstreambuf::sync(); + if (!traits_type::eq_int_type(c, traits_type::eof())) + { + m_Storage->push_back(traits_type::to_char_type(c)); + return c; + } + else + return traits_type::not_eof(c); + } + //! Puts a character sequence to the string + std::streamsize xsputn(const char_type* s, std::streamsize n) + { + BOOST_ASSERT(m_Storage != 0); + basic_ostringstreambuf::sync(); + typedef typename string_type::size_type string_size_type; + const string_size_type max_storage_left = + m_Storage->max_size() - m_Storage->size(); + if (static_cast< string_size_type >(n) < max_storage_left) + { + m_Storage->append(s, static_cast< string_size_type >(n)); + return n; + } + else + { + m_Storage->append(s, max_storage_left); + return static_cast< std::streamsize >(max_storage_left); + } + } + + //! Copy constructor (closed) + BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that)) + //! Assignment (closed) + BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_ diff --git a/boost/log/detail/attr_output_impl.hpp b/boost/log/detail/attr_output_impl.hpp new file mode 100644 index 0000000000..8f00736c5f --- /dev/null +++ b/boost/log/detail/attr_output_impl.hpp @@ -0,0 +1,111 @@ +/* + * 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 attr_output_impl.hpp + * \author Andrey Semashev + * \date 12.08.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_ + +#include <boost/mpl/is_sequence.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/expressions/attr.hpp> +#include <boost/log/utility/functional/bind_to_log.hpp> +#include <boost/log/detail/attr_output_terminal.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename LeftT, typename T, typename FallbackPolicyT, typename TagT > +struct make_output_expression +{ + //! Resulting expression + typedef attribute_output_terminal< LeftT, T, FallbackPolicyT, to_log_fun< TagT > > type; + + //! Creates the output expression + template< typename RightT > + static BOOST_FORCEINLINE type make(LeftT const& left, RightT const& right) + { + return type(left, right.get_name(), to_log_fun< TagT >(), right.get_fallback_policy()); + } +}; + +template< typename LeftT, typename RightT, typename ValueT = typename RightT::value_type, bool IsSequenceV = mpl::is_sequence< ValueT >::value > +struct make_output_actor; + +template< template< typename > class ActorT, typename LeftExprT, typename RightT, typename ValueT > +struct make_output_actor< ActorT< LeftExprT >, RightT, ValueT, false > +{ + typedef make_output_expression< + ActorT< LeftExprT >, + ValueT, + typename RightT::fallback_policy, + typename RightT::tag_type + > make_expression; + + typedef ActorT< typename make_expression::type > type; + + static BOOST_FORCEINLINE type make(ActorT< LeftExprT > const& left, RightT const& right) + { + type res = {{ make_expression::make(left, right) }}; + return res; + } +}; + +template< template< typename > class ActorT, typename LeftExprT, typename RightT, typename ValueT > +struct make_output_actor< ActorT< LeftExprT >, RightT, ValueT, true > +{ + typedef attribute_output_terminal< ActorT< LeftExprT >, ValueT, typename RightT::fallback_policy, to_log_fun< typename RightT::tag_type > > expression_type; + + typedef ActorT< expression_type > type; + + static BOOST_FORCEINLINE type make(ActorT< LeftExprT > const& left, RightT const& right) + { + type res = {{ expression_type(left, right.get_name(), to_log_fun< typename RightT::tag_type >(), right.get_fallback_policy()) }}; + return res; + } +}; + +} // namespace aux + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename T, typename FallbackPolicyT, typename TagT >\ + BOOST_FORCEINLINE typename aux::make_output_actor< phoenix::actor< LeftExprT >, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > >::type\ + operator<< (phoenix::actor< LeftExprT > left_ref left, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > right_ref right)\ + {\ + return aux::make_output_actor< phoenix::actor< LeftExprT >, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > >::make(left, right);\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_ diff --git a/boost/log/detail/attr_output_terminal.hpp b/boost/log/detail/attr_output_terminal.hpp new file mode 100644 index 0000000000..574993aace --- /dev/null +++ b/boost/log/detail/attr_output_terminal.hpp @@ -0,0 +1,162 @@ +/* + * 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 attribute_output_terminal.hpp + * \author Andrey Semashev + * \date 06.11.2012 + * + * The header contains implementation of a generic output manipulator in template expressions. + */ + +#ifndef BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/meta_grammar.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +//! Attribute stream output expression +template< typename LeftT, typename T, typename FallbackPolicyT, typename ImplT > +class attribute_output_terminal +{ +private: + //! Self type + typedef attribute_output_terminal< LeftT, T, FallbackPolicyT, ImplT > this_type; + //! Attribute value visitor invoker + typedef value_visitor_invoker< T, FallbackPolicyT > visitor_invoker_type; + //! Manipulator implementation + typedef ImplT impl_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Result type definition + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; + typedef typename phoenix::evaluator::impl< + typename LeftT::proto_base_expr&, + context_type, + phoenix::unused + >::result_type type; + }; + +private: + //! Left argument actor + LeftT m_left; + //! Attribute name + const attribute_name m_name; + //! Attribute value visitor invoker + visitor_invoker_type m_visitor_invoker; + //! Manipulator implementation + impl_type m_impl; + +public: + //! Initializing constructor + attribute_output_terminal(LeftT const& left, attribute_name const& name) : m_left(left), m_name(name) + { + } + + //! Initializing constructor + attribute_output_terminal(LeftT const& left, attribute_name const& name, impl_type const& impl) : m_left(left), m_name(name), m_impl(impl) + { + } + + //! Initializing constructor + template< typename U > + attribute_output_terminal(LeftT const& left, attribute_name const& name, impl_type const& impl, U const& arg) : + m_left(left), m_name(name), m_visitor_invoker(arg), m_impl(impl) + { + } + + //! Copy constructor + attribute_output_terminal(attribute_output_terminal const& that) : + m_left(that.m_left), m_name(that.m_name), m_visitor_invoker(that.m_visitor_invoker), m_impl(that.m_impl) + { + } + + //! Invokation operator + template< typename ContextT > + typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) + { + typedef typename result< this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< impl_type&, result_type >(m_impl, strm)); + return strm; + } + + //! Invokation operator + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const + { + typedef typename result< const this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< impl_type const&, result_type >(m_impl, strm)); + return strm; + } + + BOOST_DELETED_FUNCTION(attribute_output_terminal()) +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename LeftT, typename T, typename FallbackPolicyT, typename ImplT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::attribute_output_terminal< LeftT, T, FallbackPolicyT, ImplT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_ diff --git a/boost/log/detail/attribute_get_value_impl.hpp b/boost/log/detail/attribute_get_value_impl.hpp new file mode 100644 index 0000000000..2058d65242 --- /dev/null +++ b/boost/log/detail/attribute_get_value_impl.hpp @@ -0,0 +1,43 @@ +/* + * 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 attribute_get_value_impl.hpp + * \author Andrey Semashev + * \date 04.08.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +inline attribute_value attribute::get_value() const +{ + return m_pImpl->get_value(); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_ diff --git a/boost/log/detail/attribute_predicate.hpp b/boost/log/detail/attribute_predicate.hpp new file mode 100644 index 0000000000..a0978632a2 --- /dev/null +++ b/boost/log/detail/attribute_predicate.hpp @@ -0,0 +1,116 @@ +/* + * 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 attribute_predicate.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of a generic predicate in template expressions. + */ + +#ifndef BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/utility/functional/save_result.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +/*! + * The predicate checks if the attribute value satisfies a predicate. + */ +template< typename T, typename ArgT, typename PredicateT, typename FallbackPolicyT = fallback_to_none > +class attribute_predicate +{ +public: + //! Function result_type + typedef bool result_type; + //! Expected attribute value type + typedef T value_type; + //! Predicate type + typedef PredicateT predicate_type; + //! Argument type for the predicate + typedef ArgT argument_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + +private: + //! Argument for the predicate + const argument_type m_arg; + //! Attribute value name + const attribute_name m_name; + //! Visitor invoker + value_visitor_invoker< value_type, fallback_policy > m_visitor_invoker; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param pred_arg The predicate argument + */ + attribute_predicate(attribute_name const& name, argument_type const& pred_arg) : m_arg(pred_arg), m_name(name) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param pred_arg The predicate argument + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_predicate(attribute_name const& name, argument_type const& pred_arg, U const& arg) : m_arg(pred_arg), m_name(name), m_visitor_invoker(arg) + { + } + + /*! + * Checking operator + * + * \param arg A set of attribute values or a log record + * \return \c true if the log record contains the sought attribute value, \c false otherwise + */ + template< typename ArgumentT > + result_type operator() (ArgumentT const& arg) const + { + typedef binder2nd< predicate_type, argument_type const& > visitor_type; + + bool res = false; + m_visitor_invoker(m_name, arg, boost::log::save_result(visitor_type(predicate_type(), m_arg), res)); + return res; + } +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_ diff --git a/boost/log/detail/cleanup_scope_guard.hpp b/boost/log/detail/cleanup_scope_guard.hpp new file mode 100644 index 0000000000..dd2c0e170a --- /dev/null +++ b/boost/log/detail/cleanup_scope_guard.hpp @@ -0,0 +1,55 @@ +/* + * 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 cleanup_scope_guard.hpp + * \author Andrey Semashev + * \date 11.03.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Cleanup scope guard +template< typename T > +struct cleanup_guard +{ + explicit cleanup_guard(T& obj) : m_Obj(obj) {} + ~cleanup_guard() { m_Obj.clear(); } + + // Copying prohibited + BOOST_DELETED_FUNCTION(cleanup_guard(cleanup_guard const&)) + BOOST_DELETED_FUNCTION(cleanup_guard& operator= (cleanup_guard const&)) + +private: + T& m_Obj; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_ diff --git a/boost/log/detail/code_conversion.hpp b/boost/log/detail/code_conversion.hpp new file mode 100644 index 0000000000..d49988bc21 --- /dev/null +++ b/boost/log/detail/code_conversion.hpp @@ -0,0 +1,119 @@ +/* + * 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 code_conversion.hpp + * \author Andrey Semashev + * \date 08.11.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ + +#include <locale> +#include <string> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale()); +#if !defined(BOOST_NO_CXX11_CHAR16_T) +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale()); +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale()); +#endif + +//! The function converts one string to the character type of another +template< typename CharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetTraitsT, typename TargetAllocatorT > +inline void code_convert(std::basic_string< CharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) +{ + str2.append(str1.c_str(), str1.size()); +} +//! The function converts one string to the character type of another +template< typename CharT, typename TargetTraitsT, typename TargetAllocatorT > +inline void code_convert(const CharT* str1, std::size_t len, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) +{ + str2.append(str1, len); +} + +//! The function converts one string to the character type of another +template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT > +inline void code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale()) +{ + aux::code_convert(str1.c_str(), str1.size(), str2, loc); +} + +//! The function converts the passed string to the narrow-character encoding +inline std::string const& to_narrow(std::string const& str) +{ + return str; +} + +//! The function converts the passed string to the narrow-character encoding +inline std::string const& to_narrow(std::string const& str, std::locale const&) +{ + return str; +} + +//! The function converts the passed string to the narrow-character encoding +inline std::string to_narrow(std::wstring const& str, std::locale const& loc = std::locale()) +{ + std::string res; + aux::code_convert(str, res, loc); + return res; +} + +//! The function converts the passed string to the wide-character encoding +inline std::wstring const& to_wide(std::wstring const& str) +{ + return str; +} + +//! The function converts the passed string to the wide-character encoding +inline std::wstring const& to_wide(std::wstring const& str, std::locale const&) +{ + return str; +} + +//! The function converts the passed string to the wide-character encoding +inline std::wstring to_wide(std::string const& str, std::locale const& loc = std::locale()) +{ + std::wstring res; + aux::code_convert(str, res, loc); + return res; +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp new file mode 100644 index 0000000000..4d1e66b73c --- /dev/null +++ b/boost/log/detail/config.hpp @@ -0,0 +1,351 @@ +/* + * 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 config.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_ + +// This check must be before any system headers are included, or __MSVCRT_VERSION__ may get defined to 0x0600 +#if defined(__MINGW32__) && !defined(__MSVCRT_VERSION__) +// Target MinGW headers to at least MSVC 7.0 runtime by default. This will enable some useful functions. +#define __MSVCRT_VERSION__ 0x0700 +#endif + +#include <limits.h> // To bring in libc macros +#include <boost/config.hpp> + +#if defined(BOOST_NO_RTTI) +# error Boost.Log: RTTI is required by the library +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1600 +# define BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH +#endif + +#if defined(BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH) +#include <boost/preprocessor/stringize.hpp> +#endif + +#if !defined(BOOST_WINDOWS) +# ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT +# define BOOST_LOG_WITHOUT_DEBUG_OUTPUT +# endif +# ifndef BOOST_LOG_WITHOUT_EVENT_LOG +# define BOOST_LOG_WITHOUT_EVENT_LOG +# endif +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_MSVC) + // For some reason MSVC 9.0 fails to link the library if static integral constants are defined in cpp +# define BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE +# if _MSC_VER <= 1310 + // MSVC 7.1 sometimes fails to match out-of-class template function definitions with + // their declarations if the return type or arguments of the functions involve typename keyword + // and depend on the template parameters. +# define BOOST_LOG_BROKEN_TEMPLATE_DEFINITION_MATCHING +# endif +# if _MSC_VER <= 1400 + // Older MSVC versions reject friend declarations for class template specializations +# define BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS +# endif +# if _MSC_VER <= 1600 + // MSVC up to 10.0 attempts to invoke copy constructor when initializing a const reference from rvalue returned from a function. + // This fails when the returned value cannot be copied (only moved): + // + // class base {}; + // class derived : public base { BOOST_MOVABLE_BUT_NOT_COPYABLE(derived) }; + // derived foo(); + // base const& var = foo(); // attempts to call copy constructor of derived +# define BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT +# endif +# if !defined(_STLPORT_VERSION) + // MSVC 9.0 mandates packaging of STL classes, which apparently affects alignment and + // makes alignment_of< T >::value no longer be a power of 2 for types that derive from STL classes. + // This breaks type_with_alignment and everything that relies on it. + // This doesn't happen with non-native STLs, such as STLPort. Strangely, this doesn't show with + // STL classes themselves or most of the user-defined derived classes. + // Not sure if that happens with other MSVC versions. + // See: http://svn.boost.org/trac/boost/ticket/1946 +# define BOOST_LOG_BROKEN_STL_ALIGNMENT +# endif +#endif + +#if defined(BOOST_INTEL) || defined(__SUNPRO_CC) + // Intel compiler and Sun Studio 12.3 have problems with friend declarations for nested class templates +# define BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1600 + // MSVC cannot interpret constant expressions in certain contexts, such as non-type template parameters +# define BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS +#endif + +#if defined(__CYGWIN__) + // Boost.ASIO is broken on Cygwin +# define BOOST_LOG_NO_ASIO +#endif + +#if !defined(BOOST_LOG_USE_NATIVE_SYSLOG) && defined(BOOST_LOG_NO_ASIO) +# ifndef BOOST_LOG_WITHOUT_SYSLOG +# define BOOST_LOG_WITHOUT_SYSLOG +# endif +#endif + +#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) + // GCC 4.1 and 4.2 have buggy anonymous namespaces support, which interferes with symbol linkage +# define BOOST_LOG_ANONYMOUS_NAMESPACE namespace anonymous {} using namespace anonymous; namespace anonymous +#else +# define BOOST_LOG_ANONYMOUS_NAMESPACE namespace +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 6)) +// GCC up to 4.6 (inclusively) did not support expanding template argument packs into non-variadic template arguments +#define BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION +#endif + +#if defined(_MSC_VER) +# define BOOST_LOG_NO_VTABLE __declspec(novtable) +#elif defined(__GNUC__) +# define BOOST_LOG_NO_VTABLE +#else +# define BOOST_LOG_NO_VTABLE +#endif + +// An MS-like compilers' extension that allows to optimize away the needless code +#if defined(_MSC_VER) +# define BOOST_LOG_ASSUME(expr) __assume(expr) +#else +# define BOOST_LOG_ASSUME(expr) +#endif + +// The statement marking unreachable branches of code to avoid warnings +#if defined(BOOST_CLANG) +# if __has_builtin(__builtin_unreachable) +# define BOOST_LOG_UNREACHABLE() __builtin_unreachable() +# endif +#elif defined(__GNUC__) +# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +# define BOOST_LOG_UNREACHABLE() __builtin_unreachable() +# endif +#elif defined(_MSC_VER) +# define BOOST_LOG_UNREACHABLE() __assume(0) +#endif +#if !defined(BOOST_LOG_UNREACHABLE) +# define BOOST_LOG_UNREACHABLE() +# define BOOST_LOG_UNREACHABLE_RETURN(r) return r +#else +# define BOOST_LOG_UNREACHABLE_RETURN(r) BOOST_LOG_UNREACHABLE() +#endif + +// Some compilers support a special attribute that shows that a function won't return +#if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) + // GCC and Sun Studio 12 support attribute syntax +# define BOOST_LOG_NORETURN __attribute__((noreturn)) +#elif defined (_MSC_VER) + // Microsoft-compatible compilers go here +# define BOOST_LOG_NORETURN __declspec(noreturn) +#else + // The rest compilers might emit bogus warnings about missing return statements + // in functions with non-void return types when throw_exception is used. +# define BOOST_LOG_NORETURN +#endif + +#if !defined(BOOST_LOG_BUILDING_THE_LIB) + +// Detect if we're dealing with dll +# if defined(BOOST_LOG_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# define BOOST_LOG_DLL +# endif + +# if defined(BOOST_LOG_DLL) +# if defined(BOOST_SYMBOL_IMPORT) +# define BOOST_LOG_API BOOST_SYMBOL_IMPORT +# elif defined(BOOST_HAS_DECLSPEC) +# define BOOST_LOG_API __declspec(dllimport) +# endif +# endif +# ifndef BOOST_LOG_API +# define BOOST_LOG_API +# endif +// +// Automatically link to the correct build variant where possible. +// +# if !defined(BOOST_ALL_NO_LIB) +# if !defined(BOOST_LOG_NO_LIB) +# define BOOST_LIB_NAME boost_log +# if defined(BOOST_LOG_DLL) +# define BOOST_DYN_LINK +# endif +# include <boost/config/auto_link.hpp> +# endif + // In static-library builds compilers ignore auto-link comments from Boost.Log binary to + // other Boost libraries. We explicitly add comments here for other libraries. + // In dynamic-library builds this is not needed. +# if !defined(BOOST_LOG_DLL) +# include <boost/system/config.hpp> +# include <boost/filesystem/config.hpp> +# if !defined(BOOST_DATE_TIME_NO_LIB) && !defined(BOOST_DATE_TIME_SOURCE) +# define BOOST_LIB_NAME boost_date_time +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK) +# define BOOST_DYN_LINK +# endif +# include <boost/config/auto_link.hpp> +# endif + // Boost.Thread's config is included below, if needed +# endif +# endif // auto-linking disabled + +#else // !defined(BOOST_LOG_BUILDING_THE_LIB) + +# if defined(BOOST_LOG_DLL) +# if defined(BOOST_SYMBOL_EXPORT) +# define BOOST_LOG_API BOOST_SYMBOL_EXPORT +# elif defined(BOOST_HAS_DECLSPEC) +# define BOOST_LOG_API __declspec(dllexport) +# endif +# endif +# ifndef BOOST_LOG_API +# define BOOST_LOG_API BOOST_SYMBOL_VISIBLE +# endif + +#endif // !defined(BOOST_LOG_BUILDING_THE_LIB) + +// By default we provide support for both char and wchar_t +#if !defined(BOOST_LOG_WITHOUT_CHAR) +# define BOOST_LOG_USE_CHAR +#endif +#if !defined(BOOST_LOG_WITHOUT_WCHAR_T) +# define BOOST_LOG_USE_WCHAR_T +#endif + +#if !defined(BOOST_LOG_DOXYGEN_PASS) + // Check if multithreading is supported +# if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_HAS_THREADS) +# define BOOST_LOG_NO_THREADS +# endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +#if !defined(BOOST_LOG_NO_THREADS) + // We need this header to (i) enable auto-linking with Boost.Thread and + // (ii) to bring in configuration macros of Boost.Thread. +# include <boost/thread/detail/config.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) + +#if !defined(BOOST_LOG_NO_THREADS) +# define BOOST_LOG_EXPR_IF_MT(expr) expr +#else +# undef BOOST_LOG_USE_COMPILER_TLS +# define BOOST_LOG_EXPR_IF_MT(expr) +#endif // !defined(BOOST_LOG_NO_THREADS) + +#if defined(BOOST_LOG_USE_COMPILER_TLS) +# if defined(__GNUC__) || defined(__SUNPRO_CC) +# define BOOST_LOG_TLS __thread +# elif defined(BOOST_MSVC) +# define BOOST_LOG_TLS __declspec(thread) +# else +# undef BOOST_LOG_USE_COMPILER_TLS +# endif +#endif // defined(BOOST_LOG_USE_COMPILER_TLS) + +#ifndef BOOST_LOG_CPU_CACHE_LINE_SIZE +//! The macro defines the CPU cache line size for the target architecture. This is mostly used for optimization. +#define BOOST_LOG_CPU_CACHE_LINE_SIZE 64 +#endif + +namespace boost { + +// Setup namespace name +#if !defined(BOOST_LOG_DOXYGEN_PASS) +# if defined(BOOST_LOG_DLL) +# if defined(BOOST_LOG_NO_THREADS) +# define BOOST_LOG_VERSION_NAMESPACE v2_st +# else +# if defined(BOOST_THREAD_PLATFORM_PTHREAD) +# define BOOST_LOG_VERSION_NAMESPACE v2_mt_posix +# elif defined(BOOST_THREAD_PLATFORM_WIN32) +# if defined(BOOST_LOG_USE_WINNT6_API) +# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt6 +# else +# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt5 +# endif // defined(BOOST_LOG_USE_WINNT6_API) +# else +# define BOOST_LOG_VERSION_NAMESPACE v2_mt +# endif +# endif // defined(BOOST_LOG_NO_THREADS) +# else +# if defined(BOOST_LOG_NO_THREADS) +# define BOOST_LOG_VERSION_NAMESPACE v2s_st +# else +# if defined(BOOST_THREAD_PLATFORM_PTHREAD) +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_posix +# elif defined(BOOST_THREAD_PLATFORM_WIN32) +# if defined(BOOST_LOG_USE_WINNT6_API) +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt6 +# else +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt5 +# endif // defined(BOOST_LOG_USE_WINNT6_API) +# else +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt +# endif +# endif // defined(BOOST_LOG_NO_THREADS) +# endif // defined(BOOST_LOG_DLL) + + +namespace log { + +# if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES) + +inline namespace BOOST_LOG_VERSION_NAMESPACE {} +} + +# define BOOST_LOG_OPEN_NAMESPACE namespace log { inline namespace BOOST_LOG_VERSION_NAMESPACE { +# define BOOST_LOG_CLOSE_NAMESPACE }} + +# else + +namespace BOOST_LOG_VERSION_NAMESPACE {} + +using namespace BOOST_LOG_VERSION_NAMESPACE +# if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && !defined(__clang__) +__attribute__((__strong__)) +# endif +; + +} + +# define BOOST_LOG_OPEN_NAMESPACE namespace log { namespace BOOST_LOG_VERSION_NAMESPACE { +# define BOOST_LOG_CLOSE_NAMESPACE }} +# endif + +#else // !defined(BOOST_LOG_DOXYGEN_PASS) + +namespace log {} +# define BOOST_LOG_OPEN_NAMESPACE namespace log { +# define BOOST_LOG_CLOSE_NAMESPACE } + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +#if defined(BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH) +#pragma detect_mismatch("boost_log_abi", BOOST_PP_STRINGIZE(BOOST_LOG_VERSION_NAMESPACE)) +#endif + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_ diff --git a/boost/log/detail/copy_cv.hpp b/boost/log/detail/copy_cv.hpp new file mode 100644 index 0000000000..a6a4ebae04 --- /dev/null +++ b/boost/log/detail/copy_cv.hpp @@ -0,0 +1,64 @@ +/* + * 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 copy_cv.hpp + * \author Andrey Semashev + * \date 16.03.2014 + * + * The header defines \c copy_cv type trait which copies const/volatile qualifiers from one type to another + */ + +#ifndef BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The type trait copies top level const/volatile qualifiers from \c FromT to \c ToT +template< typename FromT, typename ToT > +struct copy_cv +{ + typedef ToT type; +}; + +template< typename FromT, typename ToT > +struct copy_cv< const FromT, ToT > +{ + typedef const ToT type; +}; + +template< typename FromT, typename ToT > +struct copy_cv< volatile FromT, ToT > +{ + typedef volatile ToT type; +}; + +template< typename FromT, typename ToT > +struct copy_cv< const volatile FromT, ToT > +{ + typedef const volatile ToT type; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_ diff --git a/boost/log/detail/custom_terminal_spec.hpp b/boost/log/detail/custom_terminal_spec.hpp new file mode 100644 index 0000000000..fb43357b00 --- /dev/null +++ b/boost/log/detail/custom_terminal_spec.hpp @@ -0,0 +1,70 @@ +/* + * 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 custom_terminal_spec.hpp + * \author Andrey Semashev + * \date 29.01.2012 + * + * The header contains Boost.Phoenix custom terminal specialization for Boost.Log terminals. + */ + +#ifndef BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/terminal.hpp> // needed for terminal-related part of the grammar +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +namespace phoenix { + +template< typename T > +struct is_custom_terminal< T, typename T::_is_boost_log_terminal > : + public mpl::true_ +{ +}; + +template< typename T > +struct custom_terminal< T, typename T::_is_boost_log_terminal > +{ + typedef custom_terminal< T, typename T::_is_boost_log_terminal > this_type; + + template< typename > + struct result; + + template< typename ThisT, typename TermT, typename ContextT > + struct result< ThisT(TermT, ContextT) > + { + typedef typename remove_cv< typename remove_reference< TermT >::type >::type term; + typedef typename boost::result_of< const term(ContextT) >::type type; + }; + + template< typename ContextT > + typename result< const this_type(T const&, ContextT&) >::type operator() (T const& term, ContextT& ctx) const + { + return term(ctx); + } +}; + +} // namespace phoenix + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_ diff --git a/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp b/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp new file mode 100644 index 0000000000..a80930b2ae --- /dev/null +++ b/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp @@ -0,0 +1,44 @@ +/* + * 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 date_time_fmt_gen_traits_fwd.hpp + * \author Andrey Semashev + * \date 07.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename T, typename CharT, typename VoidT = void > +struct date_time_formatter_generator_traits; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_ diff --git a/boost/log/detail/date_time_format_parser.hpp b/boost/log/detail/date_time_format_parser.hpp new file mode 100644 index 0000000000..7b82d5556a --- /dev/null +++ b/boost/log/detail/date_time_format_parser.hpp @@ -0,0 +1,486 @@ +/* + * 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 date_time_format_parser.hpp + * \author Andrey Semashev + * \date 16.09.2012 + * + * The header contains a parser for date and time format strings. + */ + +#ifndef BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_ + +#include <string> +#include <boost/range/as_literal.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +/*! + * This is the interface the parser will use to notify the caller about various components of date in the format string. + */ +template< typename CharT > +struct date_format_parser_callback +{ + //! Character type used by the parser + typedef CharT char_type; + + //! Destructor + virtual ~date_format_parser_callback() {} + + /*! + * \brief The function is called when the parser discovers a string literal in the format string + * + * \param lit The string of characters not interpreted as a placeholder + */ + virtual void on_literal(iterator_range< const char_type* > const& lit) = 0; + + /*! + * \brief The method is called when an unknown placeholder is found in the format string + * + * \param ph The placeholder with the leading percent sign + */ + virtual void on_placeholder(iterator_range< const char_type* > const& ph) + { + // By default interpret all unrecognized placeholders as literals + on_literal(ph); + } + + /*! + * \brief The function is called when the short year placeholder is found in the format string + */ + virtual void on_short_year() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('y'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the full year placeholder is found in the format string + */ + virtual void on_full_year() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('Y'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the numeric month placeholder is found in the format string + */ + virtual void on_numeric_month() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('m'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the short alphabetic month placeholder is found in the format string + */ + virtual void on_short_month() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('b'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the full alphabetic month placeholder is found in the format string + */ + virtual void on_full_month() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('B'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the numeric day of month placeholder is found in the format string + * + * \param leading_zero If \c true, the day should be formatted with leading zero, otherwise with leading space + */ + virtual void on_month_day(bool leading_zero) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('d') : static_cast< char_type >('e')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the numeric day of week placeholder is found in the format string + */ + virtual void on_numeric_week_day() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('w'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the short alphabetic day of week placeholder is found in the format string + */ + virtual void on_short_week_day() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('a'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the full alphabetic day of week placeholder is found in the format string + */ + virtual void on_full_week_day() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('A'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the ISO-formatted date is found in the format string + */ + virtual void on_iso_date() + { + on_full_year(); + on_numeric_month(); + on_month_day(true); + } + + /*! + * \brief The function is called when the extended ISO-formatted date is found in the format string + */ + virtual void on_extended_iso_date() + { + const char_type delimiter[2] = { static_cast< char_type >('-'), static_cast< char_type >('\0') }; + on_full_year(); + on_literal(boost::as_literal(delimiter)); + on_numeric_month(); + on_literal(boost::as_literal(delimiter)); + on_month_day(true); + } +}; + +/*! + * This is the interface the parser will use to notify the caller about various components of date in the format string. + */ +template< typename CharT > +struct time_format_parser_callback +{ + //! Character type used by the parser + typedef CharT char_type; + + //! Destructor + virtual ~time_format_parser_callback() {} + + /*! + * \brief The function is called when the parser discovers a string literal in the format string + * + * \param lit The string of characters not interpreted as a placeholder + */ + virtual void on_literal(iterator_range< const char_type* > const& lit) = 0; + + /*! + * \brief The method is called when an unknown placeholder is found in the format string + * + * \param ph The placeholder with the leading percent sign + */ + virtual void on_placeholder(iterator_range< const char_type* > const& ph) + { + // By default interpret all unrecognized placeholders as literals + on_literal(ph); + } + + /*! + * \brief The function is called when the hours placeholder is found in the format string + * + * The placeholder is used for 24-hour clock and duration formatting. + * + * \param leading_zero If \c true, the one-digit number of hours should be formatted with leading zero, otherwise with leading space + */ + virtual void on_hours(bool leading_zero) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('O') : static_cast< char_type >('k')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the hours placeholder is found in the format string + * + * The placeholder is used for 12-hour clock formatting. It should not be used for duration formatting. + * + * \param leading_zero If \c true, the one-digit number of hours should be formatted with leading zero, otherwise with leading space + */ + virtual void on_hours_12(bool leading_zero) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('I') : static_cast< char_type >('l')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the minutes placeholder is found in the format string + */ + virtual void on_minutes() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('M'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the seconds placeholder is found in the format string + */ + virtual void on_seconds() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('S'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the fractional seconds placeholder is found in the format string + */ + virtual void on_fractional_seconds() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('f'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the day period (AM/PM) placeholder is found in the format string + * + * The placeholder is used for 12-hour clock formatting. It should not be used for duration formatting. + * + * \param upper_case If \c true, the day period will be upper case, and lower case otherwise + */ + virtual void on_am_pm(bool upper_case) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (upper_case ? static_cast< char_type >('p') : static_cast< char_type >('P')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the time duration sign placeholder is found in the format string + * + * The placeholder is used for duration formatting. It should not be used for time point formatting. + * + * \param display_positive If \c true, the positive sign will be explicitly displayed, otherwise only negative sign will be displayed + */ + virtual void on_duration_sign(bool display_positive) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (display_positive ? static_cast< char_type >('+') : static_cast< char_type >('-')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the ISO time zone placeholder is found in the format string + */ + virtual void on_iso_time_zone() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('q'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the extended ISO time zone placeholder is found in the format string + */ + virtual void on_extended_iso_time_zone() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('Q'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the ISO-formatted time is found in the format string + */ + virtual void on_iso_time() + { + on_hours(true); + on_minutes(); + on_seconds(); + } + + /*! + * \brief The function is called when the extended ISO-formatted time is found in the format string + */ + virtual void on_extended_iso_time() + { + const char_type delimiter[2] = { static_cast< char_type >(':'), static_cast< char_type >('\0') }; + on_hours(true); + on_literal(boost::as_literal(delimiter)); + on_minutes(); + on_literal(boost::as_literal(delimiter)); + on_seconds(); + } + + /*! + * \brief The function is called when the extended ISO-formatted time with fractional seconds is found in the format string + */ + virtual void on_default_time() + { + on_extended_iso_time(); + + const char_type delimiter[2] = { static_cast< char_type >('.'), static_cast< char_type >('\0') }; + on_literal(boost::as_literal(delimiter)); + on_fractional_seconds(); + } +}; + +/*! + * This is the interface the parser will use to notify the caller about various components of date in the format string. + */ +template< typename CharT > +struct date_time_format_parser_callback : + public date_format_parser_callback< CharT >, + public time_format_parser_callback< CharT > +{ + //! Character type used by the parser + typedef CharT char_type; + + //! Destructor + virtual ~date_time_format_parser_callback() {} + + /*! + * \brief The function is called when the parser discovers a string literal in the format string + * + * \param lit The string of characters not interpreted as a placeholder + */ + virtual void on_literal(iterator_range< const char_type* > const& lit) = 0; + + /*! + * \brief The method is called when an unknown placeholder is found in the format string + * + * \param ph The placeholder with the leading percent sign + */ + virtual void on_placeholder(iterator_range< const char_type* > const& ph) + { + // By default interpret all unrecognized placeholders as literals + on_literal(ph); + } +}; + +/*! + * \brief Parses the date format string and invokes the callback object + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +BOOST_LOG_API void parse_date_format(const CharT* begin, const CharT* end, date_format_parser_callback< CharT >& callback); + +/*! + * \brief Parses the date format string and invokes the callback object + * + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline void parse_date_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, date_format_parser_callback< CharT >& callback) +{ + const CharT* p = str.c_str(); + return parse_date_format(p, p + str.size(), callback); +} + +/*! + * \brief Parses the date format string and invokes the callback object + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +inline void parse_date_format(const CharT* str, date_format_parser_callback< CharT >& callback) +{ + return parse_date_format(str, str + std::char_traits< CharT >::length(str), callback); +} + +/*! + * \brief Parses the time format string and invokes the callback object + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +BOOST_LOG_API void parse_time_format(const CharT* begin, const CharT* end, time_format_parser_callback< CharT >& callback); + +/*! + * \brief Parses the time format string and invokes the callback object + * + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline void parse_time_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, time_format_parser_callback< CharT >& callback) +{ + const CharT* p = str.c_str(); + return parse_time_format(p, p + str.size(), callback); +} + +/*! + * \brief Parses the time format string and invokes the callback object + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +inline void parse_time_format(const CharT* str, time_format_parser_callback< CharT >& callback) +{ + return parse_time_format(str, str + std::char_traits< CharT >::length(str), callback); +} + +/*! + * \brief Parses the date and time format string and invokes the callback object + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +BOOST_LOG_API void parse_date_time_format(const CharT* begin, const CharT* end, date_time_format_parser_callback< CharT >& callback); + +/*! + * \brief Parses the date and time format string and invokes the callback object + * + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline void parse_date_time_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, date_time_format_parser_callback< CharT >& callback) +{ + const CharT* p = str.c_str(); + return parse_date_time_format(p, p + str.size(), callback); +} + +/*! + * \brief Parses the date and time format string and invokes the callback object + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +inline void parse_date_time_format(const CharT* str, date_time_format_parser_callback< CharT >& callback) +{ + return parse_date_time_format(str, str + std::char_traits< CharT >::length(str), callback); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_ diff --git a/boost/log/detail/decomposed_time.hpp b/boost/log/detail/decomposed_time.hpp new file mode 100644 index 0000000000..24f7546533 --- /dev/null +++ b/boost/log/detail/decomposed_time.hpp @@ -0,0 +1,440 @@ +/* + * 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 decomposed_time.hpp + * \author Andrey Semashev + * \date 07.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_ + +#include <ctime> +#include <string> +#include <vector> +#include <locale> +#include <boost/cstdint.hpp> +#include <boost/move/core.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/date_time_format_parser.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Date and time suitable for formatting +struct decomposed_time +{ + // Subseconds are microseconds + enum _ + { + subseconds_per_second = 1000000, + subseconds_digits10 = 6 + }; + + uint32_t year, month, day, hours, minutes, seconds, subseconds; + bool negative; + + decomposed_time() : year(0), month(1), day(1), hours(0), minutes(0), seconds(0), subseconds(0), negative(false) + { + } + + decomposed_time(uint32_t y, uint32_t mo, uint32_t d, uint32_t h, uint32_t mi, uint32_t s, uint32_t ss = 0, bool neg = false) : + year(y), month(mo), day(d), hours(h), minutes(mi), seconds(s), subseconds(ss), negative(neg) + { + } + + unsigned int week_day() const + { + unsigned int a = (14u - month) / 12u; + unsigned int y = year - a; + unsigned int m = month + 12u * a - 2u; + return (day + y + (y / 4u) - (y / 100u) + (y / 400u) + (31u * m) / 12u) % 7u; + } + + unsigned int year_day() const + { + bool is_leap_year = (!(year % 4u)) && ((year % 100u) || (!(year % 400u))); + static const unsigned int first_day_offset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + return first_day_offset[month - 1] + day + (month > 2 && is_leap_year); + } +}; + +inline std::tm to_tm(decomposed_time const& t) +{ + std::tm res = {}; + res.tm_year = static_cast< int >(t.year) - 1900; + res.tm_mon = t.month - 1; + res.tm_mday = t.day; + res.tm_hour = t.hours; + res.tm_min = t.minutes; + res.tm_sec = t.seconds; + res.tm_wday = t.week_day(); + res.tm_yday = t.year_day(); + res.tm_isdst = -1; + + return res; +} + +template< typename T > +struct decomposed_time_wrapper : + public boost::log::aux::decomposed_time +{ + typedef boost::log::aux::decomposed_time base_type; + typedef T value_type; + value_type m_time; + + BOOST_DEFAULTED_FUNCTION(decomposed_time_wrapper(), {}) + + explicit decomposed_time_wrapper(value_type const& time) : m_time(time) + { + } +}; + +template< typename CharT > +BOOST_LOG_API void put_integer(std::basic_string< CharT >& str, uint32_t value, unsigned int width, CharT fill_char); + +template< typename T, typename CharT > +class date_time_formatter +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(date_time_formatter) + +protected: + // Note: This typedef is needed to work around MSVC 2012 crappy name lookup in the derived classes + typedef date_time_formatter date_time_formatter_; + +public: + typedef void result_type; + typedef T value_type; + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef basic_formatting_ostream< char_type > stream_type; + + struct context + { + date_time_formatter const& self; + stream_type& strm; + string_type& str; + value_type const& value; + unsigned int literal_index, literal_pos; + + context(date_time_formatter const& self_, stream_type& strm_, value_type const& value_) : + self(self_), + strm(strm_), + str(*strm_.rdbuf()->storage()), + value(value_), + literal_index(0), + literal_pos(0) + { + } + + BOOST_DELETED_FUNCTION(context(context const&)) + BOOST_DELETED_FUNCTION(context& operator=(context const&)) + }; + +private: + typedef void (*formatter_type)(context&); + typedef std::vector< formatter_type > formatters; + typedef std::vector< unsigned int > literal_lens; + +protected: + formatters m_formatters; + literal_lens m_literal_lens; + string_type m_literal_chars; + +public: + BOOST_DEFAULTED_FUNCTION(date_time_formatter(), {}) + date_time_formatter(date_time_formatter const& that) : + m_formatters(that.m_formatters), + m_literal_lens(that.m_literal_lens), + m_literal_chars(that.m_literal_chars) + { + } + date_time_formatter(BOOST_RV_REF(date_time_formatter) that) + { + this->swap(static_cast< date_time_formatter& >(that)); + } + + date_time_formatter& operator= (date_time_formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + // Some formatters will put characters directly to the underlying string, so we have to flush stream buffers before formatting + strm.flush(); + context ctx(*this, strm, value); + for (typename formatters::const_iterator it = m_formatters.begin(), end = m_formatters.end(); strm.good() && it != end; ++it) + { + (*it)(ctx); + } + } + + void add_formatter(formatter_type fun) + { + m_formatters.push_back(fun); + } + + void add_literal(iterator_range< const char_type* > const& lit) + { + m_literal_chars.append(lit.begin(), lit.end()); + m_literal_lens.push_back(static_cast< unsigned int >(lit.size())); + m_formatters.push_back(&date_time_formatter_::format_literal); + } + + void swap(date_time_formatter& that) + { + m_formatters.swap(that.m_formatters); + m_literal_lens.swap(that.m_literal_lens); + m_literal_chars.swap(that.m_literal_chars); + } + +public: + template< char FormatCharV > + static void format_through_locale(context& ctx) + { + typedef std::time_put< char_type > facet_type; + typedef typename facet_type::iter_type iter_type; + std::tm t = to_tm(static_cast< decomposed_time const& >(ctx.value)); + std::use_facet< facet_type >(ctx.strm.getloc()).put(iter_type(ctx.strm.stream()), ctx.strm.stream(), ' ', &t, FormatCharV); + ctx.strm.flush(); + } + + static void format_full_year(context& ctx) + { + (put_integer)(ctx.str, ctx.value.year, 4, static_cast< char_type >('0')); + } + + static void format_short_year(context& ctx) + { + (put_integer)(ctx.str, ctx.value.year % 100u, 2, static_cast< char_type >('0')); + } + + static void format_numeric_month(context& ctx) + { + (put_integer)(ctx.str, ctx.value.month, 2, static_cast< char_type >('0')); + } + + template< char_type FillCharV > + static void format_month_day(context& ctx) + { + (put_integer)(ctx.str, ctx.value.day, 2, static_cast< char_type >(FillCharV)); + } + + static void format_week_day(context& ctx) + { + (put_integer)(ctx.str, static_cast< decomposed_time const& >(ctx.value).week_day(), 1, static_cast< char_type >('0')); + } + + template< char_type FillCharV > + static void format_hours(context& ctx) + { + (put_integer)(ctx.str, ctx.value.hours, 2, static_cast< char_type >(FillCharV)); + } + + template< char_type FillCharV > + static void format_hours_12(context& ctx) + { + (put_integer)(ctx.str, ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV)); + } + + static void format_minutes(context& ctx) + { + (put_integer)(ctx.str, ctx.value.minutes, 2, static_cast< char_type >('0')); + } + + static void format_seconds(context& ctx) + { + (put_integer)(ctx.str, ctx.value.seconds, 2, static_cast< char_type >('0')); + } + + static void format_fractional_seconds(context& ctx) + { + (put_integer)(ctx.str, ctx.value.subseconds, decomposed_time::subseconds_digits10, static_cast< char_type >('0')); + } + + template< bool UpperCaseV > + static void format_am_pm(context& ctx) + { + static const char_type am[] = { static_cast< char_type >(UpperCaseV ? 'A' : 'a'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) }; + static const char_type pm[] = { static_cast< char_type >(UpperCaseV ? 'P' : 'p'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) }; + + ctx.str.append(((static_cast< decomposed_time const& >(ctx.value).hours > 11) ? pm : am), 2u); + } + + template< bool DisplayPositiveV > + static void format_sign(context& ctx) + { + if (static_cast< decomposed_time const& >(ctx.value).negative) + ctx.str.push_back('-'); + else if (DisplayPositiveV) + ctx.str.push_back('+'); + } + +private: + static void format_literal(context& ctx) + { + unsigned int len = ctx.self.m_literal_lens[ctx.literal_index], pos = ctx.literal_pos; + ++ctx.literal_index; + ctx.literal_pos += len; + const char_type* lit = ctx.self.m_literal_chars.c_str(); + ctx.str.append(lit + pos, len); + } +}; + +template< typename FormatterT, typename CharT > +class decomposed_time_formatter_builder : + public date_time_format_parser_callback< CharT > +{ +public: + typedef date_time_format_parser_callback< CharT > base_type; + typedef typename base_type::char_type char_type; + typedef FormatterT formatter_type; + typedef typename formatter_type::value_type value_type; + typedef typename formatter_type::stream_type stream_type; + typedef typename stream_type::string_type string_type; + +protected: + formatter_type& m_formatter; + +public: + explicit decomposed_time_formatter_builder(formatter_type& fmt) : m_formatter(fmt) + { + } + + void on_literal(iterator_range< const char_type* > const& lit) + { + m_formatter.add_literal(lit); + } + + void on_short_year() + { + m_formatter.add_formatter(&formatter_type::format_short_year); + } + + void on_full_year() + { + m_formatter.add_formatter(&formatter_type::format_full_year); + } + + void on_numeric_month() + { + m_formatter.add_formatter(&formatter_type::format_numeric_month); + } + + void on_short_month() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'b' >); + } + + void on_full_month() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'B' >); + } + + void on_month_day(bool leading_zero) + { + if (leading_zero) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< '0' >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< ' ' >); + } + + void on_numeric_week_day() + { + m_formatter.add_formatter(&formatter_type::format_week_day); + } + + void on_short_week_day() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'a' >); + } + + void on_full_week_day() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'A' >); + } + + void on_hours(bool leading_zero) + { + if (leading_zero) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< '0' >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< ' ' >); + } + + void on_hours_12(bool leading_zero) + { + if (leading_zero) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< '0' >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< ' ' >); + } + + void on_minutes() + { + m_formatter.add_formatter(&formatter_type::format_minutes); + } + + void on_seconds() + { + m_formatter.add_formatter(&formatter_type::format_seconds); + } + + void on_fractional_seconds() + { + m_formatter.add_formatter(&formatter_type::format_fractional_seconds); + } + + void on_am_pm(bool upper_case) + { + if (upper_case) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< true >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< false >); + } + + void on_duration_sign(bool display_positive) + { + if (display_positive) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< true >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< false >); + } + + void on_iso_time_zone() + { + } + + void on_extended_iso_time_zone() + { + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_ diff --git a/boost/log/detail/deduce_char_type.hpp b/boost/log/detail/deduce_char_type.hpp new file mode 100644 index 0000000000..cb024609e9 --- /dev/null +++ b/boost/log/detail/deduce_char_type.hpp @@ -0,0 +1,108 @@ +/* + * 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 deduce_char_type.hpp + * \author Andrey Semashev + * \date 17.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +struct deduced_char_type; + +template< > +struct deduced_char_type< char > +{ + typedef char type; +}; + +template< > +struct deduced_char_type< const char > +{ + typedef char type; +}; + +template< > +struct deduced_char_type< wchar_t > +{ + typedef wchar_t type; +}; + +template< > +struct deduced_char_type< const wchar_t > +{ + typedef wchar_t type; +}; + +//! Auxiliary traits to detect character type from a string +template< typename RangeT > +struct deduce_char_type : + public deduced_char_type< typename RangeT::value_type > +{ +}; + +template< typename T > +struct deduce_char_type< T* > : + public deduced_char_type< T > +{ +}; + +template< typename T > +struct deduce_char_type< T* const > : + public deduced_char_type< T > +{ +}; + +template< typename T, unsigned int CountV > +struct deduce_char_type< T[CountV] > : + public deduced_char_type< T > +{ +}; + +template< typename T > +struct deduce_char_type< T& > : + public deduce_char_type< T > +{ +}; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T > +struct deduce_char_type< T&& > : + public deduce_char_type< T > +{ +}; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_ diff --git a/boost/log/detail/default_attribute_names.hpp b/boost/log/detail/default_attribute_names.hpp new file mode 100644 index 0000000000..c1fddd36e3 --- /dev/null +++ b/boost/log/detail/default_attribute_names.hpp @@ -0,0 +1,53 @@ +/* + * 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 default_attribute_names.hpp + * \author Andrey Semashev + * \date 15.01.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +namespace default_attribute_names { + +BOOST_LOG_API attribute_name severity(); +BOOST_LOG_API attribute_name channel(); +BOOST_LOG_API attribute_name message(); +BOOST_LOG_API attribute_name line_id(); +BOOST_LOG_API attribute_name timestamp(); +BOOST_LOG_API attribute_name process_id(); +BOOST_LOG_API attribute_name thread_id(); + +} // namespace default_attribute_names + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_ diff --git a/boost/log/detail/embedded_string_type.hpp b/boost/log/detail/embedded_string_type.hpp new file mode 100644 index 0000000000..091dce205b --- /dev/null +++ b/boost/log/detail/embedded_string_type.hpp @@ -0,0 +1,125 @@ +/* + * 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 embedded_string_type.hpp + * \author Andrey Semashev + * \date 16.08.2009 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_ + +#include <string> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T, typename ArgT > +struct make_embedded_string_type_impl +{ + typedef ArgT type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< char, ArgT > +{ + typedef std::basic_string< char > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const char, ArgT > +{ + typedef std::basic_string< char > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< wchar_t, ArgT > +{ + typedef std::basic_string< wchar_t > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const wchar_t, ArgT > +{ + typedef std::basic_string< wchar_t > type; +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +template< typename ArgT > +struct make_embedded_string_type_impl< char16_t, ArgT > +{ + typedef std::basic_string< char16_t > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const char16_t, ArgT > +{ + typedef std::basic_string< char16_t > type; +}; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +template< typename ArgT > +struct make_embedded_string_type_impl< char32_t, ArgT > +{ + typedef std::basic_string< char32_t > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const char32_t, ArgT > +{ + typedef std::basic_string< char32_t > type; +}; +#endif + +//! An auxiliary type translator to store strings by value in function objects and attribute values +template< typename ArgT > +struct make_embedded_string_type : + public remove_cv< ArgT > +{ +}; + +template< typename ArgT > +struct make_embedded_string_type< ArgT* > : + public make_embedded_string_type_impl< ArgT, ArgT* > +{ +}; + +template< typename ArgT, unsigned int CountV > +struct make_embedded_string_type< ArgT[CountV] > : + public make_embedded_string_type_impl< ArgT, ArgT[CountV] > +{ +}; + +template< typename ArgT, unsigned int CountV > +struct make_embedded_string_type< ArgT(&)[CountV] > : + public make_embedded_string_type_impl< ArgT, ArgT(&)[CountV] > +{ +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_ diff --git a/boost/log/detail/enqueued_record.hpp b/boost/log/detail/enqueued_record.hpp new file mode 100644 index 0000000000..11aaf186f5 --- /dev/null +++ b/boost/log/detail/enqueued_record.hpp @@ -0,0 +1,103 @@ +/* + * 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 enqueued_record.hpp + * \author Andrey Semashev + * \date 01.04.2014 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/timestamp.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace aux { + +//! Log record with enqueueing timestamp +class enqueued_record +{ + BOOST_COPYABLE_AND_MOVABLE(enqueued_record) + +public: + //! Ordering predicate + template< typename OrderT > + struct order : + public OrderT + { + typedef typename OrderT::result_type result_type; + + order() {} + order(order const& that) : OrderT(static_cast< OrderT const& >(that)) {} + order(OrderT const& that) : OrderT(that) {} + + result_type operator() (enqueued_record const& left, enqueued_record const& right) const + { + // std::priority_queue requires ordering with semantics of std::greater, so we swap arguments + return OrderT::operator() (right.m_record, left.m_record); + } + }; + + boost::log::aux::timestamp m_timestamp; + record_view m_record; + + enqueued_record(enqueued_record const& that) : m_timestamp(that.m_timestamp), m_record(that.m_record) + { + } + enqueued_record(BOOST_RV_REF(enqueued_record) that) : + m_timestamp(that.m_timestamp), + m_record(boost::move(that.m_record)) + { + } + explicit enqueued_record(record_view const& rec) : + m_timestamp(boost::log::aux::get_timestamp()), + m_record(rec) + { + } + enqueued_record& operator= (BOOST_COPY_ASSIGN_REF(enqueued_record) that) + { + m_timestamp = that.m_timestamp; + m_record = that.m_record; + return *this; + } + enqueued_record& operator= (BOOST_RV_REF(enqueued_record) that) + { + m_timestamp = that.m_timestamp; + m_record = boost::move(that.m_record); + return *this; + } +}; + +} // namespace aux + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ diff --git a/boost/log/detail/event.hpp b/boost/log/detail/event.hpp new file mode 100644 index 0000000000..741ab3c9bd --- /dev/null +++ b/boost/log/detail/event.hpp @@ -0,0 +1,142 @@ +/* + * 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 detail/event.hpp + * \author Andrey Semashev + * \date 24.07.2011 + */ + +#ifndef BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#if defined(BOOST_THREAD_PLATFORM_PTHREAD) +# if defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES + 0) > 0 +# if defined(__GNUC__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# include <semaphore.h> +# include <boost/cstdint.hpp> +# define BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE +# endif +# endif +#elif defined(BOOST_THREAD_PLATFORM_WIN32) +# include <boost/cstdint.hpp> +# define BOOST_LOG_EVENT_USE_WINAPI +#endif + +#if !defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) && !defined(BOOST_LOG_EVENT_USE_WINAPI) +# include <boost/thread/mutex.hpp> +# include <boost/thread/condition_variable.hpp> +# define BOOST_LOG_EVENT_USE_BOOST_CONDITION +#endif + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) + +class sem_based_event +{ +private: + boost::uint32_t m_state; + sem_t m_semaphore; + +public: + //! Default constructor + BOOST_LOG_API sem_based_event(); + //! Destructor + BOOST_LOG_API ~sem_based_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(sem_based_event(sem_based_event const&)) + BOOST_DELETED_FUNCTION(sem_based_event& operator= (sem_based_event const&)) +}; + +typedef sem_based_event event; + +#elif defined(BOOST_LOG_EVENT_USE_WINAPI) + +class winapi_based_event +{ +private: + boost::uint32_t m_state; + void* m_event; + +public: + //! Default constructor + BOOST_LOG_API winapi_based_event(); + //! Destructor + BOOST_LOG_API ~winapi_based_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(winapi_based_event(winapi_based_event const&)) + BOOST_DELETED_FUNCTION(winapi_based_event& operator= (winapi_based_event const&)) +}; + +typedef winapi_based_event event; + +#else + +class generic_event +{ +private: + boost::mutex m_mutex; + boost::condition_variable m_cond; + bool m_state; + +public: + //! Default constructor + BOOST_LOG_API generic_event(); + //! Destructor + BOOST_LOG_API ~generic_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(generic_event(generic_event const&)) + BOOST_DELETED_FUNCTION(generic_event& operator= (generic_event const&)) +}; + +typedef generic_event event; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_ diff --git a/boost/log/detail/fake_mutex.hpp b/boost/log/detail/fake_mutex.hpp new file mode 100644 index 0000000000..f21f961538 --- /dev/null +++ b/boost/log/detail/fake_mutex.hpp @@ -0,0 +1,56 @@ +/* + * 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 fake_mutex.hpp + * \author Andrey Semashev + * \date 31.07.2011 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Fake mutex that doesn't do anything. Note: we're not using \c null_mutex from Boost.Thread in order not to introduce false dependencies on Boost.Thread and Boost.Chrono. +class fake_mutex +{ +public: + BOOST_DEFAULTED_FUNCTION(fake_mutex(), {}) + void lock() {} + bool try_lock() { return true; } + template< typename T > + bool timed_lock(T const&) { return true; } + void unlock() {} + + // Copying prohibited + BOOST_DELETED_FUNCTION(fake_mutex(fake_mutex const&)) + BOOST_DELETED_FUNCTION(fake_mutex& operator=(fake_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_ diff --git a/boost/log/detail/footer.hpp b/boost/log/detail/footer.hpp new file mode 100644 index 0000000000..8208ebd33a --- /dev/null +++ b/boost/log/detail/footer.hpp @@ -0,0 +1,22 @@ +/* + * 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) + */ + +#if !defined(BOOST_LOG_ENABLE_WARNINGS) + +#if defined(_MSC_VER) + +#pragma warning(pop) + +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + +#pragma GCC diagnostic pop + +#endif + +#endif // !defined(BOOST_LOG_ENABLE_WARNINGS) + +#include <boost/config/abi_suffix.hpp> diff --git a/boost/log/detail/format.hpp b/boost/log/detail/format.hpp new file mode 100644 index 0000000000..d383aba717 --- /dev/null +++ b/boost/log/detail/format.hpp @@ -0,0 +1,336 @@ +/* + * 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 format.hpp + * \author Andrey Semashev + * \date 15.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_ + +#include <string> +#include <vector> +#include <iosfwd> +#include <boost/assert.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/unhandled_exception_count.hpp> +#include <boost/log/detail/cleanup_scope_guard.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! An element (either literal or placeholder) of the format string +struct format_element +{ + //! Argument placeholder number or -1 if it's not a placeholder (i.e. a literal) + int arg_number; + //! If the element describes a constant literal, the starting character and length of the literal + unsigned int literal_start_pos, literal_len; + + format_element() : arg_number(0), literal_start_pos(0), literal_len(0) + { + } + + static format_element literal(unsigned int start_pos, unsigned int len) + { + format_element el; + el.arg_number = -1; + el.literal_start_pos = start_pos; + el.literal_len = len; + return el; + } + + static format_element positional_argument(unsigned int arg_n) + { + format_element el; + el.arg_number = arg_n; + return el; + } +}; + +//! Parsed format string description +template< typename CharT > +struct format_description +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(format_description) + +public: + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + + //! Array of format element descriptors + typedef std::vector< format_element > format_element_list; + + //! Characters of all literal parts of the format string + string_type literal_chars; + //! Format element descriptors + format_element_list format_elements; + + BOOST_DEFAULTED_FUNCTION(format_description(), {}) + + format_description(format_description const& that) : literal_chars(that.literal_chars), format_elements(that.format_elements) + { + } + + format_description(BOOST_RV_REF(format_description) that) + { + literal_chars.swap(that.literal_chars); + format_elements.swap(that.format_elements); + } + + format_description& operator= (format_description that) + { + literal_chars.swap(that.literal_chars); + format_elements.swap(that.format_elements); + return *this; + } +}; + +//! Parses format string +template< typename CharT > +BOOST_LOG_API format_description< CharT > parse_format(const CharT* begin, const CharT* end); + +//! Parses format string +template< typename CharT > +BOOST_FORCEINLINE format_description< CharT > parse_format(const CharT* begin) +{ + return parse_format(begin, begin + std::char_traits< CharT >::length(begin)); +} + +//! Parses format string +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_FORCEINLINE format_description< CharT > parse_format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt) +{ + const CharT* begin = fmt.c_str(); + return parse_format(begin, begin + fmt.size()); +} + +//! Formatter object +template< typename CharT > +class basic_format +{ +public: + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Format description type + typedef format_description< char_type > format_description_type; + + //! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream. + class pump; + friend class pump; + +private: + //! Formatting params for a single placeholder in the format string + struct formatting_params + { + //! Formatting element index in the format description + unsigned int element_idx; + //! Formatting result + string_type target; + + formatting_params() : element_idx(~0u) {} + }; + typedef std::vector< formatting_params > formatting_params_list; + +private: + //! Format string description + format_description_type m_format; + //! Formatting parameters for all placeholders + formatting_params_list m_formatting_params; + //! Current formatting position + unsigned int m_current_idx; + +public: + //! Initializing constructor + explicit basic_format(string_type const& fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0) + { + init_params(); + } + //! Initializing constructor + explicit basic_format(const char_type* fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0) + { + init_params(); + } + + //! Clears all formatted strings and resets the current formatting position + void clear() BOOST_NOEXCEPT + { + for (typename formatting_params_list::iterator it = m_formatting_params.begin(), end = m_formatting_params.end(); it != end; ++it) + { + it->target.clear(); + } + m_current_idx = 0; + } + + //! Creates a pump that will receive all format arguments and put the formatted string into the stream + pump make_pump(stream_type& strm) BOOST_NOEXCEPT + { + return pump(*this, strm); + } + + //! Composes the final string from the formatted pieces + void compose(string_type& str) const + { + typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end(); + for (; it != end; ++it) + { + if (it->arg_number >= 0) + { + // This is a placeholder + str.append(m_formatting_params[it->arg_number].target); + } + else + { + // This is a literal + const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos; + str.append(p, it->literal_len); + } + } + } + + //! Composes the final string from the formatted pieces + string_type str() const + { + string_type result; + compose(result); + return boost::move(result); + } + +private: + //! Initializes the formatting params + void init_params() + { + typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end(); + for (; it != end; ++it) + { + if (it->arg_number >= 0) + { + if (static_cast< unsigned int >(it->arg_number) >= m_formatting_params.size()) + m_formatting_params.resize(it->arg_number + 1); + m_formatting_params[it->arg_number].element_idx = static_cast< unsigned int >(it - m_format.format_elements.begin()); + } + } + } +}; + +//! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream. +template< typename CharT > +class basic_format< CharT >::pump +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(pump) + +private: + //! The guard temporarily replaces storage string in the specified stream + struct scoped_storage + { + scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_backup(*strm.rdbuf()->storage()) + { + strm.attach(storage); + } + ~scoped_storage() + { + m_stream.attach(m_storage_backup); + } + + private: + stream_type& m_stream; + string_type& m_storage_backup; + }; + +private: + //! Reference to the owner + basic_format* m_owner; + //! Reference to the stream + stream_type* m_stream; + //! Unhandled exception count + const unsigned int m_exception_count; + +public: + //! Initializing constructor + pump(basic_format& owner, stream_type& strm) BOOST_NOEXCEPT : m_owner(&owner), m_stream(&strm), m_exception_count(unhandled_exception_count()) + { + } + + //! Move constructor + pump(BOOST_RV_REF(pump) that) BOOST_NOEXCEPT : m_owner(that.m_owner), m_stream(that.m_stream), m_exception_count(that.m_exception_count) + { + that.m_owner = NULL; + that.m_stream = NULL; + } + + //! Destructor + ~pump() BOOST_NOEXCEPT_IF(false) + { + if (m_owner) + { + // Whether or not the destructor is called because of an exception, the format object has to be cleared + boost::log::aux::cleanup_guard< basic_format< char_type > > cleanup1(*m_owner); + + BOOST_ASSERT(m_stream != NULL); + if (m_exception_count >= unhandled_exception_count()) + { + // Compose the final string in the stream buffer + m_stream->flush(); + m_owner->compose(*m_stream->rdbuf()->storage()); + } + } + } + + /*! + * Puts an argument to the formatter. Note the pump has to be returned by value and not by reference in order this to + * work with Boost.Phoenix expressions. Otherwise the pump that is returned from \c basic_format::make_pump is + * destroyed after the first call to \c operator%, and the returned reference becomes dangling. + */ + template< typename T > + pump operator% (T const& val) + { + BOOST_ASSERT_MSG(m_owner != NULL && m_stream != NULL, "Boost.Log: This basic_format::pump has already been moved from"); + + if (m_owner->m_current_idx < m_owner->m_formatting_params.size()) + { + scoped_storage storage_guard(*m_stream, m_owner->m_formatting_params[m_owner->m_current_idx].target); + + *m_stream << val; + m_stream->flush(); + + ++m_owner->m_current_idx; + } + + return boost::move(*this); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_ diff --git a/boost/log/detail/function_traits.hpp b/boost/log/detail/function_traits.hpp new file mode 100644 index 0000000000..bd298fca30 --- /dev/null +++ b/boost/log/detail/function_traits.hpp @@ -0,0 +1,236 @@ +/* + * 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 function_traits.hpp + * \author Andrey Semashev + * \date 30.08.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_ + +#include <boost/mpl/has_xxx.hpp> +#include <boost/log/detail/config.hpp> + +#if defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX) +# if !defined(BOOST_LOG_NO_FUNCTION_TRAITS) +# define BOOST_LOG_NO_FUNCTION_TRAITS +# endif +#else + +#include <boost/mpl/int.hpp> +#include <boost/mpl/front.hpp> +#include <boost/mpl/pop_front.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/function_types/function_arity.hpp> +#include <boost/function_types/parameter_types.hpp> +#include <boost/function_types/is_nonmember_callable_builtin.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + + // A number of traits to deal with functors + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_argument_type, argument_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_first_argument_type, first_argument_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_second_argument_type, second_argument_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg1_type, arg1_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg2_type, arg2_type, false) + + namespace has_arity_no_adl { + + typedef char yes_type; + struct no_type + { + char dummy[2]; + }; + + template< typename FunT, int ArityV = FunT::arity > + struct checker + { + }; + + template< typename FunT > + yes_type has_arity_impl(FunT const&, checker< FunT >*); + template< typename FunT > + no_type has_arity_impl(FunT const&, ...); + + } // namespace has_arity_no_adl + + //! The metafunction detects if the type has an arity static constant member + template< typename FunT > + struct has_arity + { + static FunT const& get_FunT(); + + enum value_t { value = (sizeof(has_arity_no_adl::has_arity_impl(get_FunT(), 0)) == sizeof(has_arity_no_adl::yes_type)) }; + typedef mpl::bool_< value > type; + }; + + //! The metafunction results in an unqualified type with removed reference + template< typename T > + struct root_type : + public remove_cv< + typename remove_reference< + T + >::type + > + { + }; + + template< + typename FunT, + bool = function_types::is_nonmember_callable_builtin< FunT >::value, + bool = has_argument_type< FunT >::value, + bool = has_first_argument_type< FunT >::value, + bool = has_arg1_type< FunT >::value + > + struct first_argument_type_of_impl + { + }; + template< typename FunT > + struct first_argument_type_of_impl< FunT, true, false, false, false > + { + typedef typename root_type< + typename mpl::front< + typename function_types::parameter_types< FunT >::type + >::type + >::type type; + }; + template< typename FunT, bool HasFirstArgumentV, bool HasArg1V > + struct first_argument_type_of_impl< FunT, false, true, HasFirstArgumentV, HasArg1V > + { + typedef typename root_type< + typename FunT::argument_type + >::type type; + }; + template< typename FunT, bool HasArg1V > + struct first_argument_type_of_impl< FunT, false, false, true, HasArg1V > + { + typedef typename root_type< + typename FunT::first_argument_type + >::type type; + }; + template< typename FunT > + struct first_argument_type_of_impl< FunT, false, false, false, true > + { + typedef typename root_type< + typename FunT::arg1_type + >::type type; + }; + + //! The metafunction returns the first argument type of a function + template< typename FunT > + struct first_argument_type_of : + public first_argument_type_of_impl< FunT > + { + }; + + + template< + typename FunT, + bool = function_types::is_nonmember_callable_builtin< FunT >::value, + bool = has_second_argument_type< FunT >::value, + bool = has_arg2_type< FunT >::value + > + struct second_argument_type_of_impl + { + }; + template< typename FunT > + struct second_argument_type_of_impl< FunT, true, false, false > + { + typedef typename root_type< + typename mpl::front< + typename mpl::pop_front< + typename function_types::parameter_types< FunT >::type + >::type + >::type + >::type type; + }; + template< typename FunT, bool HasArg2V > + struct second_argument_type_of_impl< FunT, false, true, HasArg2V > + { + typedef typename root_type< + typename FunT::second_argument_type + >::type type; + }; + template< typename FunT > + struct second_argument_type_of_impl< FunT, false, false, true > + { + typedef typename root_type< + typename FunT::arg2_type + >::type type; + }; + + //! The metafunction returns the second argument type of a function + template< typename FunT > + struct second_argument_type_of : + public second_argument_type_of_impl< FunT > + { + }; + + + template< + typename FunT, + bool = function_types::is_nonmember_callable_builtin< FunT >::value, + bool = has_arity< FunT >::value, + bool = has_argument_type< FunT >::value, + bool = has_second_argument_type< FunT >::value + > + struct arity_of_impl + { + }; + template< typename FunT > + struct arity_of_impl< FunT, true, false, false, false > : + public function_types::function_arity< FunT > + { + }; + template< typename FunT, bool HasArgumentTypeV, bool HasSecondArgumentTypeV > + struct arity_of_impl< FunT, false, true, HasArgumentTypeV, HasSecondArgumentTypeV > : + public mpl::int_< FunT::arity > + { + }; + template< typename FunT, bool HasArgumentTypeV > + struct arity_of_impl< FunT, false, false, HasArgumentTypeV, true > : + public mpl::int_< 2 > + { + }; + template< typename FunT > + struct arity_of_impl< FunT, false, false, true, false > : + public mpl::int_< 1 > + { + }; + + //! The metafunction returns the arity of a function + template< typename FunT > + struct arity_of : + public arity_of_impl< FunT > + { + }; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX) + +#endif // BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_ diff --git a/boost/log/detail/generate_overloads.hpp b/boost/log/detail/generate_overloads.hpp new file mode 100644 index 0000000000..63b9edf081 --- /dev/null +++ b/boost/log/detail/generate_overloads.hpp @@ -0,0 +1,30 @@ +/* + * 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) + */ + +BOOST_LOG_AUX_OVERLOAD(const&, const&) +BOOST_LOG_AUX_OVERLOAD(&, const&) +BOOST_LOG_AUX_OVERLOAD(const&, &) +BOOST_LOG_AUX_OVERLOAD(&, &) + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +BOOST_LOG_AUX_OVERLOAD(const&&, const&&) +BOOST_LOG_AUX_OVERLOAD(&&, const&&) +BOOST_LOG_AUX_OVERLOAD(const&&, &&) +BOOST_LOG_AUX_OVERLOAD(&&, &&) + +BOOST_LOG_AUX_OVERLOAD(const&&, const&) +BOOST_LOG_AUX_OVERLOAD(&&, const&) +BOOST_LOG_AUX_OVERLOAD(const&&, &) +BOOST_LOG_AUX_OVERLOAD(&&, &) + +BOOST_LOG_AUX_OVERLOAD(const&, const&&) +BOOST_LOG_AUX_OVERLOAD(&, const&&) +BOOST_LOG_AUX_OVERLOAD(const&, &&) +BOOST_LOG_AUX_OVERLOAD(&, &&) + +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/boost/log/detail/header.hpp b/boost/log/detail/header.hpp new file mode 100644 index 0000000000..f7cf75d557 --- /dev/null +++ b/boost/log/detail/header.hpp @@ -0,0 +1,64 @@ +/* + * 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) + */ + +#include <boost/config/abi_prefix.hpp> + +#if !defined(BOOST_LOG_ENABLE_WARNINGS) + +#if defined(_MSC_VER) + +#pragma warning(push, 3) +// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B' +#pragma warning(disable: 4251) +// non dll-interface class 'A' used as base for dll-interface class 'B' +#pragma warning(disable: 4275) +// switch statement contains 'default' but no 'case' labels +#pragma warning(disable: 4065) +// 'this' : used in base member initializer list +#pragma warning(disable: 4355) +// 'int' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable: 4800) +// unreferenced formal parameter +#pragma warning(disable: 4100) +// conditional expression is constant +#pragma warning(disable: 4127) +// default constructor could not be generated +#pragma warning(disable: 4510) +// copy constructor could not be generated +#pragma warning(disable: 4511) +// assignment operator could not be generated +#pragma warning(disable: 4512) +// struct 'A' can never be instantiated - user defined constructor required +#pragma warning(disable: 4610) +// function marked as __forceinline not inlined +#pragma warning(disable: 4714) +// decorated name length exceeded, name was truncated +#pragma warning(disable: 4503) +// declaration of 'A' hides previous local declaration +#pragma warning(disable: 4456) +// declaration of 'A' hides global declaration +#pragma warning(disable: 4459) + +#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \ + && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + +#pragma GCC diagnostic push +// 'var' defined but not used +#pragma GCC diagnostic ignored "-Wunused-variable" +// unused parameter 'arg' +#pragma GCC diagnostic ignored "-Wunused-parameter" +// missing initializer for member var +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 +// typedef 'foo' locally defined but not used +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#endif + +#endif + +#endif // !defined(BOOST_LOG_ENABLE_WARNINGS) diff --git a/boost/log/detail/id.hpp b/boost/log/detail/id.hpp new file mode 100644 index 0000000000..2ca1e1e30d --- /dev/null +++ b/boost/log/detail/id.hpp @@ -0,0 +1,84 @@ +/* + * 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 id.hpp + * \author Andrey Semashev + * \date 08.01.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_ID_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ID_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Generic identifier class +template< typename DescriptorT > +class id +{ +public: + //! Native type of the process id + typedef typename DescriptorT::native_type native_type; + +private: + native_type m_NativeID; + +public: + BOOST_CONSTEXPR id() BOOST_NOEXCEPT : m_NativeID(0) {} + + explicit id(native_type native) BOOST_NOEXCEPT : m_NativeID(native) {} + + native_type native_id() const BOOST_NOEXCEPT { return m_NativeID; } + + bool operator== (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID == that.m_NativeID); + } + bool operator!= (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID != that.m_NativeID); + } + bool operator< (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID < that.m_NativeID); + } + bool operator> (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID > that.m_NativeID); + } + bool operator<= (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID <= that.m_NativeID); + } + bool operator>= (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID >= that.m_NativeID); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ID_HPP_INCLUDED_ diff --git a/boost/log/detail/light_function.hpp b/boost/log/detail/light_function.hpp new file mode 100644 index 0000000000..b673359e63 --- /dev/null +++ b/boost/log/detail/light_function.hpp @@ -0,0 +1,521 @@ +/* + * 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 light_function.hpp + * \author Andrey Semashev + * \date 20.06.2010 + * + * \brief This header is the Boost.Log library impl, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + * + * The file contains a lightweight alternative of Boost.Function. It does not provide all + * features of Boost.Function but doesn't introduce dependency on Boost.Bind. + */ + +#ifndef BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ + +#include <cstddef> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/type_traits/remove_cv.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +#endif +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include <boost/utility/enable_if.hpp> +#else +#include <boost/type_traits/remove_reference.hpp> +#endif +#if defined(BOOST_NO_CXX11_NULLPTR) +#include <boost/assert.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_LIGHT_FUNCTION_LIMIT +#define BOOST_LOG_LIGHT_FUNCTION_LIMIT 2 +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T, typename ThisT > +struct is_cv_same { enum _ { value = false }; }; +template< typename T > +struct is_cv_same< T, T > { enum _ { value = true }; }; +template< typename T > +struct is_cv_same< T, const T > { enum _ { value = true }; }; +template< typename T > +struct is_cv_same< T, volatile T > { enum _ { value = true }; }; +template< typename T > +struct is_cv_same< T, const volatile T > { enum _ { value = true }; }; + +template< typename T, typename ThisT > +struct is_rv_or_same { enum _ { value = false }; }; +template< typename T > +struct is_rv_or_same< T, T > { enum _ { value = true }; }; +template< typename T, typename ThisT > +struct is_rv_or_same< boost::rv< T >, ThisT > { enum _ { value = true }; }; + +#endif + +template< typename SignatureT > +class light_function; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template< typename ResultT, typename... ArgsT > +class light_function< ResultT (ArgsT...) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef ResultT result_type; + +private: + struct impl_base + { + typedef result_type (*invoke_type)(void*, ArgsT...); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self, ArgsT... args) + { + return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (ArgsT... args) const + { + return m_pImpl->invoke(m_pImpl, args...); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; + +template< typename... ArgsT > +class light_function< void (ArgsT...) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef void result_type; + +private: + struct impl_base + { + typedef void (*invoke_type)(void*, ArgsT...); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self, ArgsT... args) + { + static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (ArgsT... args) const + { + m_pImpl->invoke(m_pImpl, args...); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; + +#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#define BOOST_PP_FILENAME_1 <boost/log/detail/light_function_pp.hpp> +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_LOG_LIGHT_FUNCTION_LIMIT) +#include BOOST_PP_ITERATE() + +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template< typename SignatureT > +inline void swap(light_function< SignatureT >& left, light_function< SignatureT >& right) +{ + left.swap(right); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ diff --git a/boost/log/detail/light_function_pp.hpp b/boost/log/detail/light_function_pp.hpp new file mode 100644 index 0000000000..55eca7cdd8 --- /dev/null +++ b/boost/log/detail/light_function_pp.hpp @@ -0,0 +1,424 @@ +/* + * 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) + */ + +template< + typename ResultT + BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename ArgT) +> +class light_function< ResultT (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef ResultT result_type; + +private: + struct impl_base + { + typedef result_type (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) + { + return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const + { + return m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; + +template< + BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) +> +class light_function< void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef void result_type; + +private: + struct impl_base + { + typedef void (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) + { + static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const + { + m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; diff --git a/boost/log/detail/light_rw_mutex.hpp b/boost/log/detail/light_rw_mutex.hpp new file mode 100644 index 0000000000..abfef13972 --- /dev/null +++ b/boost/log/detail/light_rw_mutex.hpp @@ -0,0 +1,208 @@ +/* + * 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 light_rw_mutex.hpp + * \author Andrey Semashev + * \date 24.03.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#include <boost/log/detail/header.hpp> + +#if defined(BOOST_THREAD_POSIX) // This one can be defined by users, so it should go first +#define BOOST_LOG_LWRWMUTEX_USE_PTHREAD +#elif defined(BOOST_WINDOWS) && defined(BOOST_LOG_USE_WINNT6_API) +#define BOOST_LOG_LWRWMUTEX_USE_SRWLOCK +#elif defined(BOOST_HAS_PTHREADS) +#define BOOST_LOG_LWRWMUTEX_USE_PTHREAD +#endif + +#if defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK) + +#if defined(BOOST_USE_WINDOWS_H) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 // _WIN32_WINNT_LONGHORN +#endif + +#include <windows.h> + +#else // defined(BOOST_USE_WINDOWS_H) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +extern "C" { + +struct SRWLOCK { void* p; }; +__declspec(dllimport) void __stdcall InitializeSRWLock(SRWLOCK*); +__declspec(dllimport) void __stdcall ReleaseSRWLockExclusive(SRWLOCK*); +__declspec(dllimport) void __stdcall ReleaseSRWLockShared(SRWLOCK*); +__declspec(dllimport) void __stdcall AcquireSRWLockExclusive(SRWLOCK*); +__declspec(dllimport) void __stdcall AcquireSRWLockShared(SRWLOCK*); + +} // extern "C" + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_USE_WINDOWS_H + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A light read/write mutex that uses WinNT 6 and later APIs +class light_rw_mutex +{ + SRWLOCK m_Mutex; + +public: + light_rw_mutex() + { + InitializeSRWLock(&m_Mutex); + } + void lock_shared() + { + AcquireSRWLockShared(&m_Mutex); + } + void unlock_shared() + { + ReleaseSRWLockShared(&m_Mutex); + } + void lock() + { + AcquireSRWLockExclusive(&m_Mutex); + } + void unlock() + { + ReleaseSRWLockExclusive(&m_Mutex); + } + + // Noncopyable + BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&)) + BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#elif defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) + +#include <pthread.h> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A light read/write mutex that maps directly onto POSIX threading library +class light_rw_mutex +{ + pthread_rwlock_t m_Mutex; + +public: + light_rw_mutex() + { + pthread_rwlock_init(&m_Mutex, NULL); + } + ~light_rw_mutex() + { + pthread_rwlock_destroy(&m_Mutex); + } + void lock_shared() + { + pthread_rwlock_rdlock(&m_Mutex); + } + void unlock_shared() + { + pthread_rwlock_unlock(&m_Mutex); + } + void lock() + { + pthread_rwlock_wrlock(&m_Mutex); + } + void unlock() + { + pthread_rwlock_unlock(&m_Mutex); + } + + // Noncopyable + BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&)) + BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#else + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A light read/write mutex +class light_rw_mutex +{ + struct { void* p; } m_Mutex; + +public: + BOOST_LOG_API light_rw_mutex(); + BOOST_LOG_API ~light_rw_mutex(); + BOOST_LOG_API void lock_shared(); + BOOST_LOG_API void unlock_shared(); + BOOST_LOG_API void lock(); + BOOST_LOG_API void unlock(); + + // Noncopyable + BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&)) + BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_ diff --git a/boost/log/detail/locking_ptr.hpp b/boost/log/detail/locking_ptr.hpp new file mode 100644 index 0000000000..913780e98e --- /dev/null +++ b/boost/log/detail/locking_ptr.hpp @@ -0,0 +1,148 @@ +/* + * 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 locking_ptr.hpp + * \author Andrey Semashev + * \date 15.07.2009 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_ + +#include <cstddef> +#include <boost/move/core.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/thread/lock_options.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A pointer type that locks the backend until it's destroyed +template< typename T, typename LockableT > +class locking_ptr +{ + typedef locking_ptr this_type; + BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) + +public: + //! Pointed type + typedef T element_type; + +private: + //! Lockable type + typedef LockableT lockable_type; + +private: + //! The pointer to the backend + shared_ptr< element_type > m_pElement; + //! Reference to the shared lock control object + lockable_type* m_pLock; + +public: + //! Default constructor + locking_ptr() BOOST_NOEXCEPT : m_pLock(NULL) + { + } + //! Constructor + locking_ptr(shared_ptr< element_type > const& p, lockable_type& l) : m_pElement(p), m_pLock(&l) + { + m_pLock->lock(); + } + //! Constructor + locking_ptr(shared_ptr< element_type > const& p, lockable_type& l, try_to_lock_t const&) : m_pElement(p), m_pLock(&l) + { + if (!m_pLock->try_lock()) + { + m_pElement.reset(); + m_pLock = NULL; + } + } + //! Copy constructor + locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock) + { + if (m_pLock) + m_pLock->lock(); + } + //! Move constructor + locking_ptr(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_pLock(that.m_pLock) + { + m_pElement.swap(that.m_pElement); + that.m_pLock = NULL; + } + + //! Destructor + ~locking_ptr() + { + if (m_pLock) + m_pLock->unlock(); + } + + //! Assignment + locking_ptr& operator= (locking_ptr that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + + //! Indirection + element_type* operator-> () const BOOST_NOEXCEPT { return m_pElement.get(); } + //! Dereferencing + element_type& operator* () const BOOST_NOEXCEPT { return *m_pElement; } + + //! Accessor to the raw pointer + element_type* get() const BOOST_NOEXCEPT { return m_pElement.get(); } + + //! Checks for null pointer + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + //! Checks for null pointer + bool operator! () const BOOST_NOEXCEPT { return !m_pElement; } + + //! Swaps two pointers + void swap(locking_ptr& that) BOOST_NOEXCEPT + { + m_pElement.swap(that.m_pElement); + lockable_type* p = m_pLock; + m_pLock = that.m_pLock; + that.m_pLock = p; + } +}; + +//! Free raw pointer getter to assist generic programming +template< typename T, typename LockableT > +inline T* get_pointer(locking_ptr< T, LockableT > const& p) BOOST_NOEXCEPT +{ + return p.get(); +} +//! Free swap operation +template< typename T, typename LockableT > +inline void swap(locking_ptr< T, LockableT >& left, locking_ptr< T, LockableT >& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_ diff --git a/boost/log/detail/locks.hpp b/boost/log/detail/locks.hpp new file mode 100644 index 0000000000..72b8945b26 --- /dev/null +++ b/boost/log/detail/locks.hpp @@ -0,0 +1,180 @@ +/* + * 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 locks.hpp + * \author Andrey Semashev + * \date 30.05.2010 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +#ifndef BOOST_LOG_NO_THREADS + +// Forward declaration of Boost.Thread locks. Specified here to avoid including Boost.Thread, +// which would bring in many dependent headers, including a great deal of Boost.DateTime. +template< typename > +class lock_guard; +template< typename > +class shared_lock; +template< typename > +class upgrade_lock; +template< typename > +class unique_lock; + +template< typename > +struct is_mutex_type; + +#endif // BOOST_LOG_NO_THREADS + +BOOST_LOG_OPEN_NAMESPACE + +//! An auxiliary pseudo-lock to express no locking requirements in logger features +template< typename MutexT > +class no_lock +{ +public: + /*! + * Constructs the pseudo-lock. The mutex is not affected during the construction. + */ + explicit no_lock(MutexT&) {} + +private: + no_lock(no_lock const&); + no_lock& operator= (no_lock const&); +}; + +namespace aux { + +#ifndef BOOST_LOG_NO_THREADS + +//! A trait to detect if the mutex supports exclusive locking +template< typename MutexT > +struct is_exclusively_lockable +{ + typedef char true_type; + struct false_type { char t[2]; }; + + template< typename T > + static true_type check_lockable(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock); + static false_type check_lockable(void*); + + enum value_t { value = sizeof(check_lockable((MutexT*)NULL)) == sizeof(true_type) }; +}; + +//! A trait to detect if the mutex supports shared locking +template< typename MutexT > +struct is_shared_lockable +{ + typedef char true_type; + struct false_type { char t[2]; }; + + template< typename T > + static true_type check_shared_lockable(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared); + static false_type check_shared_lockable(void*); + + enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) }; +}; + +//! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread. +template< typename MutexT > +struct exclusive_lock_guard +{ + explicit exclusive_lock_guard(MutexT& m) : m_Mutex(m) + { + m.lock(); + } + ~exclusive_lock_guard() + { + m_Mutex.unlock(); + } + +private: + exclusive_lock_guard(exclusive_lock_guard const&); + exclusive_lock_guard& operator= (exclusive_lock_guard const&); + +private: + MutexT& m_Mutex; +}; + +//! An analogue to the minimalistic \c lock_guard template that locks \c shared_mutex with shared ownership. +template< typename MutexT > +struct shared_lock_guard +{ + explicit shared_lock_guard(MutexT& m) : m_Mutex(m) + { + m.lock_shared(); + } + ~shared_lock_guard() + { + m_Mutex.unlock_shared(); + } + +private: + shared_lock_guard(shared_lock_guard const&); + shared_lock_guard& operator= (shared_lock_guard const&); + +private: + MutexT& m_Mutex; +}; + +//! A deadlock-safe lock type that exclusively locks two mutexes +template< typename MutexT1, typename MutexT2 > +class multiple_unique_lock2 +{ +public: + multiple_unique_lock2(MutexT1& m1, MutexT2& m2) : + m_p1(&m1), + m_p2(&m2) + { + // Yes, it's not conforming, but it works + // and it doesn't require to #include <functional> + if (static_cast< void* >(m_p1) < static_cast< void* >(m_p2)) + { + m_p1->lock(); + m_p2->lock(); + } + else + { + m_p2->lock(); + m_p1->lock(); + } + } + ~multiple_unique_lock2() + { + m_p2->unlock(); + m_p1->unlock(); + } + +private: + MutexT1* m_p1; + MutexT2* m_p2; +}; + +#endif // BOOST_LOG_NO_THREADS + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ diff --git a/boost/log/detail/named_scope_fmt_pp.hpp b/boost/log/detail/named_scope_fmt_pp.hpp new file mode 100644 index 0000000000..d9f0027f86 --- /dev/null +++ b/boost/log/detail/named_scope_fmt_pp.hpp @@ -0,0 +1,82 @@ +/* + * 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) + */ + +template< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) > +BOOST_FORCEINLINE format_named_scope_actor< + fallback_to_none, + typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type +> format_named_scope(attribute_name const& name, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg)) +{ + typedef typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type char_type; + return aux::format_named_scope< char_type, phoenix::actor >(name, fallback_to_none(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg))); +} + +template< typename DescriptorT, template< typename > class ActorT, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) > +BOOST_FORCEINLINE format_named_scope_actor< + fallback_to_none, + typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type, + ActorT +> +format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg)) +{ + BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type char_type; + return aux::format_named_scope< char_type, ActorT >(keyword.get_name(), fallback_to_none(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg))); +} + +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) > +BOOST_FORCEINLINE format_named_scope_actor< + FallbackPolicyT, + typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type, + ActorT +> +format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg)) +{ + BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type char_type; + return aux::format_named_scope< char_type, ActorT >(placeholder.get_name(), placeholder.get_fallback_policy(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg))); +} diff --git a/boost/log/detail/native_typeof.hpp b/boost/log/detail/native_typeof.hpp new file mode 100644 index 0000000000..276b2942e8 --- /dev/null +++ b/boost/log/detail/native_typeof.hpp @@ -0,0 +1,63 @@ +/* + * 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 native_typeof.hpp + * \author Andrey Semashev + * \date 08.03.2009 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_NO_CXX11_DECLTYPE) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +T get_root_type(T const&); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#define BOOST_LOG_TYPEOF(x) decltype(::boost::log::aux::get_root_type(x)) + +#elif defined(__COMO__) && defined(__GNUG__) + +#define BOOST_LOG_TYPEOF(x) typeof(x) + +#elif defined(__GNUC__) || defined(__MWERKS__) + +#define BOOST_LOG_TYPEOF(x) __typeof__(x) + +#endif + + +#if !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) +#define BOOST_LOG_AUTO(var, expr) auto var = (expr) +#endif + +#if !defined(BOOST_LOG_AUTO) && defined(BOOST_LOG_TYPEOF) +#define BOOST_LOG_AUTO(var, expr) BOOST_LOG_TYPEOF((expr)) var = (expr) +#endif + +#endif // BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_ diff --git a/boost/log/detail/parameter_tools.hpp b/boost/log/detail/parameter_tools.hpp new file mode 100644 index 0000000000..692a3377d3 --- /dev/null +++ b/boost/log/detail/parameter_tools.hpp @@ -0,0 +1,114 @@ +/* + * 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 parameter_tools.hpp + * \author Andrey Semashev + * \date 28.06.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/facilities/intercept.hpp> +#include <boost/preprocessor/arithmetic/dec.hpp> +#include <boost/preprocessor/tuple/elem.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_MAX_PARAMETER_ARGS +//! The maximum number of named arguments that are accepted by constructors and functions +#define BOOST_LOG_MAX_PARAMETER_ARGS 16 +#endif + +// The macro applies the passed macro with the specified arguments BOOST_LOG_MAX_PARAMETER_ARGS times +#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(macro, args)\ + public:\ + BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, macro, args) + + +#define BOOST_LOG_CTOR_FORWARD(z, n, types)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ + BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))) {} + +// The macro expands to a number of templated constructors that aggregate their named arguments +// into an ArgumentsPack and pass it to the base class constructor. +#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, base_type)\ + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_FORWARD, (class_type, base_type)) + + +#define BOOST_LOG_CTOR_CALL(z, n, types)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\ + { BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))); } + +// The macro expands to a number of templated constructors that aggregate their named arguments +// into an ArgumentsPack and pass it to a function call. +#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(class_type, fun)\ + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_CALL, (class_type, fun)) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +// Yeah, not too cute. The empty_arg_list class should really be public. +typedef boost::parameter::aux::empty_arg_list empty_arg_list; + +#if !(defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION)) + +//! The metafunction generates argument pack +template< typename ArgT0, typename... ArgsT > +struct make_arg_list +{ + typedef boost::parameter::aux::arg_list< ArgT0, typename make_arg_list< ArgsT... >::type > type; +}; + +template< typename ArgT0 > +struct make_arg_list< ArgT0 > +{ + typedef boost::parameter::aux::arg_list< ArgT0 > type; +}; + +#else + +//! The metafunction generates argument pack +template< typename ArgT0, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), typename T, = void BOOST_PP_INTERCEPT) > +struct make_arg_list +{ + typedef boost::parameter::aux::arg_list< ArgT0, typename make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), T) >::type > type; +}; + +template< typename ArgT0 > +struct make_arg_list< ArgT0, BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), void BOOST_PP_INTERCEPT) > +{ + typedef boost::parameter::aux::arg_list< ArgT0 > type; +}; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_ diff --git a/boost/log/detail/pp_identity.hpp b/boost/log/detail/pp_identity.hpp new file mode 100644 index 0000000000..8daaf951b8 --- /dev/null +++ b/boost/log/detail/pp_identity.hpp @@ -0,0 +1,27 @@ +/* + * 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 pp_identity.hpp + * \author Andrey Semashev + * \date 12.02.2011 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_LOG_PP_IDENTITY(z, n, data) data + +#endif // BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_ diff --git a/boost/log/detail/process_id.hpp b/boost/log/detail/process_id.hpp new file mode 100644 index 0000000000..3532506c2a --- /dev/null +++ b/boost/log/detail/process_id.hpp @@ -0,0 +1,60 @@ +/* + * 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 process_id.hpp + * \author Andrey Semashev + * \date 12.09.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/id.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The process id descriptor +struct process +{ + typedef unsigned long native_type; + typedef boost::log::aux::id< process > id; +}; + +namespace this_process { + +//! The function returns current process identifier +BOOST_LOG_API process::id get_id(); + +} // namespace this_process + +template< typename CharT, typename TraitsT > +BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& +operator<< (std::basic_ostream< CharT, TraitsT >& strm, process::id const& pid); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_ diff --git a/boost/log/detail/setup_config.hpp b/boost/log/detail/setup_config.hpp new file mode 100644 index 0000000000..11239592af --- /dev/null +++ b/boost/log/detail/setup_config.hpp @@ -0,0 +1,61 @@ +/* + * 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 setup_config.hpp + * \author Andrey Semashev + * \date 14.09.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB) + +// Detect if we're dealing with dll +# if defined(BOOST_LOG_SETUP_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# define BOOST_LOG_SETUP_DLL +# endif + +# if defined(BOOST_HAS_DECLSPEC) && defined(BOOST_LOG_SETUP_DLL) +# define BOOST_LOG_SETUP_API __declspec(dllimport) +# else +# define BOOST_LOG_SETUP_API +# endif // defined(BOOST_HAS_DECLSPEC) +// +// Automatically link to the correct build variant where possible. +// +# if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_LOG_SETUP_NO_LIB) +# define BOOST_LIB_NAME boost_log_setup +# if defined(BOOST_LOG_SETUP_DLL) +# define BOOST_DYN_LINK +# endif +# include <boost/config/auto_link.hpp> +# endif // auto-linking disabled + +#else // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB) + +# if defined(BOOST_HAS_DECLSPEC) && defined(BOOST_LOG_SETUP_DLL) +# define BOOST_LOG_SETUP_API __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 && (defined(linux) || defined(__linux) || defined(__linux__)) +# define BOOST_LOG_SETUP_API __attribute__((visibility("default"))) +# else +# define BOOST_LOG_SETUP_API +# endif + +#endif // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB) + +#endif // BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_ diff --git a/boost/log/detail/singleton.hpp b/boost/log/detail/singleton.hpp new file mode 100644 index 0000000000..ac1ac1afe0 --- /dev/null +++ b/boost/log/detail/singleton.hpp @@ -0,0 +1,89 @@ +/* + * 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 singleton.hpp + * \author Andrey Semashev + * \date 20.04.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/once_block.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A base class for singletons, constructed on-demand +template< typename DerivedT, typename StorageT = DerivedT > +class lazy_singleton +{ +public: + BOOST_DEFAULTED_FUNCTION(lazy_singleton(), {}) + + //! Returns the singleton instance + static StorageT& get() + { + BOOST_LOG_ONCE_BLOCK() + { + DerivedT::init_instance(); + } + return get_instance(); + } + + //! Initializes the singleton instance + static void init_instance() + { + get_instance(); + } + + BOOST_DELETED_FUNCTION(lazy_singleton(lazy_singleton const&)) + BOOST_DELETED_FUNCTION(lazy_singleton& operator= (lazy_singleton const&)) + +protected: + //! Returns the singleton instance (not thread-safe) + static StorageT& get_instance() + { + static StorageT instance; + return instance; + } +}; + +//! A base class for singletons, constructed on namespace scope initialization stage +template< typename DerivedT, typename StorageT = DerivedT > +class singleton : + public lazy_singleton< DerivedT, StorageT > +{ +public: + static StorageT& instance; +}; + +template< typename DerivedT, typename StorageT > +StorageT& singleton< DerivedT, StorageT >::instance = + lazy_singleton< DerivedT, StorageT >::get(); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_ diff --git a/boost/log/detail/sink_init_helpers.hpp b/boost/log/detail/sink_init_helpers.hpp new file mode 100644 index 0000000000..060aab7fc8 --- /dev/null +++ b/boost/log/detail/sink_init_helpers.hpp @@ -0,0 +1,118 @@ +/* + * 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 sink_init_helpers.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_ + +#include <string> +#include <boost/mpl/bool.hpp> +#include <boost/parameter/binding.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/phoenix/core/is_actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/core/core.hpp> +#include <boost/log/expressions/filter.hpp> +#include <boost/log/expressions/formatter.hpp> +#include <boost/log/utility/setup/filter_parser.hpp> +#include <boost/log/utility/setup/formatter_parser.hpp> +#include <boost/log/keywords/filter.hpp> +#include <boost/log/keywords/format.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +// The function creates a filter functional object from the provided argument +template< typename CharT > +inline filter acquire_filter(const CharT* filter) +{ + return boost::log::parse_filter(filter); +} +template< typename CharT, typename TraitsT, typename AllocatorT > +inline filter acquire_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& filter) +{ + return boost::log::parse_filter(filter); +} +template< typename FilterT > +inline typename enable_if< + phoenix::is_actor< FilterT >, + FilterT const& +>::type acquire_filter(FilterT const& filter) +{ + return filter; +} + +// The function installs filter into the sink, if provided in the arguments pack +template< typename SinkT, typename ArgsT > +inline void setup_filter(SinkT&, ArgsT const&, mpl::true_) +{ +} + +template< typename SinkT, typename ArgsT > +inline void setup_filter(SinkT& s, ArgsT const& args, mpl::false_) +{ + s.set_filter(aux::acquire_filter(args[keywords::filter])); +} + + +// The function creates a filter functional object from the provided argument +template< typename CharT > +inline basic_formatter< CharT > acquire_formatter(const CharT* formatter) +{ + return boost::log::parse_formatter(formatter); +} +template< typename CharT, typename TraitsT, typename AllocatorT > +inline basic_formatter< CharT > acquire_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& formatter) +{ + return boost::log::parse_formatter(formatter); +} +template< typename FormatterT > +inline typename enable_if< + phoenix::is_actor< FormatterT >, + FormatterT const& +>::type acquire_formatter(FormatterT const& formatter) +{ + return formatter; +} + +// The function installs filter into the sink, if provided in the arguments pack +template< typename SinkT, typename ArgsT > +inline void setup_formatter(SinkT&, ArgsT const&, mpl::true_) +{ +} + +template< typename SinkT, typename ArgsT > +inline void setup_formatter(SinkT& s, ArgsT const& args, mpl::false_) +{ + s.set_formatter(aux::acquire_formatter(args[keywords::format])); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_ diff --git a/boost/log/detail/snprintf.hpp b/boost/log/detail/snprintf.hpp new file mode 100644 index 0000000000..ced0cd593a --- /dev/null +++ b/boost/log/detail/snprintf.hpp @@ -0,0 +1,106 @@ +/* + * 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 snprintf.hpp + * \author Andrey Semashev + * \date 20.02.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_ + +#include <stdio.h> +#include <cstddef> +#include <cstdarg> +#include <boost/log/detail/config.hpp> +#ifdef BOOST_LOG_USE_WCHAR_T +#include <wchar.h> +#endif // BOOST_LOG_USE_WCHAR_T +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if !defined(_MSC_VER) + +// Standard-conforming compilers already have the correct snprintfs +using ::snprintf; +using ::vsnprintf; + +# ifdef BOOST_LOG_USE_WCHAR_T +using ::swprintf; +using ::vswprintf; +# endif // BOOST_LOG_USE_WCHAR_T + +#else // !defined(_MSC_VER) + +// MSVC snprintfs are not conforming but they are good enough for our cases +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + int n = _vsnprintf(buf, size, format, args); + if (static_cast< unsigned int >(n) >= size) + { + n = static_cast< int >(size); + buf[size - 1] = '\0'; + } + return n; +} + +# ifdef BOOST_LOG_USE_WCHAR_T +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ + int n = _vsnwprintf(buf, size, format, args); + if (static_cast< unsigned int >(n) >= size) + { + n = static_cast< int >(size); + buf[size - 1] = L'\0'; + } + return n; +} +# endif // BOOST_LOG_USE_WCHAR_T + +inline int snprintf(char* buf, std::size_t size, const char* format, ...) +{ + std::va_list args; + va_start(args, format); + int n = vsnprintf(buf, size, format, args); + va_end(args); + return n; +} + +# ifdef BOOST_LOG_USE_WCHAR_T +inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...) +{ + std::va_list args; + va_start(args, format); + int n = vswprintf(buf, size, format, args); + va_end(args); + return n; +} +# endif // BOOST_LOG_USE_WCHAR_T + +#endif // !defined(_MSC_VER) + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_ diff --git a/boost/log/detail/spin_mutex.hpp b/boost/log/detail/spin_mutex.hpp new file mode 100644 index 0000000000..727d6d1ade --- /dev/null +++ b/boost/log/detail/spin_mutex.hpp @@ -0,0 +1,319 @@ +/* + * 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 spin_mutex.hpp + * \author Andrey Semashev + * \date 01.08.2010 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#include <boost/throw_exception.hpp> +#include <boost/thread/exceptions.hpp> + +#if defined(BOOST_THREAD_POSIX) // This one can be defined by users, so it should go first +#define BOOST_LOG_SPIN_MUTEX_USE_PTHREAD +#elif defined(BOOST_WINDOWS) +#define BOOST_LOG_SPIN_MUTEX_USE_WINAPI +#elif defined(BOOST_HAS_PTHREADS) +#define BOOST_LOG_SPIN_MUTEX_USE_PTHREAD +#endif + +#if defined(BOOST_LOG_SPIN_MUTEX_USE_WINAPI) + +#include <boost/detail/interlocked.hpp> + +#if defined(BOOST_USE_WINDOWS_H) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#include <windows.h> + +#else // defined(BOOST_USE_WINDOWS_H) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +extern "C" { + +__declspec(dllimport) int __stdcall SwitchToThread(); + +} // extern "C" + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_USE_WINDOWS_H + +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) +# if defined(_M_IX86) +# define BOOST_LOG_PAUSE_OP __asm { pause } +# elif defined(_M_AMD64) +extern "C" void _mm_pause(void); +#pragma intrinsic(_mm_pause) +# define BOOST_LOG_PAUSE_OP _mm_pause() +# endif +# if defined(__INTEL_COMPILER) +# define BOOST_LOG_COMPILER_BARRIER __memory_barrier() +# else +extern "C" void _ReadWriteBarrier(void); +#pragma intrinsic(_ReadWriteBarrier) +# define BOOST_LOG_COMPILER_BARRIER _ReadWriteBarrier() +# endif +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# define BOOST_LOG_PAUSE_OP __asm__ __volatile__("pause;") +# define BOOST_LOG_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory") +#endif + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A simple spinning mutex +class spin_mutex +{ +private: + enum state + { + initial_pause = 2, + max_pause = 16 + }; + + long m_State; + +public: + spin_mutex() : m_State(0) {} + + bool try_lock() + { + return (BOOST_INTERLOCKED_COMPARE_EXCHANGE(&m_State, 1L, 0L) == 0L); + } + + void lock() + { +#if defined(BOOST_LOG_PAUSE_OP) + unsigned int pause_count = initial_pause; +#endif + while (!try_lock()) + { +#if defined(BOOST_LOG_PAUSE_OP) + if (pause_count < max_pause) + { + for (unsigned int i = 0; i < pause_count; ++i) + { + BOOST_LOG_PAUSE_OP; + } + pause_count += pause_count; + } + else + { + // Restart spinning after waking up this thread + pause_count = initial_pause; + SwitchToThread(); + } +#else + SwitchToThread(); +#endif + } + } + + void unlock() + { +#if (defined(_M_IX86) || defined(_M_AMD64)) && defined(BOOST_LOG_COMPILER_BARRIER) + BOOST_LOG_COMPILER_BARRIER; + m_State = 0L; + BOOST_LOG_COMPILER_BARRIER; +#else + BOOST_INTERLOCKED_EXCHANGE(&m_State, 0L); +#endif + } + + // Non-copyable + BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&)) + BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&)) +}; + +#undef BOOST_LOG_PAUSE_OP +#undef BOOST_LOG_COMPILER_BARRIER + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#elif defined(BOOST_LOG_SPIN_MUTEX_USE_PTHREAD) + +#include <pthread.h> +#include <boost/assert.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if defined(_POSIX_SPIN_LOCKS) && _POSIX_SPIN_LOCKS > 0 + +//! A simple spinning mutex +class spin_mutex +{ +private: + pthread_spinlock_t m_State; + +public: + spin_mutex() + { + const int err = pthread_spin_init(&m_State, PTHREAD_PROCESS_PRIVATE); + if (err != 0) + throw_exception< thread_resource_error >(err, "failed to initialize a spin mutex", "spin_mutex::spin_mutex()", __FILE__, __LINE__); + } + + ~spin_mutex() + { + BOOST_VERIFY(pthread_spin_destroy(&m_State) == 0); + } + + bool try_lock() + { + const int err = pthread_spin_trylock(&m_State); + if (err == 0) + return true; + if (err != EBUSY) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::try_lock()", __FILE__, __LINE__); + return false; + } + + void lock() + { + const int err = pthread_spin_lock(&m_State); + if (err != 0) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::lock()", __FILE__, __LINE__); + } + + void unlock() + { + BOOST_VERIFY(pthread_spin_unlock(&m_State) == 0); + } + + // Non-copyable + BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&)) + BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&)) + +private: + template< typename ExceptionT > + static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_exception(int err, const char* descr, const char* func, const char* file, int line) + { +#if !defined(BOOST_EXCEPTION_DISABLE) + boost::exception_detail::throw_exception_(ExceptionT(err, descr), func, file, line); +#else + boost::throw_exception(ExceptionT(err, descr)); +#endif + } +}; + +#else // defined(_POSIX_SPIN_LOCKS) + +//! Backup implementation in case if pthreads don't support spin locks +class spin_mutex +{ +private: + pthread_mutex_t m_State; + +public: + spin_mutex() + { + const int err = pthread_mutex_init(&m_State, NULL); + if (err != 0) + throw_exception< thread_resource_error >(err, "failed to initialize a spin mutex", "spin_mutex::spin_mutex()", __FILE__, __LINE__); + } + + ~spin_mutex() + { + BOOST_VERIFY(pthread_mutex_destroy(&m_State) == 0); + } + + bool try_lock() + { + const int err = pthread_mutex_trylock(&m_State); + if (err == 0) + return true; + if (err != EBUSY) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::try_lock()", __FILE__, __LINE__); + return false; + } + + void lock() + { + const int err = pthread_mutex_lock(&m_State); + if (err != 0) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::lock()", __FILE__, __LINE__); + } + + void unlock() + { + BOOST_VERIFY(pthread_mutex_unlock(&m_State) == 0); + } + + // Non-copyable + BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&)) + BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&)) + +private: + template< typename ExceptionT > + static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_exception(int err, const char* descr, const char* func, const char* file, int line) + { +#if !defined(BOOST_EXCEPTION_DISABLE) + boost::exception_detail::throw_exception_(ExceptionT(err, descr), func, file, line); +#else + boost::throw_exception(ExceptionT(err, descr)); +#endif + } +}; + +#endif // defined(_POSIX_SPIN_LOCKS) + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_ diff --git a/boost/log/detail/tagged_integer.hpp b/boost/log/detail/tagged_integer.hpp new file mode 100644 index 0000000000..5aef5bbfcc --- /dev/null +++ b/boost/log/detail/tagged_integer.hpp @@ -0,0 +1,147 @@ +/* + * 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 tagged_integer.hpp + * \author Andrey Semashev + * \date 11.01.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_ +#define BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A tagged integer wrapper for type safety +template< typename IntT, typename TagT > +struct tagged_integer +{ + //! Contained value type + typedef IntT integer_type; + //! Tag + typedef TagT tag; + + //! Contained value + integer_type value; + + //! Conversion operator + operator integer_type() const { return value; } + + // Increment + tagged_integer& operator++ () { ++value; return *this; } + tagged_integer operator++ (int) { tagged_integer temp = *this; ++value; return temp; } + // Decrement + tagged_integer& operator-- () { --value; return *this; } + tagged_integer operator-- (int) { tagged_integer temp = *this; --value; return temp; } + +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + tagged_integer& operator op (tagged_integer const& that) { value op that.value; return *this; } + + BOOST_LOG_TAGGED_INTEGER_OP(|=) + BOOST_LOG_TAGGED_INTEGER_OP(&=) + BOOST_LOG_TAGGED_INTEGER_OP(^=) + BOOST_LOG_TAGGED_INTEGER_OP(+=) + BOOST_LOG_TAGGED_INTEGER_OP(-=) + BOOST_LOG_TAGGED_INTEGER_OP(*=) + BOOST_LOG_TAGGED_INTEGER_OP(/=) + BOOST_LOG_TAGGED_INTEGER_OP(%=) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + + //! Inversion operator + tagged_integer& operator~ () { ~value; return *this; } + + // Shift operators + template< typename T > + tagged_integer& operator<<= (T const& that) { value <<= that; return *this; } + template< typename T > + tagged_integer& operator>>= (T const& that) { value >>= that; return *this; } + +private: + // Protection against improper usage + template< typename T1, typename T2 > + tagged_integer& operator<<= (tagged_integer< T1, T2 > const&); + template< typename T1, typename T2 > + tagged_integer& operator>>= (tagged_integer< T1, T2 > const&); +}; + + // Relational operators +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + template< typename IntT, typename TagT >\ + inline bool operator op (\ + tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\ + {\ + return (left.value op right.value);\ + } + +BOOST_LOG_TAGGED_INTEGER_OP(==) +BOOST_LOG_TAGGED_INTEGER_OP(!=) +BOOST_LOG_TAGGED_INTEGER_OP(<) +BOOST_LOG_TAGGED_INTEGER_OP(>) +BOOST_LOG_TAGGED_INTEGER_OP(<=) +BOOST_LOG_TAGGED_INTEGER_OP(>=) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + template< typename IntT, typename TagT >\ + inline tagged_integer< IntT, TagT > operator op (\ + tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\ + {\ + tagged_integer< IntT, TagT > temp = left;\ + temp op##= right;\ + return temp;\ + } + +BOOST_LOG_TAGGED_INTEGER_OP(|) +BOOST_LOG_TAGGED_INTEGER_OP(&) +BOOST_LOG_TAGGED_INTEGER_OP(^) +BOOST_LOG_TAGGED_INTEGER_OP(+) +BOOST_LOG_TAGGED_INTEGER_OP(-) +BOOST_LOG_TAGGED_INTEGER_OP(*) +BOOST_LOG_TAGGED_INTEGER_OP(/) +BOOST_LOG_TAGGED_INTEGER_OP(%) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + template< typename IntT, typename TagT, typename T >\ + inline tagged_integer< IntT, TagT > operator op (\ + tagged_integer< IntT, TagT > const& left, T const& right)\ + {\ + tagged_integer< IntT, TagT > temp = left;\ + temp op##= right;\ + return temp;\ + } + +BOOST_LOG_TAGGED_INTEGER_OP(<<) +BOOST_LOG_TAGGED_INTEGER_OP(>>) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_ diff --git a/boost/log/detail/thread_id.hpp b/boost/log/detail/thread_id.hpp new file mode 100644 index 0000000000..3b592c2c25 --- /dev/null +++ b/boost/log/detail/thread_id.hpp @@ -0,0 +1,65 @@ +/* + * 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 thread_id.hpp + * \author Andrey Semashev + * \date 08.01.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/cstdint.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/id.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The thread id descriptor +struct thread +{ +#if defined(BOOST_WINDOWS) + typedef uint32_t native_type; +#else + typedef uintmax_t native_type; +#endif + typedef boost::log::aux::id< thread > id; +}; + +namespace this_thread { + +//! The function returns current thread identifier +BOOST_LOG_API thread::id const& get_id(); + +} // namespace this_thread + +template< typename CharT, typename TraitsT > +BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& +operator<< (std::basic_ostream< CharT, TraitsT >& strm, thread::id const& tid); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_ diff --git a/boost/log/detail/thread_specific.hpp b/boost/log/detail/thread_specific.hpp new file mode 100644 index 0000000000..72d2a3b22e --- /dev/null +++ b/boost/log/detail/thread_specific.hpp @@ -0,0 +1,116 @@ +/* + * 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 thread_specific.hpp + * \author Andrey Semashev + * \date 01.03.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_pod.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_LOG_NO_THREADS) + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Base class for TLS to hide platform-specific storage management +class thread_specific_base +{ +private: + union key_storage + { + void* as_pointer; + unsigned int as_dword; + }; + + key_storage m_Key; + +protected: + BOOST_LOG_API thread_specific_base(); + BOOST_LOG_API ~thread_specific_base(); + BOOST_LOG_API void* get_content() const; + BOOST_LOG_API void set_content(void* value) const; + + // Copying prohibited + BOOST_DELETED_FUNCTION(thread_specific_base(thread_specific_base const&)) + BOOST_DELETED_FUNCTION(thread_specific_base& operator= (thread_specific_base const&)) +}; + +//! A TLS wrapper for small POD types with least possible overhead +template< typename T > +class thread_specific : + public thread_specific_base +{ + BOOST_STATIC_ASSERT_MSG(sizeof(T) <= sizeof(void*) && is_pod< T >::value, "Boost.Log: Thread-specific values must be PODs and must not exceed the size of a pointer"); + + //! Union to perform type casting + union value_storage + { + void* as_pointer; + T as_value; + }; + +public: + //! Default constructor + BOOST_DEFAULTED_FUNCTION(thread_specific(), {}) + //! Initializing constructor + thread_specific(T const& value) + { + set(value); + } + //! Assignment + thread_specific& operator= (T const& value) + { + set(value); + return *this; + } + + //! Accessor + T get() const + { + value_storage cast = {}; + cast.as_pointer = thread_specific_base::get_content(); + return cast.as_value; + } + + //! Setter + void set(T const& value) + { + value_storage cast = {}; + cast.as_value = value; + thread_specific_base::set_content(cast.as_pointer); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif // BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ diff --git a/boost/log/detail/threadsafe_queue.hpp b/boost/log/detail/threadsafe_queue.hpp new file mode 100644 index 0000000000..a1e78249f0 --- /dev/null +++ b/boost/log/detail/threadsafe_queue.hpp @@ -0,0 +1,277 @@ +/* + * 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 threadsafe_queue.hpp + * \author Andrey Semashev + * \date 05.11.2010 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#include <new> +#include <memory> +#include <cstddef> +#include <boost/aligned_storage.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/type_traits/alignment_of.hpp> +#include <boost/type_traits/type_with_alignment.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Base class for the thread-safe queue implementation +struct threadsafe_queue_impl +{ + struct +#if defined(__GNUC__) + // Explicitly mark the type so that it may alias other types + __attribute__ ((__may_alias__)) +#endif + pointer_storage + { + union + { + void* data[2]; + type_with_alignment< 2 * sizeof(void*) >::type alignment; + }; + }; + + struct node_base + { + pointer_storage next; + }; + + static BOOST_LOG_API threadsafe_queue_impl* create(node_base* first_node); + + static BOOST_LOG_API void* operator new (std::size_t size); + static BOOST_LOG_API void operator delete (void* p, std::size_t); + + virtual ~threadsafe_queue_impl() {} + virtual node_base* reset_last_node() = 0; + virtual bool unsafe_empty() = 0; + virtual void push(node_base* p) = 0; + virtual bool try_pop(node_base*& node_to_free, node_base*& node_with_value) = 0; +}; + +//! A helper class to compose some of the types used by the queue +template< typename T, typename AllocatorT > +struct threadsafe_queue_types +{ + struct node : + public threadsafe_queue_impl::node_base + { + typedef typename aligned_storage< sizeof(T), alignment_of< T >::value >::type storage_type; + storage_type storage; + + node() {} + explicit node(T const& val) { new (storage.address()) T(val); } + T& value() { return *static_cast< T* >(storage.address()); } + void destroy() { static_cast< T* >(storage.address())->~T(); } + }; + + typedef typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< node >::other allocator_type; +}; + +/*! + * \brief An unbounded thread-safe queue + * + * The implementation is based on algorithms published in the "Simple, Fast, + * and Practical Non-Blocking and Blocking Concurrent Queue Algorithms" article + * in PODC96 by Maged M. Michael and Michael L. Scott. Pseudocode is available here: + * http://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html + * + * The implementation provides thread-safe \c push and \c try_pop operations, as well as + * a thread-unsafe \c empty operation. The queue imposes the following requirements + * on the element type: + * + * \li Default constructible, the default constructor must not throw. + * \li Copy constructible. + * \li Movable (i.e. there should be an efficient move assignment for this type). + * + * The last requirement is not mandatory but is crucial for decent performance. + */ +template< typename T, typename AllocatorT = std::allocator< void > > +class threadsafe_queue : + private threadsafe_queue_types< T, AllocatorT >::allocator_type +{ +private: + typedef typename threadsafe_queue_types< T, AllocatorT >::allocator_type base_type; + typedef typename threadsafe_queue_types< T, AllocatorT >::node node; + + //! A simple scope guard to automate memory reclaiming + struct auto_deallocate; + friend struct auto_deallocate; + struct auto_deallocate + { + auto_deallocate(base_type* alloc, node* dealloc, node* destr) : + m_pAllocator(alloc), + m_pDeallocate(dealloc), + m_pDestroy(destr) + { + } + ~auto_deallocate() + { + m_pAllocator->deallocate(m_pDeallocate, 1); + m_pDestroy->destroy(); + } + + private: + base_type* m_pAllocator; + node* m_pDeallocate; + node* m_pDestroy; + }; + +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T* pointer; + typedef T const* const_pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef AllocatorT allocator_type; + +public: + /*! + * Default constructor, creates an empty queue. Unlike most containers, + * the constructor requires memory allocation. + * + * \throw std::bad_alloc if there is not sufficient memory + */ + threadsafe_queue(base_type const& alloc = base_type()) : + base_type(alloc) + { + node* p = base_type::allocate(1); + if (p) + { + try + { + new (p) node(); + try + { + m_pImpl = threadsafe_queue_impl::create(p); + } + catch (...) + { + p->~node(); + throw; + } + } + catch (...) + { + base_type::deallocate(p, 1); + throw; + } + } + else + throw std::bad_alloc(); + } + /*! + * Destructor + */ + ~threadsafe_queue() + { + // Clear the queue + if (!unsafe_empty()) + { + value_type value; + while (try_pop(value)); + } + + // Remove the last dummy node + node* p = static_cast< node* >(m_pImpl->reset_last_node()); + p->~node(); + base_type::deallocate(p, 1); + + delete m_pImpl; + } + + /*! + * Checks if the queue is empty. Not thread-safe, the returned result may not be actual. + */ + bool unsafe_empty() const { return m_pImpl->unsafe_empty(); } + + /*! + * Puts a new element to the end of the queue. Thread-safe, can be called + * concurrently by several threads, and concurrently with the \c pop operation. + */ + void push(const_reference value) + { + node* p = base_type::allocate(1); + if (p) + { + try + { + new (p) node(value); + } + catch (...) + { + base_type::deallocate(p, 1); + throw; + } + m_pImpl->push(p); + } + else + throw std::bad_alloc(); + } + + /*! + * Attempts to pop an element from the beginning of the queue. Thread-safe, can + * be called concurrently with the \c push operation. Should not be called by + * several threads concurrently. + */ + bool try_pop(reference value) + { + threadsafe_queue_impl::node_base *dealloc, *destr; + if (m_pImpl->try_pop(dealloc, destr)) + { + node* p = static_cast< node* >(destr); + auto_deallocate guard(static_cast< base_type* >(this), static_cast< node* >(dealloc), p); + value = boost::move(p->value()); + return true; + } + else + return false; + } + + // Copying and assignment is prohibited + BOOST_DELETED_FUNCTION(threadsafe_queue(threadsafe_queue const&)) + BOOST_DELETED_FUNCTION(threadsafe_queue& operator= (threadsafe_queue const&)) + +private: + //! Pointer to the implementation + threadsafe_queue_impl* m_pImpl; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_ diff --git a/boost/log/detail/timestamp.hpp b/boost/log/detail/timestamp.hpp new file mode 100644 index 0000000000..719061fb01 --- /dev/null +++ b/boost/log/detail/timestamp.hpp @@ -0,0 +1,99 @@ +/* + * 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 timestamp.hpp + * \author Andrey Semashev + * \date 31.07.2011 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_ + +#include <boost/cstdint.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +/*! + * Duration between two timestamps + */ +class duration +{ + int64_t m_ticks; + +public: + explicit duration(int64_t ticks = 0) : m_ticks(ticks) {} + +#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + int64_t milliseconds() const { return m_ticks; } +#else + BOOST_LOG_API int64_t milliseconds() const; +#endif +}; + +/*! + * Opaque timestamp class + */ +class timestamp +{ + uint64_t m_ticks; + +public: + explicit timestamp(uint64_t ticks = 0) : m_ticks(ticks) {} + + duration operator- (timestamp that) const + { + return duration(m_ticks - that.m_ticks); + } +}; + +/*! + * \fn get_timestamp + * + * The function returns a timestamp, in opaque units since an unspecified + * time point. This timer is guaranteed to be monotonic, it should not + * be affected by clock changes, either manual or seasonal. Also, it + * should be as fast as possible. + */ +#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +typedef uint64_t (__stdcall* get_tick_count_t)(); +extern BOOST_LOG_API get_tick_count_t get_tick_count; + +inline timestamp get_timestamp() +{ + return timestamp(get_tick_count()); +} + +#else + +typedef timestamp (*get_timestamp_t)(); +extern BOOST_LOG_API get_timestamp_t get_timestamp; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_ diff --git a/boost/log/detail/trivial_keyword.hpp b/boost/log/detail/trivial_keyword.hpp new file mode 100644 index 0000000000..d0e4f60713 --- /dev/null +++ b/boost/log/detail/trivial_keyword.hpp @@ -0,0 +1,43 @@ +/* + * 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 trivial_keyword.hpp + * \author Andrey Semashev + * \date 02.12.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace trivial { + +//! Trivial severity keyword +BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level) + +} // namespace trivial + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_ diff --git a/boost/log/detail/unary_function_terminal.hpp b/boost/log/detail/unary_function_terminal.hpp new file mode 100644 index 0000000000..f9a3412acf --- /dev/null +++ b/boost/log/detail/unary_function_terminal.hpp @@ -0,0 +1,142 @@ +/* + * 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 unary_function_terminal.hpp + * \author Andrey Semashev + * \date 21.07.2012 + * + * The header contains attribute value extractor adapter for constructing expression template terminals. + */ + +#ifndef BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/copy_cv.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +/*! + * \brief An adapter for a unary function to be used as a terminal in a Boost.Phoenix expression + * + * This class is an adapter between Boost.Phoenix expression invocation protocol and + * a unary function. It forwards the call to the base function, passing only the first argument + * from the original call. This allows to embed value extractors in template expressions. + */ +template< typename FunT > +class unary_function_terminal +{ +private: + //! Adopted function type + typedef FunT function_type; + //! Self type + typedef unary_function_terminal< function_type > this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Function result type + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< + typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type + >::type env_type; + typedef typename env_type::args_type args_type; + typedef typename boost::log::aux::copy_cv< ThisT, function_type >::type cv_function_type; + + typedef typename boost::result_of< cv_function_type(typename fusion::result_of::at_c< args_type, 0 >::type) >::type type; + }; + +private: + //! Adopted function + function_type m_fun; + +public: + //! Default constructor + BOOST_DEFAULTED_FUNCTION(unary_function_terminal(), {}) + //! Copy constructor + unary_function_terminal(unary_function_terminal const& that) : m_fun(that.m_fun) {} + //! Initializing constructor + template< typename ArgT1 > + explicit unary_function_terminal(ArgT1 const& arg1) : m_fun(arg1) {} + //! Initializing constructor + template< typename ArgT1, typename ArgT2 > + unary_function_terminal(ArgT1 const& arg1, ArgT2 const& arg2) : m_fun(arg1, arg2) {} + //! Initializing constructor + template< typename ArgT1, typename ArgT2, typename ArgT3 > + unary_function_terminal(ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3) : m_fun(arg1, arg2, arg3) {} + + //! The operator forwards the call to the base function + template< typename ContextT > + typename result< this_type(ContextT const&) >::type + operator() (ContextT const& ctx) + { + return m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args())); + } + + //! The operator forwards the call to the base function + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type + operator() (ContextT const& ctx) const + { + return m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args())); + } +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename FunT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::unary_function_terminal< FunT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_ diff --git a/boost/log/detail/unhandled_exception_count.hpp b/boost/log/detail/unhandled_exception_count.hpp new file mode 100644 index 0000000000..17866c3b36 --- /dev/null +++ b/boost/log/detail/unhandled_exception_count.hpp @@ -0,0 +1,40 @@ +/* + * 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 unhandled_exception_count.hpp + * \author Andrey Semashev + * \date 05.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Returns the number of currently pending exceptions +BOOST_LOG_API unsigned int unhandled_exception_count() BOOST_NOEXCEPT; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_ diff --git a/boost/log/detail/value_ref_visitation.hpp b/boost/log/detail/value_ref_visitation.hpp new file mode 100644 index 0000000000..795069d150 --- /dev/null +++ b/boost/log/detail/value_ref_visitation.hpp @@ -0,0 +1,107 @@ +/* + * 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 value_ref_visitation.hpp + * \author Andrey Semashev + * \date 28.07.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_ + +#include <boost/mpl/at.hpp> +#include <boost/mpl/begin.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/advance.hpp> +#include <boost/mpl/erase.hpp> +#include <boost/mpl/size.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifndef BOOST_LOG_VALUE_REF_VISITATION_UNROLL_COUNT +#define BOOST_LOG_VALUE_REF_VISITATION_UNROLL_COUNT 8 +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename SequenceT, typename VisitorT, unsigned int SizeV = mpl::size< SequenceT >::value > +struct apply_visitor_dispatch +{ + typedef typename VisitorT::result_type result_type; + + static BOOST_FORCEINLINE result_type call(const void* p, unsigned int type_index, VisitorT& visitor) + { + typedef typename mpl::begin< SequenceT >::type begin_type; + typedef typename mpl::advance_c< begin_type, SizeV / 2u >::type middle_type; + if (type_index < (SizeV / 2u)) + { + typedef typename mpl::erase< SequenceT, middle_type, typename mpl::end< SequenceT >::type >::type new_sequence; + typedef apply_visitor_dispatch< new_sequence, VisitorT > new_dispatch; + return new_dispatch::call(p, type_index, visitor); + } + else + { + typedef typename mpl::erase< SequenceT, begin_type, middle_type >::type new_sequence; + typedef apply_visitor_dispatch< new_sequence, VisitorT > new_dispatch; + return new_dispatch::call(p, type_index - (SizeV / 2u), visitor); + } + } +}; + +#define BOOST_LOG_AUX_CASE_ENTRY(z, i, data)\ + case i: return visitor(*static_cast< typename mpl::at_c< SequenceT, i >::type const* >(p)); + +#define BOOST_PP_FILENAME_1 <boost/log/detail/value_ref_visitation.hpp> +#define BOOST_PP_ITERATION_LIMITS (1, BOOST_PP_INC(BOOST_LOG_VALUE_REF_VISITATION_VTABLE_SIZE)) +#include BOOST_PP_ITERATE() + +#undef BOOST_LOG_AUX_CASE_ENTRY + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_ + +#ifdef BOOST_PP_IS_ITERATING + +#define BOOST_LOG_AUX_SWITCH_SIZE BOOST_PP_ITERATION() + +template< typename SequenceT, typename VisitorT > +struct apply_visitor_dispatch< SequenceT, VisitorT, BOOST_LOG_AUX_SWITCH_SIZE > +{ + typedef typename VisitorT::result_type result_type; + + static BOOST_FORCEINLINE result_type call(const void* p, unsigned int type_index, VisitorT& visitor) + { + switch (type_index) + { + BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_AUX_SWITCH_SIZE, BOOST_LOG_AUX_CASE_ENTRY, ~) + default: + return visitor(*static_cast< typename mpl::at_c< SequenceT, 0 >::type const* >(p)); + } + } +}; + +#undef BOOST_LOG_AUX_SWITCH_SIZE + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/log/detail/visible_type.hpp b/boost/log/detail/visible_type.hpp new file mode 100644 index 0000000000..2086278d42 --- /dev/null +++ b/boost/log/detail/visible_type.hpp @@ -0,0 +1,48 @@ +/* + * 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 visible_type.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The wrapper type whose type_info is always visible +template< typename T > +struct BOOST_SYMBOL_VISIBLE visible_type +{ + typedef T wrapped_type; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ diff --git a/boost/log/exceptions.hpp b/boost/log/exceptions.hpp new file mode 100644 index 0000000000..8171d0a3f0 --- /dev/null +++ b/boost/log/exceptions.hpp @@ -0,0 +1,387 @@ +/* + * 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 + * \author Andrey Semashev + * \date 31.10.2009 + * + * The header contains exception classes declarations. + */ + +#ifndef BOOST_LOG_EXCEPTIONS_HPP_INCLUDED_ +#define BOOST_LOG_EXCEPTIONS_HPP_INCLUDED_ + +#include <cstddef> +#include <string> +#include <stdexcept> +#include <boost/preprocessor/seq/enum.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/utility/type_info_wrapper.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +// Forward-declaration of an exception base class from Boost.Exception +#if defined(__GNUC__) +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma GCC visibility push (default) + +class exception; + +# pragma GCC visibility pop +# else + +class exception; + +# endif +#else + +class BOOST_SYMBOL_VISIBLE exception; + +#endif + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Attaches attribute name exception information +BOOST_LOG_API void attach_attribute_name_info(exception& e, attribute_name const& name); + +} // namespace aux + +/*! + * \brief Base class for runtime exceptions from the logging library + * + * Exceptions derived from this class indicate a problem that may not directly + * be caused by the user's code that interacts with the library, such as + * errors caused by input data. + */ +class BOOST_LOG_API runtime_error : + public std::runtime_error +{ +protected: + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit runtime_error(std::string const& descr); + /*! + * Destructor + */ + ~runtime_error() throw(); +}; + +/*! + * \brief Exception class that is used to indicate errors of missing values + */ +class BOOST_LOG_API missing_value : + public runtime_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + missing_value(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit missing_value(std::string const& descr); + /*! + * Destructor + */ + ~missing_value() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name); +#endif +}; + +/*! + * \brief Exception class that is used to indicate errors of incorrect type of an object + */ +class BOOST_LOG_API invalid_type : + public runtime_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + invalid_type(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit invalid_type(std::string const& descr); + /*! + * Destructor + */ + ~invalid_type() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, type_info_wrapper const& type); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, type_info_wrapper const& type); +#endif +}; + +/*! + * \brief Exception class that is used to indicate errors of incorrect value of an object + */ +class BOOST_LOG_API invalid_value : + public runtime_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + invalid_value(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit invalid_value(std::string const& descr); + /*! + * Destructor + */ + ~invalid_value() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +/*! + * \brief Exception class that is used to indicate parsing errors + */ +class BOOST_LOG_API parse_error : + public runtime_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + parse_error(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit parse_error(std::string const& descr); + /*! + * Destructor + */ + ~parse_error() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, std::size_t content_line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name); +#endif +}; + +/*! + * \brief Exception class that is used to indicate conversion errors + */ +class BOOST_LOG_API conversion_error : + public runtime_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + conversion_error(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit conversion_error(std::string const& descr); + /*! + * Destructor + */ + ~conversion_error() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +/*! + * \brief Exception class that is used to indicate underlying OS API errors + */ +class BOOST_LOG_API system_error : + public runtime_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + system_error(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit system_error(std::string const& descr); + /*! + * Destructor + */ + ~system_error() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +/*! + * \brief Base class for logic exceptions from the logging library + * + * Exceptions derived from this class usually indicate errors on the user's side, such as + * incorrect library usage. + */ +class BOOST_LOG_API logic_error : + public std::logic_error +{ +protected: + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit logic_error(std::string const& descr); + /*! + * Destructor + */ + ~logic_error() throw(); +}; + +/*! + * \brief Exception class that is used to indicate ODR violation + */ +class BOOST_LOG_API odr_violation : + public logic_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + odr_violation(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit odr_violation(std::string const& descr); + /*! + * Destructor + */ + ~odr_violation() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +/*! + * \brief Exception class that is used to indicate invalid call sequence + */ +class BOOST_LOG_API unexpected_call : + public logic_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + unexpected_call(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit unexpected_call(std::string const& descr); + /*! + * Destructor + */ + ~unexpected_call() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +/*! + * \brief Exception class that is used to indicate invalid library setup + */ +class BOOST_LOG_API setup_error : + public logic_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + setup_error(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit setup_error(std::string const& descr); + /*! + * Destructor + */ + ~setup_error() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +/*! + * \brief Exception class that is used to indicate library limitation + */ +class BOOST_LOG_API limitation_error : + public logic_error +{ +public: + /*! + * Default constructor. Creates an exception with the default error message. + */ + limitation_error(); + /*! + * Initializing constructor. Creates an exception with the specified error message. + */ + explicit limitation_error(std::string const& descr); + /*! + * Destructor + */ + ~limitation_error() throw(); + +#ifndef BOOST_LOG_DOXYGEN_PASS + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line); + static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr); +#endif +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_THROW(ex)\ + ex::throw_(__FILE__, static_cast< std::size_t >(__LINE__)) + +#define BOOST_LOG_THROW_DESCR(ex, descr)\ + ex::throw_(__FILE__, static_cast< std::size_t >(__LINE__), descr) + +#define BOOST_LOG_THROW_DESCR_PARAMS(ex, descr, params)\ + ex::throw_(__FILE__, static_cast< std::size_t >(__LINE__), descr, BOOST_PP_SEQ_ENUM(params)) + +#endif // BOOST_LOG_DOXYGEN_PASS + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXCEPTIONS_HPP_INCLUDED_ diff --git a/boost/log/expressions.hpp b/boost/log/expressions.hpp new file mode 100644 index 0000000000..990981a233 --- /dev/null +++ b/boost/log/expressions.hpp @@ -0,0 +1,38 @@ +/* + * 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 expressions.hpp + * \author Andrey Semashev + * \date 10.11.2012 + * + * This header includes other Boost.Log headers with all template expression tools. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/expressions/attr.hpp> +#include <boost/log/expressions/keyword.hpp> +#include <boost/log/expressions/message.hpp> +#include <boost/log/expressions/record.hpp> + +#include <boost/log/expressions/predicates.hpp> +#include <boost/log/expressions/formatters.hpp> + +#include <boost/log/expressions/filter.hpp> +#include <boost/log/expressions/formatter.hpp> + +// Boost.Phoenix operators are likely to be used with Boost.Log expression nodes anyway +#include <boost/phoenix/operator.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_EXPRESSIONS_HPP_INCLUDED_ diff --git a/boost/log/expressions/attr.hpp b/boost/log/expressions/attr.hpp new file mode 100644 index 0000000000..31deefc0a9 --- /dev/null +++ b/boost/log/expressions/attr.hpp @@ -0,0 +1,276 @@ +/* + * 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 attr.hpp + * \author Andrey Semashev + * \date 21.07.2012 + * + * The header contains implementation of a generic attribute placeholder in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/copy_cv.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/value_extraction.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * An attribute value extraction terminal + */ +template< typename T, typename FallbackPolicyT, typename TagT > +class attribute_terminal +{ +private: + //! Value extractor type + typedef value_extractor< T, FallbackPolicyT, TagT > value_extractor_type; + //! Self type + typedef attribute_terminal< T, FallbackPolicyT, TagT > this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Attribute tag type + typedef TagT tag_type; + //! Attribute value type + typedef typename value_extractor_type::value_type value_type; + //! Fallback policy type + typedef typename value_extractor_type::fallback_policy fallback_policy; + + //! Function result type + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< + typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type + >::type env_type; + typedef typename env_type::args_type args_type; + typedef typename boost::log::aux::copy_cv< ThisT, value_extractor_type >::type cv_value_extractor_type; + + typedef typename boost::result_of< cv_value_extractor_type(attribute_name const&, typename fusion::result_of::at_c< args_type, 0 >::type) >::type type; + }; + +private: + //! Attribute value name + const attribute_name m_name; + //! Attribute value extractor + value_extractor_type m_value_extractor; + +public: + /*! + * Initializing constructor + */ + explicit attribute_terminal(attribute_name const& name) : m_name(name) + { + } + + /*! + * Initializing constructor + */ + template< typename U > + attribute_terminal(attribute_name const& name, U const& arg) : m_name(name), m_value_extractor(arg) + { + } + + /*! + * \returns Attribute value name + */ + attribute_name get_name() const + { + return m_name; + } + + /*! + * \returns Fallback policy + */ + fallback_policy const& get_fallback_policy() const + { + return m_value_extractor.get_fallback_policy(); + } + + /*! + * The operator extracts attribute value + */ + template< typename ContextT > + typename result< this_type(ContextT const&) >::type + operator() (ContextT const& ctx) + { + return m_value_extractor(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args())); + } + + /*! + * The operator extracts attribute value + */ + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type + operator() (ContextT const& ctx) const + { + return m_value_extractor(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args())); + } + + BOOST_DELETED_FUNCTION(attribute_terminal()) +}; + +/*! + * An attribute value extraction terminal actor + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT > +class attribute_actor : + public ActorT< attribute_terminal< T, FallbackPolicyT, TagT > > +{ +public: + //! Attribute tag type + typedef TagT tag_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + //! Base terminal type + typedef attribute_terminal< T, fallback_policy, tag_type > terminal_type; + //! Attribute value type + typedef typename terminal_type::value_type value_type; + + //! Base actor type + typedef ActorT< terminal_type > base_type; + +public: + //! Initializing constructor + explicit attribute_actor(base_type const& act) : base_type(act) + { + } + + /*! + * \returns The attribute name + */ + attribute_name get_name() const + { + return this->proto_expr_.child0.get_name(); + } + + /*! + * \returns Fallback policy + */ + fallback_policy const& get_fallback_policy() const + { + return this->proto_expr_.child0.get_fallback_policy(); + } + + //! Expression with cached attribute name + typedef attribute_actor< value_type, fallback_to_none, tag_type, ActorT > or_none_result_type; + + //! Generates an expression that extracts the attribute value or a default value + or_none_result_type or_none() const + { + typedef typename or_none_result_type::terminal_type result_terminal; + typename or_none_result_type::base_type act = {{ result_terminal(get_name()) }}; + return or_none_result_type(act); + } + + //! Expression with cached attribute name + typedef attribute_actor< value_type, fallback_to_throw, tag_type, ActorT > or_throw_result_type; + + //! Generates an expression that extracts the attribute value or throws an exception + or_throw_result_type or_throw() const + { + typedef typename or_throw_result_type::terminal_type result_terminal; + typename or_throw_result_type::base_type act = {{ result_terminal(get_name()) }}; + return or_throw_result_type(act); + } + + //! Generates an expression that extracts the attribute value or a default value + template< typename DefaultT > + attribute_actor< value_type, fallback_to_default< DefaultT >, tag_type, ActorT > or_default(DefaultT const& def_val) const + { + typedef attribute_actor< value_type, fallback_to_default< DefaultT >, tag_type, ActorT > or_default_result_type; + typedef typename or_default_result_type::terminal_type result_terminal; + typename or_default_result_type::base_type act = {{ result_terminal(get_name(), def_val) }}; + return or_default_result_type(act); + } +}; + +/*! + * The function generates a terminal node in a template expression. The node will extract the value of the attribute + * with the specified name and type. + */ +template< typename AttributeValueT > +BOOST_FORCEINLINE attribute_actor< AttributeValueT > attr(attribute_name const& name) +{ + typedef attribute_actor< AttributeValueT > result_type; + typedef typename result_type::terminal_type result_terminal; + typename result_type::base_type act = {{ result_terminal(name) }}; + return result_type(act); +} + +/*! + * The function generates a terminal node in a template expression. The node will extract the value of the attribute + * with the specified name and type. + */ +template< typename AttributeValueT, typename TagT > +BOOST_FORCEINLINE attribute_actor< AttributeValueT, fallback_to_none, TagT > attr(attribute_name const& name) +{ + typedef attribute_actor< AttributeValueT, fallback_to_none, TagT > result_type; + typedef typename result_type::terminal_type result_terminal; + typename result_type::base_type act = {{ result_terminal(name) }}; + return result_type(act); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename T, typename FallbackPolicyT, typename TagT > +struct is_nullary< custom_terminal< boost::log::expressions::attribute_terminal< T, FallbackPolicyT, TagT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> +#if defined(BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_) +#include <boost/log/detail/attr_output_impl.hpp> +#endif + +#endif // BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_ diff --git a/boost/log/expressions/attr_fwd.hpp b/boost/log/expressions/attr_fwd.hpp new file mode 100644 index 0000000000..a8e7b92a81 --- /dev/null +++ b/boost/log/expressions/attr_fwd.hpp @@ -0,0 +1,69 @@ +/* + * 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 attr_fwd.hpp + * \author Andrey Semashev + * \date 21.07.2012 + * + * The header contains forward declaration of a generic attribute placeholder in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_ATTR_FWD_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_ATTR_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/fallback_policy_fwd.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +template< typename > +struct actor; + +} // namespace phoenix + +#endif + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * An attribute value extraction terminal + */ +template< + typename T, + typename FallbackPolicyT = fallback_to_none, + typename TagT = void +> +class attribute_terminal; + +/*! + * An attribute value extraction terminal actor + */ +template< + typename T, + typename FallbackPolicyT = fallback_to_none, + typename TagT = void, + template< typename > class ActorT = phoenix::actor +> +class attribute_actor; + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_EXPRESSIONS_ATTR_FWD_HPP_INCLUDED_ diff --git a/boost/log/expressions/filter.hpp b/boost/log/expressions/filter.hpp new file mode 100644 index 0000000000..dcf7d59cde --- /dev/null +++ b/boost/log/expressions/filter.hpp @@ -0,0 +1,183 @@ +/* + * 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 filter.hpp + * \author Andrey Semashev + * \date 13.07.2012 + * + * The header contains a filter function object definition. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * Log record filter function wrapper. + */ +class filter +{ + BOOST_COPYABLE_AND_MOVABLE(filter) + +public: + //! Result type + typedef bool result_type; + +private: + //! Filter function type + typedef boost::log::aux::light_function< bool (attribute_value_set const&) > filter_type; + + //! Default filter, always returns \c true + struct default_filter + { + typedef bool result_type; + result_type operator() (attribute_value_set const&) const { return true; } + }; + +private: + //! Filter function + filter_type m_Filter; + +public: + /*! + * Default constructor. Creates a filter that always returns \c true. + */ + filter() : m_Filter(default_filter()) + { + } + /*! + * Copy constructor + */ + filter(filter const& that) : m_Filter(that.m_Filter) + { + } + /*! + * Move constructor. The moved-from filter is left in an unspecified state. + */ + filter(BOOST_RV_REF(filter) that) BOOST_NOEXCEPT : m_Filter(boost::move(that.m_Filter)) + { + } + + /*! + * Initializing constructor. Creates a filter which will invoke the specified function object. + */ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + filter(FunT&& fun) : m_Filter(boost::forward< FunT >(fun)) + { + } +#elif !defined(BOOST_MSVC) || BOOST_MSVC > 1400 + template< typename FunT > + filter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Filter(fun) + { + } +#else + // MSVC 8 blows up in unexpected ways if we use SFINAE to disable constructor instantiation + template< typename FunT > + filter(FunT const& fun) : m_Filter(fun) + { + } + template< typename FunT > + filter(rv< FunT >& fun) : m_Filter(fun) + { + } + template< typename FunT > + filter(rv< FunT > const& fun) : m_Filter(static_cast< FunT const& >(fun)) + { + } + filter(rv< filter > const& that) : m_Filter(that.m_Filter) + { + } +#endif + + /*! + * Move assignment. The moved-from filter is left in an unspecified state. + */ + filter& operator= (BOOST_RV_REF(filter) that) BOOST_NOEXCEPT + { + m_Filter.swap(that.m_Filter); + return *this; + } + /*! + * Copy assignment. + */ + filter& operator= (BOOST_COPY_ASSIGN_REF(filter) that) + { + m_Filter = that.m_Filter; + return *this; + } + /*! + * Initializing assignment. Sets the specified function object to the filter. + */ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + filter& operator= (FunT const& fun) +#else + template< typename FunT > + typename disable_if< is_same< typename remove_cv< FunT >::type, filter >, filter& >::type + operator= (FunT const& fun) +#endif + { + filter(fun).swap(*this); + return *this; + } + + /*! + * Filtering operator. + * + * \param values Attribute values of the log record. + * \return \c true if the log record passes the filter, \c false otherwise. + */ + result_type operator() (attribute_value_set const& values) const + { + return m_Filter(values); + } + + /*! + * Resets the filter to the default. The default filter always returns \c true. + */ + void reset() + { + m_Filter = default_filter(); + } + + /*! + * Swaps two filters + */ + void swap(filter& that) BOOST_NOEXCEPT + { + m_Filter.swap(that.m_Filter); + } +}; + +inline void swap(filter& left, filter& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatter.hpp b/boost/log/expressions/formatter.hpp new file mode 100644 index 0000000000..05692ec287 --- /dev/null +++ b/boost/log/expressions/formatter.hpp @@ -0,0 +1,257 @@ +/* + * 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 formatter.hpp + * \author Andrey Semashev + * \date 13.07.2012 + * + * The header contains a formatter function object definition. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_ + +#include <boost/ref.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/utility/functional/bind_output.hpp> +#include <boost/log/expressions/message.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +// This reference class is a workaround for a Boost.Phoenix bug: https://svn.boost.org/trac/boost/ticket/9363 +// It is needed to pass output streams by non-const reference to function objects wrapped in phoenix::bind and phoenix::function. +// It's an implementation detail and will be removed when Boost.Phoenix is fixed. +template< typename StreamT > +class stream_ref : + public reference_wrapper< StreamT > +{ +public: + BOOST_FORCEINLINE explicit stream_ref(StreamT& strm) : reference_wrapper< StreamT >(strm) + { + } + + template< typename T > + BOOST_FORCEINLINE StreamT& operator<< (T& val) const + { + StreamT& strm = this->get(); + strm << val; + return strm; + } + + template< typename T > + BOOST_FORCEINLINE StreamT& operator<< (T const& val) const + { + StreamT& strm = this->get(); + strm << val; + return strm; + } +}; + +//! Default log record message formatter +struct message_formatter +{ + typedef void result_type; + + message_formatter() : m_MessageName(expressions::tag::message::get_name()) + { + } + + template< typename StreamT > + result_type operator() (record_view const& rec, StreamT& strm) const + { + boost::log::visit< expressions::tag::message::value_type >(m_MessageName, rec, boost::log::bind_output(strm)); + } + +private: + const attribute_name m_MessageName; +}; + +} // namespace aux + +} // namespace expressions + +/*! + * Log record formatter function wrapper. + */ +template< typename CharT > +class basic_formatter +{ + typedef basic_formatter this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + //! Result type + typedef void result_type; + + //! Character type + typedef CharT char_type; + //! Output stream type + typedef basic_formatting_ostream< char_type > stream_type; + +private: + //! Filter function type + typedef boost::log::aux::light_function< void (record_view const&, expressions::aux::stream_ref< stream_type >) > formatter_type; + +private: + //! Formatter function + formatter_type m_Formatter; + +public: + /*! + * Default constructor. Creates a formatter that only outputs log message. + */ + basic_formatter() : m_Formatter(expressions::aux::message_formatter()) + { + } + /*! + * Copy constructor + */ + basic_formatter(basic_formatter const& that) : m_Formatter(that.m_Formatter) + { + } + /*! + * Move constructor. The moved-from formatter is left in an unspecified state. + */ + basic_formatter(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_Formatter(boost::move(that.m_Formatter)) + { + } + + /*! + * Initializing constructor. Creates a formatter which will invoke the specified function object. + */ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + basic_formatter(FunT&& fun) : m_Formatter(boost::forward< FunT >(fun)) + { + } +#elif !defined(BOOST_MSVC) || BOOST_MSVC > 1400 + template< typename FunT > + basic_formatter(FunT const& fun, typename disable_if_c< move_detail::is_rv< FunT >::value, int >::type = 0) : m_Formatter(fun) + { + } +#else + // MSVC 8 blows up in unexpected ways if we use SFINAE to disable constructor instantiation + template< typename FunT > + basic_formatter(FunT const& fun) : m_Formatter(fun) + { + } + template< typename FunT > + basic_formatter(rv< FunT >& fun) : m_Formatter(fun) + { + } + template< typename FunT > + basic_formatter(rv< FunT > const& fun) : m_Formatter(static_cast< FunT const& >(fun)) + { + } + basic_formatter(rv< this_type > const& that) : m_Formatter(that.m_Formatter) + { + } +#endif + + /*! + * Move assignment. The moved-from formatter is left in an unspecified state. + */ + basic_formatter& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_Formatter.swap(that.m_Formatter); + return *this; + } + /*! + * Copy assignment. + */ + basic_formatter& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + m_Formatter = that.m_Formatter; + return *this; + } + /*! + * Initializing assignment. Sets the specified function object to the formatter. + */ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + basic_formatter& operator= (FunT&& fun) + { + this_type(boost::forward< FunT >(fun)).swap(*this); + return *this; + } +#else + template< typename FunT > + typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, this_type& >::type + operator= (FunT const& fun) + { + this_type(fun).swap(*this); + return *this; + } +#endif + + /*! + * Formatting operator. + * + * \param rec A log record to format. + * \param strm A stream to put the formatted characters to. + */ + result_type operator() (record_view const& rec, stream_type& strm) const + { + m_Formatter(rec, expressions::aux::stream_ref< stream_type >(strm)); + } + + /*! + * Resets the formatter to the default. The default formatter only outputs message text. + */ + void reset() + { + m_Formatter = expressions::aux::message_formatter(); + } + + /*! + * Swaps two formatters + */ + void swap(basic_formatter& that) BOOST_NOEXCEPT + { + m_Formatter.swap(that.m_Formatter); + } +}; + +template< typename CharT > +inline void swap(basic_formatter< CharT >& left, basic_formatter< CharT >& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_formatter< char > formatter; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_formatter< wchar_t > wformatter; +#endif + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTER_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters.hpp b/boost/log/expressions/formatters.hpp new file mode 100644 index 0000000000..47f84a516f --- /dev/null +++ b/boost/log/expressions/formatters.hpp @@ -0,0 +1,38 @@ +/* + * 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 formatters.hpp + * \author Andrey Semashev + * \date 10.11.2012 + * + * The header includes all template expression formatters. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/expressions/formatters/stream.hpp> +#include <boost/log/expressions/formatters/format.hpp> + +#include <boost/log/expressions/formatters/date_time.hpp> +#include <boost/log/expressions/formatters/named_scope.hpp> + +#include <boost/log/expressions/formatters/char_decorator.hpp> +#include <boost/log/expressions/formatters/xml_decorator.hpp> +#include <boost/log/expressions/formatters/csv_decorator.hpp> +#include <boost/log/expressions/formatters/c_decorator.hpp> + +#include <boost/log/expressions/formatters/if.hpp> +#include <boost/log/expressions/formatters/wrap_formatter.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/c_decorator.hpp b/boost/log/expressions/formatters/c_decorator.hpp new file mode 100644 index 0000000000..a793b52bfe --- /dev/null +++ b/boost/log/expressions/formatters/c_decorator.hpp @@ -0,0 +1,281 @@ +/* + * 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 formatters/c_decorator.hpp + * \author Andrey Semashev + * \date 18.11.2012 + * + * The header contains implementation of C-style character decorators. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_ + +#include <limits> +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/snprintf.hpp> +#include <boost/log/expressions/formatters/char_decorator.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename > +struct c_decorator_traits; + +#ifdef BOOST_LOG_USE_CHAR +template< > +struct c_decorator_traits< char > +{ + static boost::iterator_range< const char* const* > get_patterns() + { + static const char* const patterns[] = + { + "\\", "\a", "\b", "\f", "\n", "\r", "\t", "\v", "'", "\"", "?" + }; + return boost::make_iterator_range(patterns); + } + static boost::iterator_range< const char* const* > get_replacements() + { + static const char* const replacements[] = + { + "\\\\", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v", "\\'", "\\\"", "\\?" + }; + return boost::make_iterator_range(replacements); + } + template< unsigned int N > + static std::size_t print_escaped(char (&buf)[N], char c) + { + int n = boost::log::aux::snprintf(buf, N, "\\x%0.2X", static_cast< unsigned int >(static_cast< uint8_t >(c))); + if (n < 0) + { + n = 0; + buf[0] = '\0'; + } + return static_cast< unsigned int >(n) >= N ? N - 1 : static_cast< unsigned int >(n); + } +}; +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T +template< > +struct c_decorator_traits< wchar_t > +{ + static boost::iterator_range< const wchar_t* const* > get_patterns() + { + static const wchar_t* const patterns[] = + { + L"\\", L"\a", L"\b", L"\f", L"\n", L"\r", L"\t", L"\v", L"'", L"\"", L"?" + }; + return boost::make_iterator_range(patterns); + } + static boost::iterator_range< const wchar_t* const* > get_replacements() + { + static const wchar_t* const replacements[] = + { + L"\\\\", L"\\a", L"\\b", L"\\f", L"\\n", L"\\r", L"\\t", L"\\v", L"\\'", L"\\\"", L"\\?" + }; + return boost::make_iterator_range(replacements); + } + template< unsigned int N > + static std::size_t print_escaped(wchar_t (&buf)[N], wchar_t c) + { + const wchar_t* format; + unsigned int val; + if (sizeof(wchar_t) == 1) + { + format = L"\\x%0.2X"; + val = static_cast< uint8_t >(c); + } + else if (sizeof(wchar_t) == 2) + { + format = L"\\x%0.4X"; + val = static_cast< uint16_t >(c); + } + else + { + format = L"\\x%0.8X"; + val = static_cast< uint32_t >(c); + } + + int n = boost::log::aux::swprintf(buf, N, format, val); + if (n < 0) + { + n = 0; + buf[0] = L'\0'; + } + return static_cast< unsigned int >(n) >= N ? N - 1 : static_cast< unsigned int >(n); + } +}; +#endif // BOOST_LOG_USE_WCHAR_T + +template< typename CharT > +struct c_decorator_gen +{ + typedef CharT char_type; + + template< typename SubactorT > + BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const + { + typedef c_decorator_traits< char_type > traits_type; + typedef pattern_replacer< char_type > replacer_type; + typedef char_decorator_actor< SubactorT, replacer_type > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }}; + return result_type(act); + } +}; + +} // namespace aux + +/*! + * C-style decorator generator object. The decorator replaces characters with specific meaning in C + * language with the corresponding escape sequences. The generator provides <tt>operator[]</tt> that + * can be used to construct the actual decorator. For example: + * + * <code> + * c_decor[ attr< std::string >("MyAttr") ] + * </code> + * + * For wide-character formatting there is the similar \c wc_decor decorator generator object. + */ +#ifdef BOOST_LOG_USE_CHAR +const aux::c_decorator_gen< char > c_decor = {}; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +const aux::c_decorator_gen< wchar_t > wc_decor = {}; +#endif + +/*! + * The function creates a C-style decorator generator for arbitrary character type. + */ +template< typename CharT > +BOOST_FORCEINLINE aux::c_decorator_gen< CharT > make_c_decor() +{ + return aux::c_decorator_gen< CharT >(); +} + +/*! + * A character decorator implementation that escapes all non-prontable and non-ASCII characters + * in the output with C-style escape sequences. + */ +template< typename CharT > +class c_ascii_pattern_replacer : + public pattern_replacer< CharT > +{ +private: + //! Base type + typedef pattern_replacer< CharT > base_type; + +public: + //! Result type + typedef typename base_type::result_type result_type; + //! Character type + typedef typename base_type::char_type char_type; + //! String type + typedef typename base_type::string_type string_type; + +private: + //! Traits type + typedef aux::c_decorator_traits< char_type > traits_type; + +public: + //! Default constructor + c_ascii_pattern_replacer() : base_type(traits_type::get_patterns(), traits_type::get_replacements()) + { + } + + //! Applies string replacements starting from the specified position + result_type operator() (string_type& str, typename string_type::size_type start_pos = 0) const + { + base_type::operator() (str, start_pos); + + typedef typename string_type::iterator string_iterator; + for (string_iterator it = str.begin() + start_pos, end = str.end(); it != end; ++it) + { + char_type c = *it; + if (c < 0x20 || c > 0x7e) + { + char_type buf[(std::numeric_limits< char_type >::digits + 3) / 4 + 3]; + std::size_t n = traits_type::print_escaped(buf, c); + std::size_t pos = it - str.begin(); + str.replace(pos, 1, buf, n); + it = str.begin() + n - 1; + end = str.end(); + } + } + } +}; + +namespace aux { + +template< typename CharT > +struct c_ascii_decorator_gen +{ + typedef CharT char_type; + + template< typename SubactorT > + BOOST_FORCEINLINE char_decorator_actor< SubactorT, c_ascii_pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const + { + typedef c_decorator_traits< char_type > traits_type; + typedef c_ascii_pattern_replacer< char_type > replacer_type; + typedef char_decorator_actor< SubactorT, replacer_type > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(subactor, replacer_type()) }}; + return result_type(act); + } +}; + +} // namespace aux + +/*! + * C-style decorator generator object. Acts similarly to \c c_decor, except that \c c_ascii_decor also + * converts all non-ASCII and non-printable ASCII characters, except for space character, into + * C-style hexadecimal escape sequences. The generator provides <tt>operator[]</tt> that + * can be used to construct the actual decorator. For example: + * + * <code> + * c_ascii_decor[ attr< std::string >("MyAttr") ] + * </code> + * + * For wide-character formatting there is the similar \c wc_ascii_decor decorator generator object. + */ +#ifdef BOOST_LOG_USE_CHAR +const aux::c_ascii_decorator_gen< char > c_ascii_decor = {}; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +const aux::c_ascii_decorator_gen< wchar_t > wc_ascii_decor = {}; +#endif + +/*! + * The function creates a C-style decorator generator for arbitrary character type. + */ +template< typename CharT > +BOOST_FORCEINLINE aux::c_ascii_decorator_gen< CharT > make_c_ascii_decor() +{ + return aux::c_ascii_decorator_gen< CharT >(); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/char_decorator.hpp b/boost/log/expressions/formatters/char_decorator.hpp new file mode 100644 index 0000000000..ca24c0d486 --- /dev/null +++ b/boost/log/expressions/formatters/char_decorator.hpp @@ -0,0 +1,639 @@ +/* + * 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 formatters/char_decorator.hpp + * \author Andrey Semashev + * \date 17.11.2012 + * + * The header contains implementation of a character decorator. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_ + +#include <vector> +#include <string> +#include <iterator> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/size.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/range/value_type.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/meta_grammar.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/phoenix/support/vector.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/deduce_char_type.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename RangeT > +struct string_const_iterator : range_const_iterator< RangeT > {}; +template< > +struct string_const_iterator< char* > { typedef char* type; }; +template< > +struct string_const_iterator< const char* > { typedef const char* type; }; +template< > +struct string_const_iterator< wchar_t* > { typedef wchar_t* type; }; +template< > +struct string_const_iterator< const wchar_t* > { typedef const wchar_t* type; }; + +} // namespace aux + +/*! + * A simple character decorator implementation. This implementation replaces string patterns in the source string with + * the fixed replacements. Source patterns and replacements can be specified at the object construction. + */ +template< typename CharT > +class pattern_replacer +{ +public: + //! Result type + typedef void result_type; + + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + +private: + //! Lengths of source pattern and replacement + struct string_lengths + { + unsigned int from_len, to_len; + }; + + //! List of the decorations to apply + typedef std::vector< string_lengths > string_lengths_list; + +private: + //! Characters of the interleaved source patterns and replacements + string_type m_decoration_chars; + //! List of the decorations to apply + string_lengths_list m_string_lengths; + +public: + /*! + * Initializing constructor. Creates a pattern replacer with the specified \a decorations. + * The provided decorations must be a sequence of \c std::pair of strings. The first element + * of each pair is the source pattern, and the second one is the corresponding replacement. + */ + template< typename RangeT > + explicit pattern_replacer(RangeT const& decorations) + { + typedef typename range_const_iterator< RangeT >::type iterator; + for (iterator it = begin(decorations), end_ = end(decorations); it != end_; ++it) + { + string_lengths lens; + { + typedef typename aux::string_const_iterator< typename range_value< RangeT >::type::first_type >::type first_iterator; + first_iterator b = string_begin(it->first), e = string_end(it->first); + lens.from_len = static_cast< unsigned int >(std::distance(b, e)); + m_decoration_chars.append(b, e); + } + { + typedef typename aux::string_const_iterator< typename range_value< RangeT >::type::second_type >::type second_iterator; + second_iterator b = string_begin(it->second), e = string_end(it->second); + lens.to_len = static_cast< unsigned int >(std::distance(b, e)); + m_decoration_chars.append(b, e); + } + m_string_lengths.push_back(lens); + } + } + /*! + * Initializing constructor. Creates a pattern replacer with decorations specified + * in form of two same-sized string sequences. Each <tt>i</tt>'th decoration will be + * <tt>from[i]</tt> -> <tt>to[i]</tt>. + */ + template< typename FromRangeT, typename ToRangeT > + pattern_replacer(FromRangeT const& from, ToRangeT const& to) + { + typedef typename range_const_iterator< FromRangeT >::type iterator1; + typedef typename range_const_iterator< ToRangeT >::type iterator2; + iterator1 it1 = begin(from), end1 = end(from); + iterator2 it2 = begin(to), end2 = end(to); + for (; it1 != end1 && it2 != end2; ++it1, ++it2) + { + string_lengths lens; + { + typedef typename aux::string_const_iterator< typename range_value< FromRangeT >::type >::type from_iterator; + from_iterator b = string_begin(*it1), e = string_end(*it1); + lens.from_len = static_cast< unsigned int >(std::distance(b, e)); + m_decoration_chars.append(b, e); + } + { + typedef typename aux::string_const_iterator< typename range_value< ToRangeT >::type >::type to_iterator; + to_iterator b = string_begin(*it2), e = string_end(*it2); + lens.to_len = static_cast< unsigned int >(std::distance(b, e)); + m_decoration_chars.append(b, e); + } + m_string_lengths.push_back(lens); + } + + // Both sequences should be of the same size + BOOST_ASSERT(it1 == end1); + BOOST_ASSERT(it2 == end2); + } + //! Copy constructor + pattern_replacer(pattern_replacer const& that) : m_decoration_chars(that.m_decoration_chars), m_string_lengths(that.m_string_lengths) + { + } + + //! Applies string replacements starting from the specified position + result_type operator() (string_type& str, typename string_type::size_type start_pos = 0) const + { + typedef typename string_type::size_type size_type; + + const char_type* from_chars = m_decoration_chars.c_str(); + for (typename string_lengths_list::const_iterator it = m_string_lengths.begin(), end = m_string_lengths.end(); it != end; ++it) + { + const unsigned int from_len = it->from_len, to_len = it->to_len; + const char_type* const to_chars = from_chars + from_len; + for (size_type pos = str.find(from_chars, start_pos, from_len); pos != string_type::npos; pos = str.find(from_chars, pos, from_len)) + { + str.replace(pos, from_len, to_chars, to_len); + pos += to_len; + } + from_chars = to_chars + to_len; + } + } + +private: + static char_type* string_begin(char_type* p) + { + return p; + } + static const char_type* string_begin(const char_type* p) + { + return p; + } + template< typename RangeT > + static typename range_const_iterator< RangeT >::type string_begin(RangeT const& r) + { + return begin(r); + } + + static char_type* string_end(char_type* p) + { + while (*p) + ++p; + return p; + } + static const char_type* string_end(const char_type* p) + { + while (*p) + ++p; + return p; + } + template< typename RangeT > + static typename range_const_iterator< RangeT >::type string_end(RangeT const& r) + { + return end(r); + } +}; + +namespace aux { + +//! Character decorator stream output terminal +template< typename LeftT, typename SubactorT, typename ImplT > +class char_decorator_output_terminal +{ +private: + //! Self type + typedef char_decorator_output_terminal< LeftT, SubactorT, ImplT > this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Implementation type + typedef ImplT impl_type; + + //! Character type + typedef typename impl_type::char_type char_type; + //! String type + typedef typename impl_type::string_type string_type; + //! Adopted actor type + typedef SubactorT subactor_type; + + //! Result type definition + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; + typedef typename phoenix::evaluator::impl< + typename LeftT::proto_base_expr&, + context_type, + phoenix::unused + >::result_type type; + }; + +private: + //! Left argument actor + LeftT m_left; + //! Adopted formatter actor + subactor_type m_subactor; + //! Implementation type + impl_type m_impl; + +public: + /*! + * Initializing constructor. Creates decorator of the \a fmt formatter with the specified \a decorations. + */ + char_decorator_output_terminal(LeftT const& left, subactor_type const& sub, impl_type const& impl) : + m_left(left), m_subactor(sub), m_impl(impl) + { + } + /*! + * Copy constructor + */ + char_decorator_output_terminal(char_decorator_output_terminal const& that) : + m_left(that.m_left), m_subactor(that.m_subactor), m_impl(that.m_impl) + { + } + + /*! + * Invokation operator + */ + template< typename ContextT > + typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) + { + // Flush the stream and keep the current write position in the target string + typedef typename result< this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + strm.flush(); + typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size(); + + // Invoke the adopted formatter + typedef typename result< this_type(ContextT const&) >::type result_type; + phoenix::eval(m_subactor, ctx); + + // Flush the buffered characters and apply decorations + strm.flush(); + m_impl(*strm.rdbuf()->storage(), start_pos); + + return strm; + } + + /*! + * Invokation operator + */ + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const + { + // Flush the stream and keep the current write position in the target string + typedef typename result< const this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + strm.flush(); + typename string_type::size_type const start_pos = strm.rdbuf()->storage()->size(); + + // Invoke the adopted formatter + typedef typename result< const this_type(ContextT const&) >::type result_type; + phoenix::eval(m_subactor, ctx); + + // Flush the buffered characters and apply decorations + strm.flush(); + m_impl(*strm.rdbuf()->storage(), start_pos); + + return strm; + } + + BOOST_DELETED_FUNCTION(char_decorator_output_terminal()) +}; + +} // namespace aux + +/*! + * Character decorator terminal class. This formatter allows to modify strings generated by other + * formatters on character level. The most obvious application of decorators is replacing + * a certain set of characters with decorated equivalents to satisfy requirements of + * text-based sinks. + * + * The \c char_decorator_terminal class aggregates the formatter being decorated, and a set + * of string pairs that are used as decorations. All decorations are applied sequentially. + * The \c char_decorator_terminal class is a formatter itself, so it can be used to construct + * more complex formatters, including nesting decorators. + */ +template< typename SubactorT, typename ImplT > +class char_decorator_terminal +{ +private: + //! Self type + typedef char_decorator_terminal< SubactorT, ImplT > this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Implementation type + typedef ImplT impl_type; + //! Character type + typedef typename impl_type::char_type char_type; + //! String type + typedef typename impl_type::string_type string_type; + //! Stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Adopted actor type + typedef SubactorT subactor_type; + + //! Result type definition + typedef string_type result_type; + +private: + //! Adopted formatter actor + subactor_type m_subactor; + //! Implementation + impl_type m_impl; + +public: + /*! + * Initializing constructor. + */ + char_decorator_terminal(subactor_type const& sub, impl_type const& impl) : m_subactor(sub), m_impl(impl) + { + } + /*! + * Copy constructor + */ + char_decorator_terminal(char_decorator_terminal const& that) : m_subactor(that.m_subactor), m_impl(that.m_impl) + { + } + + /*! + * \returns Adopted subactor + */ + subactor_type const& get_subactor() const + { + return m_subactor; + } + + /*! + * \returns Implementation + */ + impl_type const& get_impl() const + { + return m_impl; + } + + /*! + * Invokation operator + */ + template< typename ContextT > + result_type operator() (ContextT const& ctx) + { + string_type str; + stream_type strm(str); + + // Invoke the adopted formatter + typedef phoenix::vector3< + subactor_type*, + typename fusion::result_of::at_c< + typename remove_cv< + typename remove_reference< + typename phoenix::result_of::env< ContextT const& >::type + >::type + >::type::args_type, + 0 + >::type, + stream_type& + > env_type; + env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm }; + phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx))); + + // Flush the buffered characters and apply decorations + strm.flush(); + m_impl(*strm.rdbuf()->storage()); + + return boost::move(str); + } + + /*! + * Invokation operator + */ + template< typename ContextT > + result_type operator() (ContextT const& ctx) const + { + string_type str; + stream_type strm(str); + + // Invoke the adopted formatter + typedef phoenix::vector3< + const subactor_type*, + typename fusion::result_of::at_c< + typename remove_cv< + typename remove_reference< + typename phoenix::result_of::env< ContextT const& >::type + >::type + >::type::args_type, + 0 + >::type, + stream_type& + > env_type; + env_type env = { boost::addressof(m_subactor), fusion::at_c< 0 >(phoenix::env(ctx).args()), strm }; + phoenix::eval(m_subactor, phoenix::make_context(env, phoenix::actions(ctx))); + + // Flush the buffered characters and apply decorations + strm.flush(); + m_impl(*strm.rdbuf()->storage()); + + return boost::move(str); + } + + BOOST_DELETED_FUNCTION(char_decorator_terminal()) +}; + +/*! + * Character decorator actor + */ +template< typename SubactorT, typename ImplT, template< typename > class ActorT = phoenix::actor > +class char_decorator_actor : + public ActorT< char_decorator_terminal< SubactorT, ImplT > > +{ +public: + //! Base terminal type + typedef char_decorator_terminal< SubactorT, ImplT > terminal_type; + //! Character type + typedef typename terminal_type::char_type char_type; + + //! Base actor type + typedef ActorT< terminal_type > base_type; + +public: + //! Initializing constructor + explicit char_decorator_actor(base_type const& act) : base_type(act) + { + } + + //! Returns reference to the terminal + terminal_type const& get_terminal() const + { + return this->proto_expr_.child0; + } +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename SubactorT, typename ImplT, template< typename > class ActorT >\ + BOOST_FORCEINLINE phoenix::actor< aux::char_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, ImplT > >\ + operator<< (phoenix::actor< LeftExprT > left_ref left, char_decorator_actor< SubactorT, ImplT, ActorT > right_ref right)\ + {\ + typedef aux::char_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, ImplT > terminal_type;\ + phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_terminal().get_subactor(), right.get_terminal().get_impl()) }};\ + return actor;\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +#endif // BOOST_LOG_DOXYGEN_PASS + +namespace aux { + +template< typename RangeT > +class char_decorator_gen1 +{ + RangeT const& m_decorations; + + typedef typename boost::log::aux::deduce_char_type< typename range_value< RangeT >::type::first_type >::type char_type; + +public: + explicit char_decorator_gen1(RangeT const& decorations) : m_decorations(decorations) + { + } + + template< typename SubactorT > + BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const + { + typedef pattern_replacer< char_type > replacer_type; + typedef char_decorator_actor< SubactorT, replacer_type > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(m_decorations)) }}; + return result_type(act); + } +}; + +template< typename FromRangeT, typename ToRangeT > +class char_decorator_gen2 +{ + FromRangeT const& m_from; + ToRangeT const& m_to; + + typedef typename boost::log::aux::deduce_char_type< typename range_value< FromRangeT >::type >::type from_char_type; + typedef typename boost::log::aux::deduce_char_type< typename range_value< ToRangeT >::type >::type to_char_type; + BOOST_STATIC_ASSERT_MSG((is_same< from_char_type, to_char_type >::value), "Boost.Log: character decorator cannot be instantiated with different character types for source and replacement strings"); + +public: + char_decorator_gen2(FromRangeT const& from, ToRangeT const& to) : m_from(from), m_to(to) + { + } + + template< typename SubactorT > + BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< from_char_type > > operator[] (SubactorT const& subactor) const + { + typedef pattern_replacer< from_char_type > replacer_type; + typedef char_decorator_actor< SubactorT, replacer_type > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(m_from, m_to)) }}; + return result_type(act); + } +}; + +} // namespace aux + +/*! + * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used + * to construct the actual decorator. + * + * \param decorations A sequence of string pairs that will be used as decorations. Every <tt>decorations[i].first</tt> + * substring occurrence in the output will be replaced with <tt>decorations[i].second</tt>. + */ +template< typename RangeT > +BOOST_FORCEINLINE aux::char_decorator_gen1< RangeT > char_decor(RangeT const& decorations) +{ + return aux::char_decorator_gen1< RangeT >(decorations); +} + +/*! + * The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used + * to construct the actual decorator. + * + * \param from A sequence of strings that will be sought in the output. + * \param to A sequence of strings that will be used as replacements. + * + * \note The \a from and \a to sequences mush be of the same size. Every <tt>from[i]</tt> + * substring occurrence in the output will be replaced with <tt>to[i]</tt>. + */ +template< typename FromRangeT, typename ToRangeT > +BOOST_FORCEINLINE aux::char_decorator_gen2< FromRangeT, ToRangeT > char_decor(FromRangeT const& from, ToRangeT const& to) +{ + return aux::char_decorator_gen2< FromRangeT, ToRangeT >(from, to); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename SubactorT, typename ImplT > +struct is_nullary< custom_terminal< boost::log::expressions::char_decorator_terminal< SubactorT, ImplT > > > : + public mpl::false_ +{ +}; + +template< typename LeftT, typename SubactorT, typename ImplT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::char_decorator_output_terminal< LeftT, SubactorT, ImplT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_CHAR_DECORATOR_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/csv_decorator.hpp b/boost/log/expressions/formatters/csv_decorator.hpp new file mode 100644 index 0000000000..8c964a0d13 --- /dev/null +++ b/boost/log/expressions/formatters/csv_decorator.hpp @@ -0,0 +1,140 @@ +/* + * 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 formatters/csv_decorator.hpp + * \author Andrey Semashev + * \date 18.11.2012 + * + * The header contains implementation of a CSV-style character decorator. + * See: http://en.wikipedia.org/wiki/Comma-separated_values + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_CSV_DECORATOR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_CSV_DECORATOR_HPP_INCLUDED_ + +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/expressions/formatters/char_decorator.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename > +struct csv_decorator_traits; + +#ifdef BOOST_LOG_USE_CHAR +template< > +struct csv_decorator_traits< char > +{ + static boost::iterator_range< const char* const* > get_patterns() + { + static const char* const patterns[] = + { + "\"" + }; + return boost::make_iterator_range(patterns); + } + static boost::iterator_range< const char* const* > get_replacements() + { + static const char* const replacements[] = + { + "\"\"" + }; + return boost::make_iterator_range(replacements); + } +}; +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T +template< > +struct csv_decorator_traits< wchar_t > +{ + static boost::iterator_range< const wchar_t* const* > get_patterns() + { + static const wchar_t* const patterns[] = + { + L"\"" + }; + return boost::make_iterator_range(patterns); + } + static boost::iterator_range< const wchar_t* const* > get_replacements() + { + static const wchar_t* const replacements[] = + { + L"\"\"" + }; + return boost::make_iterator_range(replacements); + } +}; +#endif // BOOST_LOG_USE_WCHAR_T + +template< typename CharT > +struct csv_decorator_gen +{ + typedef CharT char_type; + + template< typename SubactorT > + BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const + { + typedef csv_decorator_traits< char_type > traits_type; + typedef pattern_replacer< char_type > replacer_type; + typedef char_decorator_actor< SubactorT, replacer_type > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }}; + return result_type(act); + } +}; + +} // namespace aux + +/*! + * CSV-style decorator generator object. The decorator doubles double quotes that may be found + * in the output. See http://en.wikipedia.org/wiki/Comma-separated_values for more information on + * the CSV format. The generator provides <tt>operator[]</tt> that can be used to construct + * the actual decorator. For example: + * + * <code> + * csv_decor[ attr< std::string >("MyAttr") ] + * </code> + * + * For wide-character formatting there is the similar \c wcsv_decor decorator generator object. + */ +#ifdef BOOST_LOG_USE_CHAR +const aux::csv_decorator_gen< char > csv_decor = {}; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +const aux::csv_decorator_gen< wchar_t > wcsv_decor = {}; +#endif + +/*! + * The function creates an CSV-style decorator generator for arbitrary character type. + */ +template< typename CharT > +BOOST_FORCEINLINE aux::csv_decorator_gen< CharT > make_csv_decor() +{ + return aux::csv_decorator_gen< CharT >(); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_CSV_DECORATOR_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/date_time.hpp b/boost/log/expressions/formatters/date_time.hpp new file mode 100644 index 0000000000..0ff6b680e6 --- /dev/null +++ b/boost/log/expressions/formatters/date_time.hpp @@ -0,0 +1,343 @@ +/* + * 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 formatters/date_time.hpp + * \author Andrey Semashev + * \date 16.09.2012 + * + * The header contains a formatter function for date and time attribute values. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_ + +#include <string> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/date_time_fmt_gen_traits_fwd.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/attr_output_terminal.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * Date and time formatter terminal. + */ +template< typename T, typename FallbackPolicyT, typename CharT > +class format_date_time_terminal +{ +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Attribute value type + typedef T value_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + + //! Formatter function + typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; + + //! Function result type + typedef string_type result_type; + +private: + //! Formatter generator traits + typedef aux::date_time_formatter_generator_traits< value_type, char_type > formatter_generator; + //! Attribute value visitor invoker + typedef value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type; + +private: + //! Attribute name + attribute_name m_name; + //! Formattr function + formatter_function_type m_formatter; + //! Attribute value visitor invoker + visitor_invoker_type m_visitor_invoker; + +public: + //! Initializing constructor + format_date_time_terminal(attribute_name const& name, fallback_policy const& fallback, string_type const& format) : + m_name(name), m_formatter(formatter_generator::parse(format)), m_visitor_invoker(fallback) + { + } + //! Copy constructor + format_date_time_terminal(format_date_time_terminal const& that) : + m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker) + { + } + + //! Returns attribute name + attribute_name get_name() const + { + return m_name; + } + + //! Returns fallback policy + fallback_policy const& get_fallback_policy() const + { + return m_visitor_invoker.get_fallback_policy(); + } + + //! Retruns formatter function + formatter_function_type const& get_formatter_function() const + { + return m_formatter; + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) + { + string_type str; + stream_type strm(str); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm)); + strm.flush(); + return boost::move(str); + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) const + { + string_type str; + stream_type strm(str); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm)); + strm.flush(); + return boost::move(str); + } + + BOOST_DELETED_FUNCTION(format_date_time_terminal()) +}; + +/*! + * Date and time formatter actor. + */ +template< typename T, typename FallbackPolicyT, typename CharT, template< typename > class ActorT = phoenix::actor > +class format_date_time_actor : + public ActorT< format_date_time_terminal< T, FallbackPolicyT, CharT > > +{ +public: + //! Attribute value type + typedef T value_type; + //! Character type + typedef CharT char_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + //! Base terminal type + typedef format_date_time_terminal< value_type, fallback_policy, char_type > terminal_type; + //! Formatter function + typedef typename terminal_type::formatter_function_type formatter_function_type; + + //! Base actor type + typedef ActorT< terminal_type > base_type; + +public: + //! Initializing constructor + explicit format_date_time_actor(base_type const& act) : base_type(act) + { + } + + /*! + * \returns The attribute name + */ + attribute_name get_name() const + { + return this->proto_expr_.child0.get_name(); + } + + /*! + * \returns Fallback policy + */ + fallback_policy const& get_fallback_policy() const + { + return this->proto_expr_.child0.get_fallback_policy(); + } + + /*! + * \returns Formatter function + */ + formatter_function_type const& get_formatter_function() const + { + return this->proto_expr_.child0.get_formatter_function(); + } +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename T, typename FallbackPolicyT, typename CharT >\ + BOOST_FORCEINLINE phoenix::actor< aux::attribute_output_terminal< phoenix::actor< LeftExprT >, T, FallbackPolicyT, typename format_date_time_actor< T, FallbackPolicyT, CharT >::formatter_function_type > >\ + operator<< (phoenix::actor< LeftExprT > left_ref left, format_date_time_actor< T, FallbackPolicyT, CharT > right_ref right)\ + {\ + typedef aux::attribute_output_terminal< phoenix::actor< LeftExprT >, T, FallbackPolicyT, typename format_date_time_actor< T, FallbackPolicyT, CharT >::formatter_function_type > terminal_type;\ + phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_name(), right.get_formatter_function(), right.get_fallback_policy()) }};\ + return actor;\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param name Attribute name + * \param format Format string + */ +template< typename AttributeValueT, typename CharT > +BOOST_FORCEINLINE format_date_time_actor< AttributeValueT, fallback_to_none, CharT > format_date_time(attribute_name const& name, const CharT* format) +{ + typedef format_date_time_actor< AttributeValueT, fallback_to_none, CharT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param name Attribute name + * \param format Format string + */ +template< typename AttributeValueT, typename CharT > +BOOST_FORCEINLINE format_date_time_actor< AttributeValueT, fallback_to_none, CharT > format_date_time(attribute_name const& name, std::basic_string< CharT > const& format) +{ + typedef format_date_time_actor< AttributeValueT, fallback_to_none, CharT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param keyword Attribute keyword + * \param format Format string + */ +template< typename DescriptorT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > +format_date_time(attribute_keyword< DescriptorT, ActorT > const& keyword, const CharT* format) +{ + typedef format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param keyword Attribute keyword + * \param format Format string + */ +template< typename DescriptorT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > +format_date_time(attribute_keyword< DescriptorT, ActorT > const& keyword, std::basic_string< CharT > const& format) +{ + typedef format_date_time_actor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param placeholder Attribute placeholder + * \param format Format string + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_date_time_actor< T, FallbackPolicyT, CharT, ActorT > +format_date_time(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, const CharT* format) +{ + typedef format_date_time_actor< T, FallbackPolicyT, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param placeholder Attribute placeholder + * \param format Format string + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_date_time_actor< T, FallbackPolicyT, CharT, ActorT > +format_date_time(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, std::basic_string< CharT > const& format) +{ + typedef format_date_time_actor< T, FallbackPolicyT, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), format) }}; + return actor_type(act); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename T, typename FallbackPolicyT, typename CharT > +struct is_nullary< custom_terminal< boost::log::expressions::format_date_time_terminal< T, FallbackPolicyT, CharT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_DATE_TIME_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/format.hpp b/boost/log/expressions/formatters/format.hpp new file mode 100644 index 0000000000..c5d7917453 --- /dev/null +++ b/boost/log/expressions/formatters/format.hpp @@ -0,0 +1,128 @@ +/* + * 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 formatters/format.hpp + * \author Andrey Semashev + * \date 15.11.2012 + * + * The header contains a generic log record formatter function. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_FORMAT_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_FORMAT_HPP_INCLUDED_ + +#include <string> +#include <boost/mpl/bool.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/format.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * \brief Template expressions terminal node with Boost.Format-like formatter + */ +template< typename CharT > +class format_terminal +{ +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Character type + typedef CharT char_type; + //! Boost.Format formatter type + typedef boost::log::aux::basic_format< char_type > format_type; + //! String type + typedef std::basic_string< char_type > string_type; + + //! Terminal result type + typedef typename format_type::pump result_type; + +private: + //! Formatter object + mutable format_type m_format; + +public: + //! Initializing constructor + explicit format_terminal(const char_type* format) : m_format(format) {} + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) const + { + return m_format.make_pump(fusion::at_c< 1 >(phoenix::env(ctx).args())); + } + + BOOST_DELETED_FUNCTION(format_terminal()) +}; + +/*! + * The function generates a terminal node in a template expression. The node will perform log record formatting + * according to the provided format string. + */ +template< typename CharT > +BOOST_FORCEINLINE phoenix::actor< format_terminal< CharT > > format(const CharT* fmt) +{ + typedef format_terminal< CharT > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(fmt) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will perform log record formatting + * according to the provided format string. + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_FORCEINLINE phoenix::actor< format_terminal< CharT > > format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt) +{ + typedef format_terminal< CharT > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(fmt.c_str()) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename CharT > +struct is_nullary< custom_terminal< boost::log::expressions::format_terminal< CharT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_FORMAT_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/if.hpp b/boost/log/expressions/formatters/if.hpp new file mode 100644 index 0000000000..0985439761 --- /dev/null +++ b/boost/log/expressions/formatters/if.hpp @@ -0,0 +1,315 @@ +/* + * 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 formatters/if.hpp + * \author Andrey Semashev + * \date 17.11.2012 + * + * The header contains implementation of a conditional formatter. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/meta_grammar.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename LeftT, typename CondT, typename ThenT > +class if_output_terminal +{ +private: + //! Self type + typedef if_output_terminal this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Result type definition + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; + typedef typename phoenix::evaluator::impl< + typename LeftT::proto_base_expr&, + context_type, + phoenix::unused + >::result_type type; + }; + +private: + //! Left argument actor + LeftT m_left; + //! Condition expression + CondT m_cond; + //! Positive branch + ThenT m_then; + +public: + //! Initializing constructor + if_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_) : m_left(left), m_cond(cond), m_then(then_) + { + } + + //! Invokation operator + template< typename ContextT > + typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) + { + typedef typename result< this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + if (phoenix::eval(m_cond, ctx)) + phoenix::eval(m_then, ctx); + return strm; + } + + //! Invokation operator + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const + { + typedef typename result< const this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + if (phoenix::eval(m_cond, ctx)) + phoenix::eval(m_then, ctx); + return strm; + } + + BOOST_DELETED_FUNCTION(if_output_terminal()) +}; + +template< typename LeftT, typename CondT, typename ThenT, typename ElseT > +class if_else_output_terminal +{ +private: + //! Self type + typedef if_else_output_terminal this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Result type definition + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; + typedef typename phoenix::evaluator::impl< + typename LeftT::proto_base_expr&, + context_type, + phoenix::unused + >::result_type type; + }; + +private: + //! Left argument actor + LeftT m_left; + //! Condition expression + CondT m_cond; + //! Positive branch + ThenT m_then; + //! Negative branch + ElseT m_else; + +public: + //! Initializing constructor + if_else_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_, ElseT const& else_) : m_left(left), m_cond(cond), m_then(then_), m_else(else_) + { + } + + //! Invokation operator + template< typename ContextT > + typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) + { + typedef typename result< this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + if (phoenix::eval(m_cond, ctx)) + phoenix::eval(m_then, ctx); + else + phoenix::eval(m_else, ctx); + return strm; + } + + //! Invokation operator + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const + { + typedef typename result< const this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + if (phoenix::eval(m_cond, ctx)) + phoenix::eval(m_then, ctx); + else + phoenix::eval(m_else, ctx); + return strm; + } + + BOOST_DELETED_FUNCTION(if_else_output_terminal()) +}; + + +template< typename CondT, typename ThenT, typename ElseT > +struct if_then_else_gen +{ + CondT m_cond; + ThenT m_then; + ElseT m_else; + + if_then_else_gen(CondT const& cond, ThenT const& then_, ElseT const& else_) : m_cond(cond), m_then(then_), m_else(else_) + { + } +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename CondT, typename ThenT, typename ElseT >\ + BOOST_FORCEINLINE phoenix::actor< if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > >\ + operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_else_gen< CondT, ThenT, ElseT > right_ref right)\ + {\ + typedef if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > terminal_type;\ + phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.m_cond, right.m_then, right.m_else) }};\ + return actor;\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +#endif // BOOST_LOG_DOXYGEN_PASS + +template< typename CondT, typename ThenT > +struct if_then_gen +{ + struct else_gen + { + CondT m_cond; + ThenT m_then; + + else_gen(CondT const& cond, ThenT const& then_) : m_cond(cond), m_then(then_) + { + } + + template< typename ElseT > + BOOST_FORCEINLINE if_then_else_gen< CondT, ThenT, ElseT > operator[] (ElseT const& el) + { + return if_then_else_gen< CondT, ThenT, ElseT >(m_cond, m_then, el); + } + } + else_; + + if_then_gen(CondT const& cond, ThenT const& then_) : else_(cond, then_) {} +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename CondT, typename ThenT >\ + BOOST_FORCEINLINE phoenix::actor< if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > >\ + operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_gen< CondT, ThenT > right_ref right)\ + {\ + typedef if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > terminal_type;\ + phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.else_.m_cond, right.else_.m_then) }};\ + return actor;\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +#endif // BOOST_LOG_DOXYGEN_PASS + +template< typename CondT > +class if_gen +{ +private: + CondT const& m_cond; + +public: + explicit if_gen(CondT const& cond) : m_cond(cond) + { + } + + template< typename ThenT > + BOOST_FORCEINLINE if_then_gen< CondT, ThenT > operator[] (ThenT const& then_) const + { + return if_then_gen< CondT, ThenT >(m_cond, then_); + } +}; + +} // namespace aux + +/*! + * The function returns a conditional formatter generator object. The generator provides <tt>operator[]</tt> that can be used + * to construct the actual formatter. The formatter must participate in a streaming expression. + * + * \param cond A filter expression that will be used as the condition + */ +template< typename CondT > +BOOST_FORCEINLINE aux::if_gen< CondT > if_(CondT const& cond) +{ + return aux::if_gen< CondT >(cond); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename LeftT, typename CondT, typename ThenT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::if_output_terminal< LeftT, CondT, ThenT > > > : + public mpl::false_ +{ +}; + +template< typename LeftT, typename CondT, typename ThenT, typename ElseT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::if_else_output_terminal< LeftT, CondT, ThenT, ElseT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/named_scope.hpp b/boost/log/expressions/formatters/named_scope.hpp new file mode 100644 index 0000000000..2225e00ec9 --- /dev/null +++ b/boost/log/expressions/formatters/named_scope.hpp @@ -0,0 +1,653 @@ +/* + * 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 formatters/named_scope.hpp + * \author Andrey Semashev + * \date 11.11.2012 + * + * The header contains a formatter function for named scope attribute values. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_ + +#include <string> +#include <iterator> +#include <utility> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/parameter/binding.hpp> +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/attributes/named_scope.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/deduce_char_type.hpp> +#include <boost/log/detail/attr_output_terminal.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/utility/string_literal_fwd.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/keywords/format.hpp> +#include <boost/log/keywords/delimiter.hpp> +#include <boost/log/keywords/depth.hpp> +#include <boost/log/keywords/iteration.hpp> +#include <boost/log/keywords/empty_marker.hpp> +#include <boost/log/keywords/incomplete_marker.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +//! Scope iteration directions +enum scope_iteration_direction +{ + forward, //!< Iterate through scopes from outermost to innermost + reverse //!< Iterate through scopes from innermost to outermost +}; + +namespace aux { + +#ifdef BOOST_LOG_USE_CHAR +//! Parses the named scope format string and constructs the formatter function +BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< char >&, attributes::named_scope::value_type::value_type const&) > +parse_named_scope_format(const char* begin, const char* end); +#endif + +#ifdef BOOST_LOG_USE_WCHAR_T +//! Parses the named scope format string and constructs the formatter function +BOOST_LOG_API boost::log::aux::light_function< void (basic_formatting_ostream< wchar_t >&, attributes::named_scope::value_type::value_type const&) > +parse_named_scope_format(const wchar_t* begin, const wchar_t* end); +#endif + +//! Parses the named scope format string and constructs the formatter function +template< typename CharT > +inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) > +parse_named_scope_format(const CharT* format) +{ + return parse_named_scope_format(format, format + std::char_traits< CharT >::length(format)); +} + +//! Parses the named scope format string and constructs the formatter function +template< typename CharT, typename TraitsT, typename AllocatorT > +inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) > +parse_named_scope_format(std::basic_string< CharT, TraitsT, AllocatorT > const& format) +{ + const CharT* p = format.c_str(); + return parse_named_scope_format(p, p + format.size()); +} + +//! Parses the named scope format string and constructs the formatter function +template< typename CharT, typename TraitsT > +inline boost::log::aux::light_function< void (basic_formatting_ostream< CharT >&, attributes::named_scope::value_type::value_type const&) > +parse_named_scope_format(basic_string_literal< CharT, TraitsT > const& format) +{ + const CharT* p = format.c_str(); + return parse_named_scope_format(p, p + format.size()); +} + +template< typename CharT > +class format_named_scope_impl +{ +public: + //! Function result type + typedef void result_type; + + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Attribute value type + typedef attributes::named_scope::value_type value_type; + //! Named scope formatter + typedef boost::log::aux::light_function< void (stream_type&, value_type::value_type const&) > element_formatter_type; + +private: + //! Element formatting function + element_formatter_type m_element_formatter; + //! Element delimiter + string_type m_delimiter; + //! Incomplete list marker + string_type m_incomplete_marker; + //! Empty list marker + string_type m_empty_marker; + //! Maximum number of elements to output + value_type::size_type m_depth; + //! Iteration direction + scope_iteration_direction m_direction; + +public: + //! Initializing constructor + format_named_scope_impl + ( + element_formatter_type const& element_formatter, + string_type const& delimiter, + string_type const& incomplete_marker, + string_type const& empty_marker, + value_type::size_type depth, + scope_iteration_direction direction + ) : + m_element_formatter(element_formatter), + m_delimiter(delimiter), + m_incomplete_marker(incomplete_marker), + m_empty_marker(empty_marker), + m_depth(depth), + m_direction(direction) + { + } + //! Copy constructor + format_named_scope_impl(format_named_scope_impl const& that) : + m_element_formatter(that.m_element_formatter), + m_delimiter(that.m_delimiter), + m_incomplete_marker(that.m_incomplete_marker), + m_empty_marker(that.m_empty_marker), + m_depth(that.m_depth), + m_direction(that.m_direction) + { + } + + //! Formatting operator + result_type operator() (stream_type& strm, value_type const& scopes) const + { + if (!scopes.empty()) + { + if (m_direction == expressions::forward) + format_forward(strm, scopes); + else + format_reverse(strm, scopes); + } + else + { + strm << m_empty_marker; + } + } + +private: + //! The function performs formatting of the extracted scope stack in forward direction + void format_forward(stream_type& strm, value_type const& scopes) const + { + value_type::const_iterator it, end = scopes.end(); + if (m_depth > 0) + { + value_type::size_type const scopes_to_iterate = (std::min)(m_depth, scopes.size()); + it = scopes.end(); + std::advance(it, -static_cast< value_type::difference_type >(scopes_to_iterate)); + } + else + { + it = scopes.begin(); + } + + if (it != end) + { + if (it != scopes.begin()) + strm << m_incomplete_marker; + + m_element_formatter(strm, *it); + for (++it; it != end; ++it) + { + strm << m_delimiter; + m_element_formatter(strm, *it); + } + } + } + //! The function performs formatting of the extracted scope stack in reverse direction + void format_reverse(stream_type& strm, value_type const& scopes) const + { + value_type::const_reverse_iterator it = scopes.rbegin(), end; + if (m_depth > 0) + { + value_type::size_type const scopes_to_iterate = (std::min)(m_depth, scopes.size()); + end = it; + std::advance(end, static_cast< value_type::difference_type >(scopes_to_iterate)); + } + else + { + end = scopes.rend(); + } + + if (it != end) + { + m_element_formatter(strm, *it); + for (++it; it != end; ++it) + { + strm << m_delimiter; + m_element_formatter(strm, *it); + } + + if (it != scopes.rend()) + strm << m_incomplete_marker; + } + } +}; + +} // namespace aux + +/*! + * Named scope formatter terminal. + */ +template< typename FallbackPolicyT, typename CharT > +class format_named_scope_terminal +{ +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Attribute value type + typedef attributes::named_scope::value_type value_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Formatter function + typedef aux::format_named_scope_impl< char_type > formatter_function_type; + + //! Function result type + typedef string_type result_type; + +private: + //! Attribute value visitor invoker + typedef value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type; + +private: + //! Attribute name + attribute_name m_name; + //! Formatter function + formatter_function_type m_formatter; + //! Attribute value visitor invoker + visitor_invoker_type m_visitor_invoker; + +public: + //! Initializing constructor + template< typename FormatT > + format_named_scope_terminal + ( + attribute_name const& name, + fallback_policy const& fallback, + FormatT const& element_format, + string_type const& delimiter, + string_type const& incomplete_marker, + string_type const& empty_marker, + value_type::size_type depth, + scope_iteration_direction direction + ) : + m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, incomplete_marker, empty_marker, depth, direction), m_visitor_invoker(fallback) + { + } + //! Copy constructor + format_named_scope_terminal(format_named_scope_terminal const& that) : + m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker) + { + } + + //! Returns attribute name + attribute_name get_name() const + { + return m_name; + } + + //! Returns fallback policy + fallback_policy const& get_fallback_policy() const + { + return m_visitor_invoker.get_fallback_policy(); + } + + //! Retruns formatter function + formatter_function_type const& get_formatter_function() const + { + return m_formatter; + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) + { + string_type str; + stream_type strm(str); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm)); + strm.flush(); + return boost::move(str); + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) const + { + string_type str; + stream_type strm(str); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm)); + strm.flush(); + return boost::move(str); + } + + BOOST_DELETED_FUNCTION(format_named_scope_terminal()) +}; + +/*! + * Named scope formatter actor. + */ +template< typename FallbackPolicyT, typename CharT, template< typename > class ActorT = phoenix::actor > +class format_named_scope_actor : + public ActorT< format_named_scope_terminal< FallbackPolicyT, CharT > > +{ +public: + //! Character type + typedef CharT char_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + //! Base terminal type + typedef format_named_scope_terminal< fallback_policy, char_type > terminal_type; + //! Attribute value type + typedef typename terminal_type::value_type value_type; + //! Formatter function + typedef typename terminal_type::formatter_function_type formatter_function_type; + + //! Base actor type + typedef ActorT< terminal_type > base_type; + +public: + //! Initializing constructor + explicit format_named_scope_actor(base_type const& act) : base_type(act) + { + } + + /*! + * \returns The attribute name + */ + attribute_name get_name() const + { + return this->proto_expr_.child0.get_name(); + } + + /*! + * \returns Fallback policy + */ + fallback_policy const& get_fallback_policy() const + { + return this->proto_expr_.child0.get_fallback_policy(); + } + + /*! + * \returns Formatter function + */ + formatter_function_type const& get_formatter_function() const + { + return this->proto_expr_.child0.get_formatter_function(); + } +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename FallbackPolicyT, typename CharT >\ + BOOST_FORCEINLINE phoenix::actor< aux::attribute_output_terminal< phoenix::actor< LeftExprT >, attributes::named_scope::value_type, FallbackPolicyT, typename format_named_scope_actor< FallbackPolicyT, CharT >::formatter_function_type > >\ + operator<< (phoenix::actor< LeftExprT > left_ref left, format_named_scope_actor< FallbackPolicyT, CharT > right_ref right)\ + {\ + typedef aux::attribute_output_terminal< phoenix::actor< LeftExprT >, attributes::named_scope::value_type, FallbackPolicyT, typename format_named_scope_actor< FallbackPolicyT, CharT >::formatter_function_type > terminal_type;\ + phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_name(), right.get_formatter_function(), right.get_fallback_policy()) }};\ + return actor;\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +#endif // BOOST_LOG_DOXYGEN_PASS + +namespace aux { + +//! Auxiliary traits to acquire default formatter parameters depending on the character type +template< typename CharT > +struct default_named_scope_params; + +#ifdef BOOST_LOG_USE_CHAR +template< > +struct default_named_scope_params< char > +{ + static const char* forward_delimiter() { return "->"; } + static const char* reverse_delimiter() { return "<-"; } + static const char* incomplete_marker() { return "..."; } + static const char* empty_marker() { return ""; } +}; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +template< > +struct default_named_scope_params< wchar_t > +{ + static const wchar_t* forward_delimiter() { return L"->"; } + static const wchar_t* reverse_delimiter() { return L"<-"; } + static const wchar_t* incomplete_marker() { return L"..."; } + static const wchar_t* empty_marker() { return L""; } +}; +#endif + +template< typename CharT, template< typename > class ActorT, typename FallbackPolicyT, typename ArgsT > +BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > format_named_scope(attribute_name const& name, FallbackPolicyT const& fallback, ArgsT const& args) +{ + typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typedef default_named_scope_params< CharT > default_params; + scope_iteration_direction dir = args[keywords::iteration | expressions::forward]; + const CharT* default_delimiter = (dir == expressions::forward ? default_params::forward_delimiter() : default_params::reverse_delimiter()); + typename actor_type::base_type act = + {{ + terminal_type + ( + name, + fallback, + args[keywords::format], + args[keywords::delimiter | default_delimiter], + args[keywords::incomplete_marker | default_params::incomplete_marker()], + args[keywords::empty_marker | default_params::empty_marker()], + args[keywords::depth | static_cast< attributes::named_scope::value_type::size_type >(0)], + dir + ) + }}; + return actor_type(act); +} + +} // namespace aux + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param name Attribute name + * \param element_format Format string for a single named scope + */ +template< typename CharT > +BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, const CharT* element_format) +{ + typedef format_named_scope_actor< fallback_to_none, CharT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param name Attribute name + * \param element_format Format string for a single named scope + */ +template< typename CharT > +BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT > format_named_scope(attribute_name const& name, std::basic_string< CharT > const& element_format) +{ + typedef format_named_scope_actor< fallback_to_none, CharT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), element_format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param keyword Attribute keyword + * \param element_format Format string for a single named scope + */ +template< typename DescriptorT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT > +format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, const CharT* element_format) +{ + BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param keyword Attribute keyword + * \param element_format Format string for a single named scope + */ +template< typename DescriptorT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_named_scope_actor< fallback_to_none, CharT, ActorT > +format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, std::basic_string< CharT > const& element_format) +{ + BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef format_named_scope_actor< fallback_to_none, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), element_format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param placeholder Attribute placeholder + * \param element_format Format string for a single named scope + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > +format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, const CharT* element_format) +{ + BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }}; + return actor_type(act); +} + +/*! + * The function generates a manipulator node in a template expression. The manipulator must participate in a formatting + * expression (stream output or \c format placeholder filler). + * + * \param placeholder Attribute placeholder + * \param element_format Format string for a single named scope + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename CharT > +BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > +format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, std::basic_string< CharT > const& element_format) +{ + BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), element_format) }}; + return actor_type(act); +} + +#if !defined(BOOST_LOG_DOXYGEN_PASS) + +# define BOOST_PP_FILENAME_1 <boost/log/detail/named_scope_fmt_pp.hpp> +# define BOOST_PP_ITERATION_LIMITS (1, 6) +# include BOOST_PP_ITERATE() + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * Formatter generator. Construct the named scope formatter with the specified formatting parameters. + * + * \param name Attribute name + * \param args An set of named parameters. Supported parameters: + * \li \c format - A format string for named scopes. The string can contain "%n", "%f" and "%l" placeholders for the scope name, file and line number, respectively. This parameter is mandatory. + * \li \c delimiter - A string that is used to delimit the formatted scope names. Default: "->" or "<-", depending on the iteration direction. + * \li \c incomplete_marker - A string that is used to indicate that the list was printed incomplete because of depth limitation. Default: "...". + * \li \c empty_marker - A string that is output in case if the scope list is empty. Default: "", i.e. nothing is output. + * \li \c iteration - Iteration direction, see \c scope_iteration_direction enumeration. Default: forward. + * \li \c depth - Iteration depth. Default: unlimited. + */ +template< typename... ArgsT > +unspecified format_named_scope(attribute_name const& name, ArgsT... const& args); + +/*! \overload */ +template< typename DescriptorT, template< typename > class ActorT, typename... ArgsT > +unspecified format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, ArgsT... const& args); + +/*! \overload */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename... ArgsT > +unspecified format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, ArgsT... const& args); + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename FallbackPolicyT, typename CharT > +struct is_nullary< custom_terminal< boost::log::expressions::format_named_scope_terminal< FallbackPolicyT, CharT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_NAMED_SCOPE_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/stream.hpp b/boost/log/expressions/formatters/stream.hpp new file mode 100644 index 0000000000..cd5f1d36c3 --- /dev/null +++ b/boost/log/expressions/formatters/stream.hpp @@ -0,0 +1,53 @@ +/* + * 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 stream.hpp + * \author Andrey Semashev + * \date 24.07.2012 + * + * The header contains implementation of a stream placeholder in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_ + +#include <boost/phoenix/core/argument.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * Stream placeholder type in formatter template expressions. + */ +typedef phoenix::expression::argument< 2 >::type stream_type; + +/*! + * Stream placeholder in formatter template expressions. + */ +const stream_type stream = {}; + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> +#if defined(BOOST_LOG_EXPRESSIONS_ATTR_HPP_INCLUDED_) +#include <boost/log/detail/attr_output_impl.hpp> +#endif + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_STREAM_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/wrap_formatter.hpp b/boost/log/expressions/formatters/wrap_formatter.hpp new file mode 100644 index 0000000000..7d8a22c4fc --- /dev/null +++ b/boost/log/expressions/formatters/wrap_formatter.hpp @@ -0,0 +1,338 @@ +/* + * 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 formatters/wrap_formatter.hpp + * \author Andrey Semashev + * \date 24.11.2012 + * + * The header contains a formatter function wrapper that enables third-party functions to participate in formatting expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_ + +#include <string> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/function_traits.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +//! Wrapped formatter stream output terminal +template< typename LeftT, typename FunT > +class wrapped_formatter_output_terminal +{ +private: + //! Self type + typedef wrapped_formatter_output_terminal< LeftT, FunT > this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Wrapped function type + typedef FunT function_type; + + //! Result type definition + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; + typedef typename phoenix::evaluator::impl< + typename LeftT::proto_base_expr&, + context_type, + phoenix::unused + >::result_type type; + }; + +private: + //! Left argument actor + LeftT m_left; + //! Wrapped function + function_type m_fun; + +public: + //! Initializing constructor + wrapped_formatter_output_terminal(LeftT const& left, function_type const& fun) : m_left(left), m_fun(fun) + { + } + //! Copy constructor + wrapped_formatter_output_terminal(wrapped_formatter_output_terminal const& that) : m_left(that.m_left), m_fun(that.m_fun) + { + } + + //! Invokation operator + template< typename ContextT > + typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) + { + typedef typename result< this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm); + return strm; + } + + //! Invokation operator + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const + { + typedef typename result< const this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm); + return strm; + } + + BOOST_DELETED_FUNCTION(wrapped_formatter_output_terminal()) +}; + +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_char_type, char_type, false) + +template< + typename FunT, + bool HasCharTypeV = has_char_type< FunT >::value, + bool HasSecondArgumentV = boost::log::aux::has_second_argument_type< FunT >::value, + bool HasArg2V = boost::log::aux::has_arg2_type< FunT >::value +> +struct default_char_type +{ + // Use this char type if all detection fails + typedef char type; +}; + +template< typename FunT, bool HasSecondArgumentV, bool HasArg2V > +struct default_char_type< FunT, true, HasSecondArgumentV, HasArg2V > +{ + typedef typename FunT::char_type type; +}; + +template< typename FunT, bool HasArg2V > +struct default_char_type< FunT, false, true, HasArg2V > +{ + typedef typename remove_cv< typename remove_reference< typename FunT::second_argument_type >::type >::type argument_type; + typedef typename argument_type::char_type type; +}; + +template< typename FunT > +struct default_char_type< FunT, false, false, true > +{ + typedef typename remove_cv< typename remove_reference< typename FunT::arg2_type >::type >::type argument_type; + typedef typename argument_type::char_type type; +}; + +} // namespace aux + +/*! + * Formatter function wrapper terminal. + */ +template< typename FunT, typename CharT > +class wrapped_formatter_terminal +{ +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Wrapped function type + typedef FunT function_type; + + //! Formatter result type + typedef string_type result_type; + +private: + //! Wrapped function + function_type m_fun; + +public: + //! Initializing construction + explicit wrapped_formatter_terminal(function_type const& fun) : m_fun(fun) + { + } + //! Copy constructor + wrapped_formatter_terminal(wrapped_formatter_terminal const& that) : m_fun(that.m_fun) + { + } + + //! Returns the wrapped function + function_type const& get_function() const + { + return m_fun; + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) + { + string_type str; + stream_type strm(str); + m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm); + strm.flush(); + return boost::move(str); + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) const + { + string_type str; + stream_type strm(str); + m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args()), strm); + strm.flush(); + return boost::move(str); + } +}; + +/*! + * Wrapped formatter function actor. + */ +template< typename FunT, typename CharT, template< typename > class ActorT = phoenix::actor > +class wrapped_formatter_actor : + public ActorT< wrapped_formatter_terminal< FunT, CharT > > +{ +public: + //! Character type + typedef CharT char_type; + //! Wrapped function type + typedef FunT function_type; + //! Base terminal type + typedef wrapped_formatter_terminal< function_type, char_type > terminal_type; + + //! Base actor type + typedef ActorT< terminal_type > base_type; + +public: + //! Initializing constructor + explicit wrapped_formatter_actor(base_type const& act) : base_type(act) + { + } + + /*! + * \returns The wrapped function + */ + function_type const& get_function() const + { + return this->proto_expr_.child0.get_function(); + } +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename FunT, typename CharT >\ + BOOST_FORCEINLINE phoenix::actor< aux::wrapped_formatter_output_terminal< phoenix::actor< LeftExprT >, FunT > >\ + operator<< (phoenix::actor< LeftExprT > left_ref left, wrapped_formatter_actor< FunT, CharT > right_ref right)\ + {\ + typedef aux::wrapped_formatter_output_terminal< phoenix::actor< LeftExprT >, FunT > terminal_type;\ + phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_function()) }};\ + return actor;\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * The function wraps a function object in order it to be able to participate in formatting expressions. The wrapped + * function object must be compatible with the following signature: + * + * <pre> + * void (record_view const&, basic_formatting_ostream< CharT >&) + * </pre> + * + * where \c CharT is the character type of the formatting expression. + */ +template< typename FunT > +BOOST_FORCEINLINE wrapped_formatter_actor< FunT, typename aux::default_char_type< FunT >::type > wrap_formatter(FunT const& fun) +{ + typedef wrapped_formatter_actor< FunT, typename aux::default_char_type< FunT >::type > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(fun) }}; + return actor_type(act); +} + +/*! + * The function wraps a function object in order it to be able to participate in formatting expressions. The wrapped + * function object must be compatible with the following signature: + * + * <pre> + * void (record_view const&, basic_formatting_ostream< CharT >&) + * </pre> + * + * where \c CharT is the character type of the formatting expression. + */ +template< typename CharT, typename FunT > +BOOST_FORCEINLINE wrapped_formatter_actor< FunT, CharT > wrap_formatter(FunT const& fun) +{ + typedef wrapped_formatter_actor< FunT, CharT > actor_type; + typedef typename actor_type::terminal_type terminal_type; + typename actor_type::base_type act = {{ terminal_type(fun) }}; + return actor_type(act); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename LeftT, typename FunT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::wrapped_formatter_output_terminal< LeftT, FunT > > > : + public mpl::false_ +{ +}; + +template< typename FunT, typename CharT > +struct is_nullary< custom_terminal< boost::log::expressions::wrapped_formatter_terminal< FunT, CharT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_WRAP_FORMATTER_HPP_INCLUDED_ diff --git a/boost/log/expressions/formatters/xml_decorator.hpp b/boost/log/expressions/formatters/xml_decorator.hpp new file mode 100644 index 0000000000..021ed60bd4 --- /dev/null +++ b/boost/log/expressions/formatters/xml_decorator.hpp @@ -0,0 +1,138 @@ +/* + * 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 formatters/xml_decorator.hpp + * \author Andrey Semashev + * \date 18.11.2012 + * + * The header contains implementation of a XML-style character decorator. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_XML_DECORATOR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_FORMATTERS_XML_DECORATOR_HPP_INCLUDED_ + +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/expressions/formatters/char_decorator.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename > +struct xml_decorator_traits; + +#ifdef BOOST_LOG_USE_CHAR +template< > +struct xml_decorator_traits< char > +{ + static boost::iterator_range< const char* const* > get_patterns() + { + static const char* const patterns[] = + { + "&", "<", ">", "\"", "'" + }; + return boost::make_iterator_range(patterns); + } + static boost::iterator_range< const char* const* > get_replacements() + { + static const char* const replacements[] = + { + "&", "<", ">", """, "'" + }; + return boost::make_iterator_range(replacements); + } +}; +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T +template< > +struct xml_decorator_traits< wchar_t > +{ + static boost::iterator_range< const wchar_t* const* > get_patterns() + { + static const wchar_t* const patterns[] = + { + L"&", L"<", L">", L"\"", L"'" + }; + return boost::make_iterator_range(patterns); + } + static boost::iterator_range< const wchar_t* const* > get_replacements() + { + static const wchar_t* const replacements[] = + { + L"&", L"<", L">", L""", L"'" + }; + return boost::make_iterator_range(replacements); + } +}; +#endif // BOOST_LOG_USE_WCHAR_T + +template< typename CharT > +struct xml_decorator_gen +{ + typedef CharT char_type; + + template< typename SubactorT > + BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const + { + typedef xml_decorator_traits< char_type > traits_type; + typedef pattern_replacer< char_type > replacer_type; + typedef char_decorator_actor< SubactorT, replacer_type > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }}; + return result_type(act); + } +}; + +} // namespace aux + +/*! + * XML-style decorator generator object. The decorator replaces characters that have special meaning + * in XML documents with the corresponding decorated counterparts. The generator provides + * <tt>operator[]</tt> that can be used to construct the actual decorator. For example: + * + * <code> + * xml_decor[ attr< std::string >("MyAttr") ] + * </code> + * + * For wide-character formatting there is the similar \c wxml_decor decorator generator object. + */ +#ifdef BOOST_LOG_USE_CHAR +const aux::xml_decorator_gen< char > xml_decor = {}; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +const aux::xml_decorator_gen< wchar_t > wxml_decor = {}; +#endif + +/*! + * The function creates an XML-style decorator generator for arbitrary character type. + */ +template< typename CharT > +BOOST_FORCEINLINE aux::xml_decorator_gen< CharT > make_xml_decor() +{ + return aux::xml_decorator_gen< CharT >(); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_XML_DECORATOR_HPP_INCLUDED_ diff --git a/boost/log/expressions/is_keyword_descriptor.hpp b/boost/log/expressions/is_keyword_descriptor.hpp new file mode 100644 index 0000000000..9899e228e7 --- /dev/null +++ b/boost/log/expressions/is_keyword_descriptor.hpp @@ -0,0 +1,67 @@ +/* + * 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 is_keyword_descriptor.hpp + * \author Andrey Semashev + * \date 14.07.2012 + * + * The header contains attribute keyword descriptor detection trait. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_IS_KEYWORD_DESCRIPTOR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_IS_KEYWORD_DESCRIPTOR_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * Base class for keyword descriptors. All keyword descriptors must derive from this class to support the \c is_keyword_descriptor trait. + */ +struct keyword_descriptor +{ +#ifndef BOOST_LOG_DOXYGEN_PASS + typedef void _is_boost_log_keyword_descriptor; +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +/*! + * The metafunction detects if the type \c T is a keyword descriptor + */ +template< typename T, typename VoidT = void > +struct is_keyword_descriptor : + public mpl::false_ +{ +}; + +#ifndef BOOST_LOG_DOXYGEN_PASS +template< typename T > +struct is_keyword_descriptor< T, typename T::_is_boost_log_keyword_descriptor > : + public mpl::true_ +{ +}; +#endif + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_IS_KEYWORD_DESCRIPTOR_HPP_INCLUDED_ diff --git a/boost/log/expressions/keyword.hpp b/boost/log/expressions/keyword.hpp new file mode 100644 index 0000000000..434247be91 --- /dev/null +++ b/boost/log/expressions/keyword.hpp @@ -0,0 +1,258 @@ +/* + * 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 keyword.hpp + * \author Andrey Semashev + * \date 29.01.2012 + * + * The header contains attribute keyword declaration. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_ + +#include <boost/ref.hpp> +#include <boost/proto/extends.hpp> +#include <boost/proto/make_expr.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/domain.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/expressions/is_keyword_descriptor.hpp> +#include <boost/log/expressions/attr.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/value_extraction.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * This class implements an expression template keyword. It is used to start template expressions involving attribute values. + */ +template< typename DescriptorT, template< typename > class ActorT > +struct attribute_keyword +{ + //! Self type + typedef attribute_keyword this_type; + //! Attribute descriptor type + typedef DescriptorT descriptor_type; + + BOOST_PROTO_BASIC_EXTENDS(typename proto::terminal< descriptor_type >::type, this_type, phoenix::phoenix_domain) + + //! Attribute value type + typedef typename descriptor_type::value_type value_type; + + //! Returns attribute name + static attribute_name get_name() { return descriptor_type::get_name(); } + + //! Expression with cached attribute name + typedef attribute_actor< + value_type, + fallback_to_none, + descriptor_type, + ActorT + > or_none_result_type; + + //! Generates an expression that extracts the attribute value or a default value + static or_none_result_type or_none() + { + typedef typename or_none_result_type::terminal_type result_terminal; + typename or_none_result_type::base_type act = {{ result_terminal(get_name()) }}; + return or_none_result_type(act); + } + + //! Expression with cached attribute name + typedef attribute_actor< + value_type, + fallback_to_throw, + descriptor_type, + ActorT + > or_throw_result_type; + + //! Generates an expression that extracts the attribute value or throws an exception + static or_throw_result_type or_throw() + { + typedef typename or_throw_result_type::terminal_type result_terminal; + typename or_throw_result_type::base_type act = {{ result_terminal(get_name()) }}; + return or_throw_result_type(act); + } + + //! Generates an expression that extracts the attribute value or a default value + template< typename DefaultT > + static attribute_actor< + value_type, + fallback_to_default< DefaultT >, + descriptor_type, + ActorT + > or_default(DefaultT const& def_val) + { + typedef attribute_actor< + value_type, + fallback_to_default< DefaultT >, + descriptor_type, + ActorT + > or_default_result_type; + typedef typename or_default_result_type::terminal_type result_terminal; + typename or_default_result_type::base_type act = {{ result_terminal(get_name(), def_val) }}; + return or_default_result_type(act); + } +}; + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace proto { + +namespace detail { + +// This hack is needed in order to cache attribute name into the expression terminal when the template +// expression is constructed. The standard way through a custom domain doesn't work because phoenix::actor +// is bound to phoenix_domain. +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ + typedef boost::log::expressions::attribute_keyword< DescriptorT, ActorT > keyword_type; + typedef typename keyword_type::or_none_result_type result_type; + + result_type operator() (keyword_type const& keyword) const + { + return keyword.or_none(); + } +}; + +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >&, DomainT > : + public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ +}; + +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const&, DomainT > : + public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ +}; + +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > : + public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ +}; + +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::reference_wrapper< boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > : + public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ +}; + +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > >, DomainT > : + public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ +}; + +template< typename DescriptorT, template< typename > class ActorT, typename DomainT > +struct protoify< boost::reference_wrapper< const boost::log::expressions::attribute_keyword< DescriptorT, ActorT > > const, DomainT > : + public protoify< boost::log::expressions::attribute_keyword< DescriptorT, ActorT >, DomainT > +{ +}; + +} // namespace detail + +} // namespace proto + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +} // namespace boost + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\ + namespace tag_ns_\ + {\ + struct keyword_ :\ + public ::boost::log::expressions::keyword_descriptor\ + {\ + typedef value_type_ value_type;\ + static ::boost::log::attribute_name get_name() { return ::boost::log::attribute_name(name_); }\ + };\ + }\ + typedef ::boost::log::expressions::attribute_keyword< tag_ns_::keyword_ > BOOST_PP_CAT(keyword_, _type); + +#define BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag_ns_)\ + BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag_ns_)\ + const BOOST_PP_CAT(keyword_, _type) keyword_ = {}; + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief The macro declares an attribute keyword type + * + * The macro should be used at a namespace scope. It expands into an attribute keyword type definition, including the + * \c tag namespace and the keyword tag type within which has the following layout: + * + * \code + * namespace tag + * { + * struct keyword_ : + * public boost::log::expressions::keyword_descriptor + * { + * typedef value_type_ value_type; + * static boost::log::attribute_name get_name(); + * }; + * } + * + * typedef boost::log::expressions::attribute_keyword< tag::keyword_ > keyword_type; + * \endcode + * + * The \c get_name method returns the attribute name. + * + * \note This macro only defines the type of the keyword. To also define the keyword object, use + * the \c BOOST_LOG_ATTRIBUTE_KEYWORD macro instead. + * + * \param keyword_ Keyword name + * \param name_ Attribute name string + * \param value_type_ Attribute value type + */ +#define BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE(keyword_, name_, value_type_)\ + BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE_IMPL(keyword_, name_, value_type_, tag) + +/*! + * \brief The macro declares an attribute keyword + * + * The macro provides definitions similar to \c BOOST_LOG_ATTRIBUTE_KEYWORD_TYPE and additionally + * defines the keyword object. + * + * \param keyword_ Keyword name + * \param name_ Attribute name string + * \param value_type_ Attribute value type + */ +#define BOOST_LOG_ATTRIBUTE_KEYWORD(keyword_, name_, value_type_)\ + BOOST_LOG_ATTRIBUTE_KEYWORD_IMPL(keyword_, name_, value_type_, tag) + +#include <boost/log/detail/footer.hpp> + +#if defined(BOOST_LOG_TRIVIAL_HPP_INCLUDED_) +#include <boost/log/detail/trivial_keyword.hpp> +#endif + +#endif // BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_ diff --git a/boost/log/expressions/keyword_fwd.hpp b/boost/log/expressions/keyword_fwd.hpp new file mode 100644 index 0000000000..a2671e9f61 --- /dev/null +++ b/boost/log/expressions/keyword_fwd.hpp @@ -0,0 +1,53 @@ +/* + * 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 keyword_fwd.hpp + * \author Andrey Semashev + * \date 29.01.2012 + * + * The header contains attribute keyword forward declaration. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_KEYWORD_FWD_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_KEYWORD_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +template< typename > +struct actor; + +} // namespace phoenix + +#endif // BOOST_LOG_DOXYGEN_PASS + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * \brief This class implements an expression template keyword + */ +template< typename DescriptorT, template< typename > class ActorT = phoenix::actor > +struct attribute_keyword; + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_EXPRESSIONS_KEYWORD_FWD_HPP_INCLUDED_ diff --git a/boost/log/expressions/message.hpp b/boost/log/expressions/message.hpp new file mode 100644 index 0000000000..79d826a992 --- /dev/null +++ b/boost/log/expressions/message.hpp @@ -0,0 +1,130 @@ +/* + * 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 message.hpp + * \author Andrey Semashev + * \date 13.07.2012 + * + * The header contains log message keyword declaration. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_MESSAGE_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_MESSAGE_HPP_INCLUDED_ + +#include <string> +#include <boost/mpl/vector.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/default_attribute_names.hpp> +#include <boost/log/expressions/keyword.hpp> +#include <boost/log/expressions/is_keyword_descriptor.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace tag { + +/*! + * Generic log message attribute descriptor. + */ +struct message : + public keyword_descriptor +{ + // The attribute value type here is not essential since message attributes are not intended to be created via the keyword + typedef void attribute_type; + +#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T) + typedef mpl::vector2< std::string, std::wstring > value_type; +#elif defined(BOOST_LOG_USE_CHAR) + typedef std::string value_type; +#elif defined(BOOST_LOG_USE_WCHAR_T) + typedef std::wstring value_type; +#endif + + static attribute_name get_name() { return boost::log::aux::default_attribute_names::message(); } +}; + +#if defined(BOOST_LOG_USE_CHAR) +/*! + * Narrow character log message attribute descriptor. + */ +struct smessage : + public keyword_descriptor +{ + // The attribute value type here is not essential since message attributes are not intended to be created via the keyword + typedef void attribute_type; + typedef std::string value_type; + + static attribute_name get_name() { return boost::log::aux::default_attribute_names::message(); } +}; +#endif + +#if defined(BOOST_LOG_USE_WCHAR_T) +/*! + * Wide character log message attribute descriptor. + */ +struct wmessage : + public keyword_descriptor +{ + // The attribute value type here is not essential since message attributes are not intended to be created via the keyword + typedef void attribute_type; + typedef std::wstring value_type; + + static attribute_name get_name() { return boost::log::aux::default_attribute_names::message(); } +}; +#endif + +} // namespace tag + +/*! + * Generic message keyword type. + */ +typedef attribute_keyword< tag::message > message_type; +/*! + * Generic message keyword. + */ +const message_type message = {}; + +#if defined(BOOST_LOG_USE_CHAR) +/*! + * Narrow message keyword type. + */ +typedef attribute_keyword< tag::smessage > smessage_type; +/*! + * Narrow message keyword. + */ +const smessage_type smessage = {}; +#endif + +#if defined(BOOST_LOG_USE_WCHAR_T) +/*! + * Wide message keyword type. + */ +typedef attribute_keyword< tag::wmessage > wmessage_type; +/*! + * Wide message keyword. + */ +const wmessage_type wmessage = {}; +#endif + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_MESSAGE_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates.hpp b/boost/log/expressions/predicates.hpp new file mode 100644 index 0000000000..297b51b9d2 --- /dev/null +++ b/boost/log/expressions/predicates.hpp @@ -0,0 +1,34 @@ +/* + * 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 predicates.hpp + * \author Andrey Semashev + * \date 29.01.2012 + * + * The header includes all template expression predicates. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/expressions/predicates/has_attr.hpp> +#include <boost/log/expressions/predicates/begins_with.hpp> +#include <boost/log/expressions/predicates/ends_with.hpp> +#include <boost/log/expressions/predicates/contains.hpp> +#include <boost/log/expressions/predicates/matches.hpp> +#include <boost/log/expressions/predicates/is_in_range.hpp> + +#include <boost/log/expressions/predicates/is_debugger_present.hpp> +#include <boost/log/expressions/predicates/channel_severity_filter.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/begins_with.hpp b/boost/log/expressions/predicates/begins_with.hpp new file mode 100644 index 0000000000..e837a4ac7e --- /dev/null +++ b/boost/log/expressions/predicates/begins_with.hpp @@ -0,0 +1,129 @@ +/* + * 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 begins_with.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of a \c begins_with predicate in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_BEGINS_WITH_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_BEGINS_WITH_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/embedded_string_type.hpp> +#include <boost/log/detail/unary_function_terminal.hpp> +#include <boost/log/detail/attribute_predicate.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/utility/functional/begins_with.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * The predicate checks if the attribute value begins with a substring. The attribute value is assumed to be of a string type. + */ +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none > +using attribute_begins_with = aux::attribute_predicate< T, SubstringT, begins_with_fun, FallbackPolicyT >; + +#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none > +class attribute_begins_with : + public aux::attribute_predicate< T, SubstringT, begins_with_fun, FallbackPolicyT > +{ + typedef aux::attribute_predicate< T, SubstringT, begins_with_fun, FallbackPolicyT > base_type; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param substring The expected attribute value beginning + */ + attribute_begins_with(attribute_name const& name, SubstringT const& substring) : base_type(name, substring) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param substring The expected attribute value beginning + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_begins_with(attribute_name const& name, SubstringT const& substring, U const& arg) : base_type(name, substring, arg) + { + } +}; + +#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, begins with the specified substring. + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename SubstringT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > > +begins_with(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), substring, attr.get_fallback_policy()) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, begins with the specified substring. + */ +template< typename DescriptorT, template< typename > class ActorT, typename SubstringT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_begins_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > > +begins_with(attribute_keyword< DescriptorT, ActorT > const&, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_begins_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), substring) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, begins with the specified substring. + */ +template< typename T, typename SubstringT > +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > > +begins_with(attribute_name const& name, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_begins_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name, substring) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_BEGINS_WITH_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/channel_severity_filter.hpp b/boost/log/expressions/predicates/channel_severity_filter.hpp new file mode 100644 index 0000000000..f0ddfb564c --- /dev/null +++ b/boost/log/expressions/predicates/channel_severity_filter.hpp @@ -0,0 +1,572 @@ +/* + * 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 channel_severity_filter.hpp + * \author Andrey Semashev + * \date 25.11.2012 + * + * The header contains implementation of a minimal severity per channel filter. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_CHANNEL_SEVERITY_FILTER_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_CHANNEL_SEVERITY_FILTER_HPP_INCLUDED_ + +#include <map> +#include <memory> +#include <utility> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/utility/functional/logical.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +template< + typename ChannelT, + typename SeverityT, + typename ChannelFallbackT = fallback_to_none, + typename SeverityFallbackT = fallback_to_none, + typename ChannelOrderT = less, + typename SeverityCompareT = greater_equal, + typename AllocatorT = std::allocator< void > +> +class channel_severity_filter_terminal +{ +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Function result type + typedef bool result_type; + + //! Channel attribute value type + typedef ChannelT channel_value_type; + //! Channel fallback policy + typedef ChannelFallbackT channel_fallback_policy; + //! Severity level attribute value type + typedef SeverityT severity_value_type; + //! Severity level fallback policy + typedef SeverityFallbackT severity_fallback_policy; + +private: + //! Channel to severity mapping type + typedef std::map< + channel_value_type, + severity_value_type, + ChannelOrderT, + typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< std::pair< const channel_value_type, severity_value_type > >::other + > mapping_type; + //! Attribute value visitor invoker for channel + typedef value_visitor_invoker< channel_value_type, channel_fallback_policy > channel_visitor_invoker_type; + //! Attribute value visitor invoker for severity level + typedef value_visitor_invoker< severity_value_type, severity_fallback_policy > severity_visitor_invoker_type; + + //! Channel visitor + template< typename ArgT > + struct channel_visitor + { + typedef void result_type; + + channel_visitor(channel_severity_filter_terminal const& self, ArgT arg, bool& res) : m_self(self), m_arg(arg), m_res(res) + { + } + + result_type operator() (channel_value_type const& channel) const + { + m_self.visit_channel(channel, m_arg, m_res); + } + + private: + channel_severity_filter_terminal const& m_self; + ArgT m_arg; + bool& m_res; + }; + + //! Severity level visitor + struct severity_visitor + { + typedef void result_type; + + severity_visitor(channel_severity_filter_terminal const& self, severity_value_type const& severity, bool& res) : m_self(self), m_severity(severity), m_res(res) + { + } + + result_type operator() (severity_value_type const& severity) const + { + m_self.visit_severity(severity, m_severity, m_res); + } + + private: + channel_severity_filter_terminal const& m_self; + severity_value_type const& m_severity; + bool& m_res; + }; + +private: + //! Channel attribute name + attribute_name m_channel_name; + //! Severity level attribute name + attribute_name m_severity_name; + //! Channel value visitor invoker + channel_visitor_invoker_type m_channel_visitor_invoker; + //! Severity level value visitor invoker + severity_visitor_invoker_type m_severity_visitor_invoker; + + //! Channel to severity level mapping + mapping_type m_mapping; + //! Severity checking predicate + SeverityCompareT m_severity_compare; + + //! Default result + bool m_default; + +public: + //! Initializing constructor + channel_severity_filter_terminal + ( + attribute_name const& channel_name, + attribute_name const& severity_name, + channel_fallback_policy const& channel_fallback = channel_fallback_policy(), + severity_fallback_policy const& severity_fallback = severity_fallback_policy(), + ChannelOrderT const& channel_order = ChannelOrderT(), + SeverityCompareT const& severity_compare = SeverityCompareT() + ) : + m_channel_name(channel_name), + m_severity_name(severity_name), + m_channel_visitor_invoker(channel_fallback), + m_severity_visitor_invoker(severity_fallback), + m_mapping(channel_order), + m_severity_compare(severity_compare), + m_default(false) + { + } + + //! Adds a new element to the mapping + void add(channel_value_type const& channel, severity_value_type const& severity) + { + typedef typename mapping_type::iterator iterator; + std::pair< iterator, bool > res = m_mapping.insert(typename mapping_type::value_type(channel, severity)); + if (!res.second) + res.first->second = severity; + } + + //! Sets the default result of the predicate + void set_default(bool def) + { + m_default = def; + } + + //! Invokation operator + template< typename ContextT > + result_type operator() (ContextT const& ctx) const + { + result_type res = m_default; + + typedef typename remove_cv< + typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type + >::type env_type; + typedef typename env_type::args_type args_type; + typedef typename fusion::result_of::at_c< args_type, 0 >::type arg_type; + arg_type arg = fusion::at_c< 0 >(phoenix::env(ctx).args()); + + m_channel_visitor_invoker(m_channel_name, arg, channel_visitor< arg_type >(*this, arg, res)); + + return res; + } + +private: + //! Visits channel name + template< typename ArgT > + void visit_channel(channel_value_type const& channel, ArgT const& arg, bool& res) const + { + typename mapping_type::const_iterator it = m_mapping.find(channel); + if (it != m_mapping.end()) + { + m_severity_visitor_invoker(m_severity_name, arg, severity_visitor(*this, it->second, res)); + } + } + + //! Visits severity level + void visit_severity(severity_value_type const& left, severity_value_type const& right, bool& res) const + { + res = m_severity_compare(left, right); + } +}; + +template< + typename ChannelT, + typename SeverityT, + typename ChannelFallbackT = fallback_to_none, + typename SeverityFallbackT = fallback_to_none, + typename ChannelOrderT = less, + typename SeverityCompareT = greater_equal, + typename AllocatorT = std::allocator< void >, + template< typename > class ActorT = phoenix::actor +> +class channel_severity_filter_actor : + public ActorT< channel_severity_filter_terminal< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, AllocatorT > > +{ +private: + //! Self type + typedef channel_severity_filter_actor this_type; + +public: + //! Terminal type + typedef channel_severity_filter_terminal< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, AllocatorT > terminal_type; + //! Base actor type + typedef ActorT< terminal_type > base_type; + + //! Channel attribute value type + typedef typename terminal_type::channel_value_type channel_value_type; + //! Channel fallback policy + typedef typename terminal_type::channel_fallback_policy channel_fallback_policy; + //! Severity level attribute value type + typedef typename terminal_type::severity_value_type severity_value_type; + //! Severity level fallback policy + typedef typename terminal_type::severity_fallback_policy severity_fallback_policy; + +private: + //! An auxiliary pseudo-reference to implement insertion through subscript operator + class subscript_result + { + private: + channel_severity_filter_actor& m_owner; + channel_value_type const& m_channel; + + public: + subscript_result(channel_severity_filter_actor& owner, channel_value_type const& channel) : m_owner(owner), m_channel(channel) + { + } + + void operator= (severity_value_type const& severity) + { + m_owner.add(m_channel, severity); + } + }; + +public: + //! Initializing constructor + explicit channel_severity_filter_actor(base_type const& act) : base_type(act) + { + } + //! Copy constructor + channel_severity_filter_actor(channel_severity_filter_actor const& that) : base_type(static_cast< base_type const& >(that)) + { + } + + //! Sets the default function result + this_type& set_default(bool def) + { + this->proto_expr_.child0.set_default(def); + return *this; + } + + //! Adds a new element to the mapping + this_type& add(channel_value_type const& channel, severity_value_type const& severity) + { + this->proto_expr_.child0.add(channel, severity); + return *this; + } + + //! Alternative interface for adding a new element to the mapping + subscript_result operator[] (channel_value_type const& channel) + { + return subscript_result(*this, channel); + } +}; + +/*! + * The function generates a filtering predicate that checks the severity levels of log records in different channels. The predicate will return \c true + * if the record severity level is not less than the threshold for the channel the record belongs to. + */ +template< typename ChannelT, typename SeverityT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT > +channel_severity_filter(attribute_name const& channel_name, attribute_name const& severity_name) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_name) }}; + return result_type(act); +} + +//! \overload +template< typename SeverityT, typename ChannelDescriptorT, template< typename > class ActorT > +BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > +channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_name const& severity_name) +{ + typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_name) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename SeverityDescriptorT, template< typename > class ActorT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > +channel_severity_filter(attribute_name const& channel_name, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword) +{ + typedef channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_keyword.get_name()) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelDescriptorT, typename SeverityDescriptorT, template< typename > class ActorT > +BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > +channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword) +{ + typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_keyword.get_name()) }}; + return result_type(act); +} + +//! \overload +template< typename SeverityT, typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, template< typename > class ActorT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > +channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_name const& severity_name) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, greater_equal, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_name, channel_placeholder.get_fallback_policy()) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT > +channel_severity_filter(attribute_name const& channel_name, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_placeholder.get_name(), fallback_to_none(), severity_placeholder.get_fallback_policy()) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT > +channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, greater_equal, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_placeholder.get_name(), channel_placeholder.get_fallback_policy(), severity_placeholder.get_fallback_policy()) }}; + return result_type(act); +} + + +//! \overload +template< typename ChannelT, typename SeverityT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT > +channel_severity_filter(attribute_name const& channel_name, attribute_name const& severity_name, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_name, fallback_to_none(), fallback_to_none(), less(), severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename SeverityT, typename ChannelDescriptorT, template< typename > class ActorT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_name const& severity_name, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_name, fallback_to_none(), fallback_to_none(), less(), severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_name const& channel_name, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), less(), severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelDescriptorT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), less(), severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename SeverityT, typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, template< typename > class ActorT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_name const& severity_name, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, less, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_name, channel_placeholder.get_fallback_policy(), fallback_to_none(), less(), severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_name const& channel_name, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_placeholder.get_name(), fallback_to_none(), severity_placeholder.get_fallback_policy(), less(), severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, less, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_placeholder.get_name(), channel_placeholder.get_fallback_policy(), severity_placeholder.get_fallback_policy(), less(), severity_compare) }}; + return result_type(act); +} + + +//! \overload +template< typename ChannelT, typename SeverityT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT > +channel_severity_filter(attribute_name const& channel_name, attribute_name const& severity_name, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_name, fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename SeverityT, typename ChannelDescriptorT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_name const& severity_name, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, SeverityT, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_name, fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_name const& channel_name, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< ChannelT, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelDescriptorT, typename SeverityDescriptorT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_keyword< ChannelDescriptorT, ActorT > const& channel_keyword, attribute_keyword< SeverityDescriptorT, ActorT > const& severity_keyword, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< typename ChannelDescriptorT::value_type, typename SeverityDescriptorT::value_type, fallback_to_none, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_keyword.get_name(), severity_keyword.get_name(), fallback_to_none(), fallback_to_none(), channel_order, severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename SeverityT, typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_name const& severity_name, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, fallback_to_none, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_name, channel_placeholder.get_fallback_policy(), fallback_to_none(), channel_order, severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_name const& channel_name, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, fallback_to_none, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_name, severity_placeholder.get_name(), fallback_to_none(), severity_placeholder.get_fallback_policy(), channel_order, severity_compare) }}; + return result_type(act); +} + +//! \overload +template< typename ChannelT, typename ChannelFallbackT, typename ChannelTagT, typename SeverityT, typename SeverityFallbackT, typename SeverityTagT, template< typename > class ActorT, typename SeverityCompareT, typename ChannelOrderT > +BOOST_FORCEINLINE channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > +channel_severity_filter(attribute_actor< ChannelT, ChannelFallbackT, ChannelTagT, ActorT > const& channel_placeholder, attribute_actor< SeverityT, SeverityFallbackT, SeverityTagT, ActorT > const& severity_placeholder, SeverityCompareT const& severity_compare, ChannelOrderT const& channel_order) +{ + typedef channel_severity_filter_actor< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, std::allocator< void >, ActorT > result_type; + typedef typename result_type::terminal_type terminal_type; + typename result_type::base_type act = {{ terminal_type(channel_placeholder.get_name(), severity_placeholder.get_name(), channel_placeholder.get_fallback_policy(), severity_placeholder.get_fallback_policy(), channel_order, severity_compare) }}; + return result_type(act); +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< + typename ChannelT, + typename SeverityT, + typename ChannelFallbackT, + typename SeverityFallbackT, + typename ChannelOrderT, + typename SeverityCompareT, + typename AllocatorT +> +struct is_nullary< custom_terminal< boost::log::expressions::channel_severity_filter_terminal< ChannelT, SeverityT, ChannelFallbackT, SeverityFallbackT, ChannelOrderT, SeverityCompareT, AllocatorT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_CHANNEL_SEVERITY_FILTER_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/contains.hpp b/boost/log/expressions/predicates/contains.hpp new file mode 100644 index 0000000000..633ba65e8e --- /dev/null +++ b/boost/log/expressions/predicates/contains.hpp @@ -0,0 +1,129 @@ +/* + * 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 contains.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of a \c contains predicate in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_CONTAINS_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_CONTAINS_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/embedded_string_type.hpp> +#include <boost/log/detail/unary_function_terminal.hpp> +#include <boost/log/detail/attribute_predicate.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/utility/functional/contains.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * The predicate checks if the attribute value contains a substring. The attribute value is assumed to be of a string type. + */ +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none > +using attribute_contains = aux::attribute_predicate< T, SubstringT, contains_fun, FallbackPolicyT >; + +#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none > +class attribute_contains : + public aux::attribute_predicate< T, SubstringT, contains_fun, FallbackPolicyT > +{ + typedef aux::attribute_predicate< T, SubstringT, contains_fun, FallbackPolicyT > base_type; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param substring The expected attribute value substring + */ + attribute_contains(attribute_name const& name, SubstringT const& substring) : base_type(name, substring) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param substring The expected attribute value substring + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_contains(attribute_name const& name, SubstringT const& substring, U const& arg) : base_type(name, substring, arg) + { + } +}; + +#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, contains the specified substring. + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename SubstringT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > > +contains(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), substring, attr.get_fallback_policy()) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, contains the specified substring. + */ +template< typename DescriptorT, template< typename > class ActorT, typename SubstringT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_contains< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > > +contains(attribute_keyword< DescriptorT, ActorT > const&, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_contains< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), substring) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, contains the specified substring. + */ +template< typename T, typename SubstringT > +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > > +contains(attribute_name const& name, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_contains< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name, substring) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_CONTAINS_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/ends_with.hpp b/boost/log/expressions/predicates/ends_with.hpp new file mode 100644 index 0000000000..1e8785dad0 --- /dev/null +++ b/boost/log/expressions/predicates/ends_with.hpp @@ -0,0 +1,129 @@ +/* + * 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 ends_with.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of a \c ends_with predicate in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_ENDS_WITH_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_ENDS_WITH_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/embedded_string_type.hpp> +#include <boost/log/detail/unary_function_terminal.hpp> +#include <boost/log/detail/attribute_predicate.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/utility/functional/ends_with.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * The predicate checks if the attribute value ends with a substring. The attribute value is assumed to be of a string type. + */ +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none > +using attribute_ends_with = aux::attribute_predicate< T, SubstringT, ends_with_fun, FallbackPolicyT >; + +#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename SubstringT, typename FallbackPolicyT = fallback_to_none > +class attribute_ends_with : + public aux::attribute_predicate< T, SubstringT, ends_with_fun, FallbackPolicyT > +{ + typedef aux::attribute_predicate< T, SubstringT, ends_with_fun, FallbackPolicyT > base_type; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param substring The expected attribute value ending + */ + attribute_ends_with(attribute_name const& name, SubstringT const& substring) : base_type(name, substring) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param substring The expected attribute value ending + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_ends_with(attribute_name const& name, SubstringT const& substring, U const& arg) : base_type(name, substring, arg) + { + } +}; + +#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, ends with the specified substring. + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename SubstringT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > > +ends_with(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type, FallbackPolicyT > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), substring, attr.get_fallback_policy()) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, ends with the specified substring. + */ +template< typename DescriptorT, template< typename > class ActorT, typename SubstringT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_ends_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > > +ends_with(attribute_keyword< DescriptorT, ActorT > const&, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_ends_with< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), substring) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, ends with the specified substring. + */ +template< typename T, typename SubstringT > +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > > +ends_with(attribute_name const& name, SubstringT const& substring) +{ + typedef aux::unary_function_terminal< attribute_ends_with< T, typename boost::log::aux::make_embedded_string_type< SubstringT >::type > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name, substring) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_ENDS_WITH_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/has_attr.hpp b/boost/log/expressions/predicates/has_attr.hpp new file mode 100644 index 0000000000..e4eb72e683 --- /dev/null +++ b/boost/log/expressions/predicates/has_attr.hpp @@ -0,0 +1,172 @@ +/* + * 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 has_attr.hpp + * \author Andrey Semashev + * \date 23.07.2012 + * + * The header contains implementation of a generic attribute presence checker in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_HAS_ATTR_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_HAS_ATTR_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.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/expressions/keyword_fwd.hpp> +#include <boost/log/detail/unary_function_terminal.hpp> +#include <boost/log/utility/functional/nop.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * An attribute value presence checker. + */ +template< typename T > +class has_attribute +{ +public: + //! Function result_type + typedef bool result_type; + //! Expected attribute value type + typedef T value_type; + +private: + //! Attribute value name + const attribute_name m_name; + //! Visitor invoker + value_visitor_invoker< value_type > m_visitor_invoker; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + */ + explicit has_attribute(attribute_name const& name) : m_name(name) + { + } + + /*! + * Checking operator + * + * \param arg A set of attribute values or a log record + * \return \c true if the log record contains the sought attribute value, \c false otherwise + */ + template< typename ArgT > + result_type operator() (ArgT const& arg) const + { + return m_visitor_invoker(m_name, arg, nop()).code() == visitation_result::ok; + } +}; + +/*! + * An attribute value presence checker. This specialization does not check the type of the attribute value. + */ +template< > +class has_attribute< void > +{ +public: + //! Function result_type + typedef bool result_type; + //! Expected attribute value type + typedef void value_type; + +private: + //! Attribute name + const attribute_name m_name; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + */ + explicit has_attribute(attribute_name const& name) : m_name(name) + { + } + + /*! + * Checking operator + * + * \param attrs A set of attribute values + * \return \c true if the log record contains the sought attribute value, \c false otherwise + */ + result_type operator() (attribute_value_set const& attrs) const + { + return attrs.find(m_name) != attrs.end(); + } + + /*! + * Checking operator + * + * \param rec A log record + * \return \c true if the log record contains the sought attribute value, \c false otherwise + */ + result_type operator() (boost::log::record_view const& rec) const + { + return operator()(rec.attribute_values()); + } +}; + +/*! + * The function generates a terminal node in a template expression. The node will check for the attribute value + * presence in a log record. The node will also check that the attribute value has the specified type, if present. + */ +template< typename AttributeValueT > +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< has_attribute< AttributeValueT > > > has_attr(attribute_name const& name) +{ + typedef aux::unary_function_terminal< has_attribute< AttributeValueT > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check for the attribute value + * presence in a log record. + */ +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< has_attribute< void > > > has_attr(attribute_name const& name) +{ + typedef aux::unary_function_terminal< has_attribute< void > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check for the attribute value + * presence in a log record. The node will also check that the attribute value has the specified type, if present. + */ +template< typename DescriptorT, template< typename > class ActorT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< has_attribute< typename DescriptorT::value_type > > > has_attr(attribute_keyword< DescriptorT, ActorT > const&) +{ + typedef aux::unary_function_terminal< has_attribute< typename DescriptorT::value_type > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name()) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_HAS_ATTR_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/is_debugger_present.hpp b/boost/log/expressions/predicates/is_debugger_present.hpp new file mode 100644 index 0000000000..f7427c8a90 --- /dev/null +++ b/boost/log/expressions/predicates/is_debugger_present.hpp @@ -0,0 +1,107 @@ +/* + * 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 is_debugger_present.hpp + * \author Andrey Semashev + * \date 05.12.2012 + * + * The header contains implementation of the \c is_debugger_present predicate in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_IS_DEBUGGER_PRESENT_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_IS_DEBUGGER_PRESENT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_WINDOWS) + +#include <boost/phoenix/core/terminal.hpp> // this is needed to be able to include this header alone, Boost.Phoenix blows up without it +#include <boost/phoenix/function/adapt_callable.hpp> +#include <boost/log/detail/header.hpp> + +#if defined(BOOST_USE_WINDOWS_H) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#include <windows.h> + +#else // defined(BOOST_USE_WINDOWS_H) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +extern "C" { + +__declspec(dllimport) int __stdcall IsDebuggerPresent(); + +} // extern "C" + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_USE_WINDOWS_H + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +struct is_debugger_present +{ + typedef bool result_type; + + result_type operator() () const + { + return IsDebuggerPresent() != 0; + } +}; + +} // namespace aux + +#ifndef BOOST_LOG_DOXYGEN_PASS + +BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(is_debugger_present, aux::is_debugger_present) + +#else + +/*! + * The function generates a filter that will check whether the logger is attached to the process + */ +unspecified is_debugger_present(); + +#endif + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_WINDOWS + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_IS_DEBUGGER_PRESENT_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/is_in_range.hpp b/boost/log/expressions/predicates/is_in_range.hpp new file mode 100644 index 0000000000..e819d2bfe2 --- /dev/null +++ b/boost/log/expressions/predicates/is_in_range.hpp @@ -0,0 +1,133 @@ +/* + * 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 is_in_range.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of an \c is_in_range predicate in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_IS_IN_RANGE_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_IS_IN_RANGE_HPP_INCLUDED_ + +#include <utility> +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/embedded_string_type.hpp> +#include <boost/log/detail/unary_function_terminal.hpp> +#include <boost/log/detail/attribute_predicate.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/utility/functional/in_range.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * The predicate checks if the attribute value contains a substring. The attribute value is assumed to be of a string type. + */ +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename BoundaryT, typename FallbackPolicyT = fallback_to_none > +using attribute_is_in_range = aux::attribute_predicate< T, std::pair< BoundaryT, BoundaryT >, in_range_fun, FallbackPolicyT >; + +#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template< typename T, typename BoundaryT, typename FallbackPolicyT = fallback_to_none > +class attribute_is_in_range : + public aux::attribute_predicate< T, std::pair< BoundaryT, BoundaryT >, in_range_fun, FallbackPolicyT > +{ + typedef aux::attribute_predicate< T, std::pair< BoundaryT, BoundaryT >, in_range_fun, FallbackPolicyT > base_type; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param boundaries The expected attribute value boundaries + */ + attribute_is_in_range(attribute_name const& name, std::pair< BoundaryT, BoundaryT > const& boundaries) : base_type(name, boundaries) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param boundaries The expected attribute value boundaries + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_is_in_range(attribute_name const& name, std::pair< BoundaryT, BoundaryT > const& boundaries, U const& arg) : base_type(name, boundaries, arg) + { + } +}; + +#endif // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value + * is in the specified range. The range must be half-open, that is the predicate will be equivalent to <tt>least <= attr < most</tt>. + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename BoundaryT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_is_in_range< T, typename boost::log::aux::make_embedded_string_type< BoundaryT >::type, FallbackPolicyT > > > +is_in_range(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, BoundaryT const& least, BoundaryT const& most) +{ + typedef typename boost::log::aux::make_embedded_string_type< BoundaryT >::type boundary_type; + typedef aux::unary_function_terminal< attribute_is_in_range< T, boundary_type, FallbackPolicyT > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), std::pair< boundary_type, boundary_type >(least, most), attr.get_fallback_policy()) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value + * is in the specified range. The range must be half-open, that is the predicate will be equivalent to <tt>least <= attr < most</tt>. + */ +template< typename DescriptorT, template< typename > class ActorT, typename BoundaryT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_is_in_range< typename DescriptorT::value_type, typename boost::log::aux::make_embedded_string_type< BoundaryT >::type > > > +is_in_range(attribute_keyword< DescriptorT, ActorT > const&, BoundaryT const& least, BoundaryT const& most) +{ + typedef typename boost::log::aux::make_embedded_string_type< BoundaryT >::type boundary_type; + typedef aux::unary_function_terminal< attribute_is_in_range< typename DescriptorT::value_type, boundary_type > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), std::pair< boundary_type, boundary_type >(least, most)) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value + * is in the specified range. The range must be half-open, that is the predicate will be equivalent to <tt>least <= attr < most</tt>. + */ +template< typename T, typename BoundaryT > +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_is_in_range< T, typename boost::log::aux::make_embedded_string_type< BoundaryT >::type > > > +is_in_range(attribute_name const& name, BoundaryT const& least, BoundaryT const& most) +{ + typedef typename boost::log::aux::make_embedded_string_type< BoundaryT >::type boundary_type; + typedef aux::unary_function_terminal< attribute_is_in_range< T, boundary_type > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name, std::pair< boundary_type, boundary_type >(least, most)) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_IS_IN_RANGE_HPP_INCLUDED_ diff --git a/boost/log/expressions/predicates/matches.hpp b/boost/log/expressions/predicates/matches.hpp new file mode 100644 index 0000000000..798f2e7e4f --- /dev/null +++ b/boost/log/expressions/predicates/matches.hpp @@ -0,0 +1,119 @@ +/* + * 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 matches.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of a \c matches predicate in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_PREDICATES_MATCHES_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_PREDICATES_MATCHES_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/unary_function_terminal.hpp> +#include <boost/log/detail/attribute_predicate.hpp> +#include <boost/log/expressions/attr_fwd.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/utility/functional/matches.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * The predicate checks if the attribute value matches a regular expression. The attribute value is assumed to be of a string type. + */ +template< typename T, typename RegexT, typename FallbackPolicyT = fallback_to_none > +class attribute_matches : + public aux::attribute_predicate< T, typename boost::log::aux::match_traits< RegexT >::compiled_type, matches_fun, FallbackPolicyT > +{ + typedef aux::attribute_predicate< T, typename boost::log::aux::match_traits< RegexT >::compiled_type, matches_fun, FallbackPolicyT > base_type; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param rex The regular expression to match the attribute value against + */ + attribute_matches(attribute_name const& name, RegexT const& rex) : base_type(name, boost::log::aux::match_traits< RegexT >::compile(rex)) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param rex The regular expression to match the attribute value against + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_matches(attribute_name const& name, RegexT const& rex, U const& arg) : base_type(name, boost::log::aux::match_traits< RegexT >::compile(rex), arg) + { + } +}; + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, matches the specified regular expression. + */ +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, typename RegexT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_matches< T, RegexT, FallbackPolicyT > > > +matches(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& attr, RegexT const& rex) +{ + typedef aux::unary_function_terminal< attribute_matches< T, RegexT, FallbackPolicyT > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(attr.get_name(), rex, attr.get_fallback_policy()) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, matches the specified regular expression. + */ +template< typename DescriptorT, template< typename > class ActorT, typename RegexT > +BOOST_FORCEINLINE ActorT< aux::unary_function_terminal< attribute_matches< typename DescriptorT::value_type, RegexT > > > +matches(attribute_keyword< DescriptorT, ActorT > const&, RegexT const& rex) +{ + typedef aux::unary_function_terminal< attribute_matches< typename DescriptorT::value_type, RegexT > > terminal_type; + ActorT< terminal_type > act = {{ terminal_type(DescriptorT::get_name(), rex) }}; + return act; +} + +/*! + * The function generates a terminal node in a template expression. The node will check if the attribute value, + * which is assumed to be a string, matches the specified regular expression. + */ +template< typename T, typename RegexT > +BOOST_FORCEINLINE phoenix::actor< aux::unary_function_terminal< attribute_matches< T, RegexT > > > +matches(attribute_name const& name, RegexT const& rex) +{ + typedef aux::unary_function_terminal< attribute_matches< T, RegexT > > terminal_type; + phoenix::actor< terminal_type > act = {{ terminal_type(name, rex) }}; + return act; +} + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_PREDICATES_MATCHES_HPP_INCLUDED_ diff --git a/boost/log/expressions/record.hpp b/boost/log/expressions/record.hpp new file mode 100644 index 0000000000..d695c2aa65 --- /dev/null +++ b/boost/log/expressions/record.hpp @@ -0,0 +1,50 @@ +/* + * 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.hpp + * \author Andrey Semashev + * \date 25.07.2012 + * + * The header contains implementation of a log record placeholder in template expressions. + */ + +#ifndef BOOST_LOG_EXPRESSIONS_RECORD_HPP_INCLUDED_ +#define BOOST_LOG_EXPRESSIONS_RECORD_HPP_INCLUDED_ + +#include <boost/phoenix/core/argument.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +/*! + * Log record placeholder type in formatter template expressions. + */ +typedef phoenix::expression::argument< 1 >::type record_type; + +/*! + * Log record placeholder in formatter template expressions. + */ +const record_type record = {}; + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_EXPRESSIONS_RECORD_HPP_INCLUDED_ diff --git a/boost/log/keywords/auto_flush.hpp b/boost/log/keywords/auto_flush.hpp new file mode 100644 index 0000000000..0c3b53a6a3 --- /dev/null +++ b/boost/log/keywords/auto_flush.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/auto_flush.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c auto_flush keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_AUTO_FLUSH_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_AUTO_FLUSH_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing auto flush flag to a sink backend initialization +BOOST_PARAMETER_KEYWORD(tag, auto_flush) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_AUTO_FLUSH_HPP_INCLUDED_ diff --git a/boost/log/keywords/channel.hpp b/boost/log/keywords/channel.hpp new file mode 100644 index 0000000000..b4bbb17a8f --- /dev/null +++ b/boost/log/keywords/channel.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/channel.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c channel keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_CHANNEL_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_CHANNEL_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing channel name to the channel logger constructor +BOOST_PARAMETER_KEYWORD(tag, channel) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_CHANNEL_HPP_INCLUDED_ diff --git a/boost/log/keywords/delimiter.hpp b/boost/log/keywords/delimiter.hpp new file mode 100644 index 0000000000..80a2e70366 --- /dev/null +++ b/boost/log/keywords/delimiter.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/delimiter.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c delimiter keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_DELIMITER_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_DELIMITER_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing delimiter between scopes to the \c named_scope formatter +BOOST_PARAMETER_KEYWORD(tag, delimiter) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_DELIMITER_HPP_INCLUDED_ diff --git a/boost/log/keywords/depth.hpp b/boost/log/keywords/depth.hpp new file mode 100644 index 0000000000..87ffcc98d4 --- /dev/null +++ b/boost/log/keywords/depth.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/depth.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c depth keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_DEPTH_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_DEPTH_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing maximum scopes depth to the \c named_scope formatter +BOOST_PARAMETER_KEYWORD(tag, depth) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_DEPTH_HPP_INCLUDED_ diff --git a/boost/log/keywords/empty_marker.hpp b/boost/log/keywords/empty_marker.hpp new file mode 100644 index 0000000000..6108315be7 --- /dev/null +++ b/boost/log/keywords/empty_marker.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/empty_marker.hpp + * \author Andrey Semashev + * \date 15.03.2014 + * + * The header contains the \c empty_marker keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing the marker for the empty list of scopes to the \c named_scope formatter +BOOST_PARAMETER_KEYWORD(tag, empty_marker) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_ diff --git a/boost/log/keywords/facility.hpp b/boost/log/keywords/facility.hpp new file mode 100644 index 0000000000..04d9b91b7b --- /dev/null +++ b/boost/log/keywords/facility.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/facility.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c facility keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_FACILITY_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_FACILITY_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass syslog facility that emits log records +BOOST_PARAMETER_KEYWORD(tag, facility) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_FACILITY_HPP_INCLUDED_ diff --git a/boost/log/keywords/file_name.hpp b/boost/log/keywords/file_name.hpp new file mode 100644 index 0000000000..ce70a54ccd --- /dev/null +++ b/boost/log/keywords/file_name.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/file_name.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c file_name keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_FILE_NAME_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_FILE_NAME_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass log file name the rotating file stream methods +BOOST_PARAMETER_KEYWORD(tag, file_name) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_FILE_NAME_HPP_INCLUDED_ diff --git a/boost/log/keywords/filter.hpp b/boost/log/keywords/filter.hpp new file mode 100644 index 0000000000..7b5ab06b5f --- /dev/null +++ b/boost/log/keywords/filter.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/filter.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c filter keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_FILTER_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_FILTER_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing filters to functions +BOOST_PARAMETER_KEYWORD(tag, filter) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_FILTER_HPP_INCLUDED_ diff --git a/boost/log/keywords/format.hpp b/boost/log/keywords/format.hpp new file mode 100644 index 0000000000..1e5c450203 --- /dev/null +++ b/boost/log/keywords/format.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/format.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c format keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_FORMAT_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_FORMAT_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing format specifiers to functions +BOOST_PARAMETER_KEYWORD(tag, format) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_FORMAT_HPP_INCLUDED_ diff --git a/boost/log/keywords/ident.hpp b/boost/log/keywords/ident.hpp new file mode 100644 index 0000000000..4847cc1f4f --- /dev/null +++ b/boost/log/keywords/ident.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/ident.hpp + * \author Andrey Semashev + * \date 22.10.2012 + * + * The header contains the \c ident keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_IDENT_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_IDENT_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing process identification string to the \c openlog call +BOOST_PARAMETER_KEYWORD(tag, ident) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_IDENT_HPP_INCLUDED_ diff --git a/boost/log/keywords/incomplete_marker.hpp b/boost/log/keywords/incomplete_marker.hpp new file mode 100644 index 0000000000..1e6d3ab18e --- /dev/null +++ b/boost/log/keywords/incomplete_marker.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/incomplete_marker.hpp + * \author Andrey Semashev + * \date 15.03.2014 + * + * The header contains the \c incomplete_marker keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing incomplete marker for the list of scopes to the \c named_scope formatter +BOOST_PARAMETER_KEYWORD(tag, incomplete_marker) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_ diff --git a/boost/log/keywords/ip_version.hpp b/boost/log/keywords/ip_version.hpp new file mode 100644 index 0000000000..c788e191e5 --- /dev/null +++ b/boost/log/keywords/ip_version.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/ip_version.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c ip_version keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_IP_VERSION_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_IP_VERSION_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to indicate which version of IP protocol to use +BOOST_PARAMETER_KEYWORD(tag, ip_version) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_IP_VERSION_HPP_INCLUDED_ diff --git a/boost/log/keywords/iteration.hpp b/boost/log/keywords/iteration.hpp new file mode 100644 index 0000000000..6fee81ee95 --- /dev/null +++ b/boost/log/keywords/iteration.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/iteration.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c iteration keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_ITERATION_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_ITERATION_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword for passing scope iteration direction to the \c named_scope formatter +BOOST_PARAMETER_KEYWORD(tag, iteration) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_ITERATION_HPP_INCLUDED_ diff --git a/boost/log/keywords/log_name.hpp b/boost/log/keywords/log_name.hpp new file mode 100644 index 0000000000..e252d29722 --- /dev/null +++ b/boost/log/keywords/log_name.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/log_name.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c log_name keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_LOG_NAME_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_LOG_NAME_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass event log name to a sink backend +BOOST_PARAMETER_KEYWORD(tag, log_name) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_LOG_NAME_HPP_INCLUDED_ diff --git a/boost/log/keywords/log_source.hpp b/boost/log/keywords/log_source.hpp new file mode 100644 index 0000000000..94f51efb12 --- /dev/null +++ b/boost/log/keywords/log_source.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/log_source.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c log_source keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_LOG_SOURCE_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_LOG_SOURCE_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass event log source name to a sink backend +BOOST_PARAMETER_KEYWORD(tag, log_source) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_LOG_SOURCE_HPP_INCLUDED_ diff --git a/boost/log/keywords/max_size.hpp b/boost/log/keywords/max_size.hpp new file mode 100644 index 0000000000..5a91797fa9 --- /dev/null +++ b/boost/log/keywords/max_size.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/max_size.hpp + * \author Andrey Semashev + * \date 30.06.2009 + * + * The header contains the \c max_size keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_MAX_SIZE_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_MAX_SIZE_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to specify maximum size of the log files +BOOST_PARAMETER_KEYWORD(tag, max_size) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_MAX_SIZE_HPP_INCLUDED_ diff --git a/boost/log/keywords/message_file.hpp b/boost/log/keywords/message_file.hpp new file mode 100644 index 0000000000..2f9c8f7f3c --- /dev/null +++ b/boost/log/keywords/message_file.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/message_file.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c message_file keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_MESSAGE_FILE_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_MESSAGE_FILE_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass the name of the file with event resources to the Windows Event Log backend constructor +BOOST_PARAMETER_KEYWORD(tag, message_file) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_MESSAGE_FILE_HPP_INCLUDED_ diff --git a/boost/log/keywords/min_free_space.hpp b/boost/log/keywords/min_free_space.hpp new file mode 100644 index 0000000000..dc6958c2b8 --- /dev/null +++ b/boost/log/keywords/min_free_space.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/min_free_space.hpp + * \author Andrey Semashev + * \date 30.06.2009 + * + * The header contains the \c min_free_space keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_MIN_FREE_SPACE_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_MIN_FREE_SPACE_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to specify minimum free space on the drive +BOOST_PARAMETER_KEYWORD(tag, min_free_space) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_MIN_FREE_SPACE_HPP_INCLUDED_ diff --git a/boost/log/keywords/open_mode.hpp b/boost/log/keywords/open_mode.hpp new file mode 100644 index 0000000000..6456b42037 --- /dev/null +++ b/boost/log/keywords/open_mode.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/open_mode.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c open_mode keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_OPEN_MODE_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_OPEN_MODE_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass log file opening parameters to the rotating file stream methods +BOOST_PARAMETER_KEYWORD(tag, open_mode) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_OPEN_MODE_HPP_INCLUDED_ diff --git a/boost/log/keywords/order.hpp b/boost/log/keywords/order.hpp new file mode 100644 index 0000000000..7e2cc10708 --- /dev/null +++ b/boost/log/keywords/order.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/order.hpp + * \author Andrey Semashev + * \date 23.08.2009 + * + * The header contains the \c order keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_ORDER_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_ORDER_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass the ordering predicate to sink frontends +BOOST_PARAMETER_KEYWORD(tag, order) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_ORDER_HPP_INCLUDED_ diff --git a/boost/log/keywords/ordering_window.hpp b/boost/log/keywords/ordering_window.hpp new file mode 100644 index 0000000000..6458aba343 --- /dev/null +++ b/boost/log/keywords/ordering_window.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/ordering_window.hpp + * \author Andrey Semashev + * \date 23.08.2009 + * + * The header contains the \c ordering_window keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_ORDERING_WINDOW_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_ORDERING_WINDOW_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass the ordering window to sink frontends +BOOST_PARAMETER_KEYWORD(tag, ordering_window) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_ORDERING_WINDOW_HPP_INCLUDED_ diff --git a/boost/log/keywords/registration.hpp b/boost/log/keywords/registration.hpp new file mode 100644 index 0000000000..41db2d1972 --- /dev/null +++ b/boost/log/keywords/registration.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/registration.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c registration keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_REGISTRATION_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_REGISTRATION_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass event log source registration mode to a sink backend +BOOST_PARAMETER_KEYWORD(tag, registration) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_REGISTRATION_HPP_INCLUDED_ diff --git a/boost/log/keywords/rotation_size.hpp b/boost/log/keywords/rotation_size.hpp new file mode 100644 index 0000000000..f87841edbc --- /dev/null +++ b/boost/log/keywords/rotation_size.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/rotation_size.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c rotation_size keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_ROTATION_SIZE_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_ROTATION_SIZE_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass maximum log file size to the file sink +BOOST_PARAMETER_KEYWORD(tag, rotation_size) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_ROTATION_SIZE_HPP_INCLUDED_ diff --git a/boost/log/keywords/scan_method.hpp b/boost/log/keywords/scan_method.hpp new file mode 100644 index 0000000000..8a203de53e --- /dev/null +++ b/boost/log/keywords/scan_method.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/scan_method.hpp + * \author Andrey Semashev + * \date 30.06.2009 + * + * The header contains the \c scan_method keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_SCAN_METHOD_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_SCAN_METHOD_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to specify scanning method of the stored log files +BOOST_PARAMETER_KEYWORD(tag, scan_method) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_SCAN_METHOD_HPP_INCLUDED_ diff --git a/boost/log/keywords/severity.hpp b/boost/log/keywords/severity.hpp new file mode 100644 index 0000000000..cc40735b6b --- /dev/null +++ b/boost/log/keywords/severity.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/severity.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c severity keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_SEVERITY_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_SEVERITY_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass severity level to the severity logger methods +BOOST_PARAMETER_KEYWORD(tag, severity) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_SEVERITY_HPP_INCLUDED_ diff --git a/boost/log/keywords/start_thread.hpp b/boost/log/keywords/start_thread.hpp new file mode 100644 index 0000000000..bfe9d7cc19 --- /dev/null +++ b/boost/log/keywords/start_thread.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/start_thread.hpp + * \author Andrey Semashev + * \date 14.07.2009 + * + * The header contains the \c start_thread keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_START_THREAD_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_START_THREAD_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows enable/disable spawning a dedicated thread in the asynchronous sink frontend +BOOST_PARAMETER_KEYWORD(tag, start_thread) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_START_THREAD_HPP_INCLUDED_ diff --git a/boost/log/keywords/target.hpp b/boost/log/keywords/target.hpp new file mode 100644 index 0000000000..00e36fb1e5 --- /dev/null +++ b/boost/log/keywords/target.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/target.hpp + * \author Andrey Semashev + * \date 21.03.2009 + * + * The header contains the \c target keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_TARGET_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_TARGET_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass the target address to send log records to +BOOST_PARAMETER_KEYWORD(tag, target) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_TARGET_HPP_INCLUDED_ diff --git a/boost/log/keywords/time_based_rotation.hpp b/boost/log/keywords/time_based_rotation.hpp new file mode 100644 index 0000000000..7e613dda11 --- /dev/null +++ b/boost/log/keywords/time_based_rotation.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/time_based_rotation.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c time_based_rotation keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_TIME_BASED_ROTATION_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_TIME_BASED_ROTATION_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword allows to pass time-based file rotation predicate to the file sink backend +BOOST_PARAMETER_KEYWORD(tag, time_based_rotation) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_TIME_BASED_ROTATION_HPP_INCLUDED_ diff --git a/boost/log/keywords/use_impl.hpp b/boost/log/keywords/use_impl.hpp new file mode 100644 index 0000000000..422e4b36ea --- /dev/null +++ b/boost/log/keywords/use_impl.hpp @@ -0,0 +1,40 @@ +/* + * 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 keywords/use_impl.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * The header contains the \c use_impl keyword declaration. + */ + +#ifndef BOOST_LOG_KEYWORDS_USE_IMPL_HPP_INCLUDED_ +#define BOOST_LOG_KEYWORDS_USE_IMPL_HPP_INCLUDED_ + +#include <boost/parameter/keyword.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace keywords { + +//! The keyword is used to pass the type of backend implementation to use +BOOST_PARAMETER_KEYWORD(tag, use_impl) + +} // namespace keywords + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_KEYWORDS_USE_IMPL_HPP_INCLUDED_ diff --git a/boost/log/sinks.hpp b/boost/log/sinks.hpp new file mode 100644 index 0000000000..95a4131401 --- /dev/null +++ b/boost/log/sinks.hpp @@ -0,0 +1,47 @@ +/* + * 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 sinks.hpp + * \author Andrey Semashev + * \date 13.07.2009 + * + * This header includes other Boost.Log headers with all sinks. + */ + +#ifndef BOOST_LOG_SINKS_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/sinks/sink.hpp> + +#include <boost/log/sinks/unlocked_frontend.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/sinks/sync_frontend.hpp> +#include <boost/log/sinks/async_frontend.hpp> +#include <boost/log/sinks/unbounded_fifo_queue.hpp> +#include <boost/log/sinks/unbounded_ordering_queue.hpp> +#include <boost/log/sinks/bounded_fifo_queue.hpp> +#include <boost/log/sinks/bounded_ordering_queue.hpp> +#include <boost/log/sinks/drop_on_overflow.hpp> +#include <boost/log/sinks/block_on_overflow.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) + +#include <boost/log/sinks/syslog_backend.hpp> +#include <boost/log/sinks/text_file_backend.hpp> +#include <boost/log/sinks/text_multifile_backend.hpp> +#include <boost/log/sinks/text_ostream_backend.hpp> +#ifdef BOOST_WINDOWS +#include <boost/log/sinks/debug_output_backend.hpp> +#include <boost/log/sinks/event_log_backend.hpp> +#endif // BOOST_WINDOWS + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_SINKS_HPP_INCLUDED_ diff --git a/boost/log/sinks/async_frontend.hpp b/boost/log/sinks/async_frontend.hpp new file mode 100644 index 0000000000..d85421e8a1 --- /dev/null +++ b/boost/log/sinks/async_frontend.hpp @@ -0,0 +1,462 @@ +/* + * 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 async_frontend.hpp + * \author Andrey Semashev + * \date 14.07.2009 + * + * The header contains implementation of asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_ASYNC_FRONTEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_ASYNC_FRONTEND_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: Asynchronous sink frontend is only supported in multithreaded environment +#endif + +#include <boost/bind.hpp> +#include <boost/static_assert.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/thread/thread.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/log/exceptions.hpp> +#include <boost/log/detail/locking_ptr.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/sinks/basic_sink_frontend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/sinks/unbounded_fifo_queue.hpp> +#include <boost/log/keywords/start_thread.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, types)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit asynchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ + base_type(true),\ + queue_base_type((BOOST_PP_ENUM_PARAMS(n, arg))),\ + m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))),\ + m_StopRequested(false),\ + m_FlushRequested(false)\ + {\ + if ((BOOST_PP_ENUM_PARAMS(n, arg))[keywords::start_thread | true])\ + start_feeding_thread();\ + }\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit asynchronous_sink(shared_ptr< sink_backend_type > const& backend, BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ + base_type(true),\ + queue_base_type((BOOST_PP_ENUM_PARAMS(n, arg))),\ + m_pBackend(backend),\ + m_StopRequested(false),\ + m_FlushRequested(false)\ + {\ + if ((BOOST_PP_ENUM_PARAMS(n, arg))[keywords::start_thread | true])\ + start_feeding_thread();\ + } + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Asynchronous logging sink frontend + * + * The frontend starts a separate thread on construction. All logging records are passed + * to the backend in this dedicated thread only. + */ +template< typename SinkBackendT, typename QueueingStrategyT = unbounded_fifo_queue > +class asynchronous_sink : + public aux::make_sink_frontend_base< SinkBackendT >::type, + public QueueingStrategyT +{ + typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type; + typedef QueueingStrategyT queue_base_type; + +private: + //! Backend synchronization mutex type + typedef boost::recursive_mutex backend_mutex_type; + //! Frontend synchronization mutex type + typedef typename base_type::mutex_type frontend_mutex_type; + + //! A scope guard that implements thread ID management + class scoped_thread_id + { + private: + frontend_mutex_type& m_Mutex; + condition_variable_any& m_Cond; + thread::id& m_ThreadID; + bool volatile& m_StopRequested; + + public: + //! Initializing constructor + scoped_thread_id(frontend_mutex_type& mut, condition_variable_any& cond, thread::id& tid, bool volatile& sr) + : m_Mutex(mut), m_Cond(cond), m_ThreadID(tid), m_StopRequested(sr) + { + lock_guard< frontend_mutex_type > lock(m_Mutex); + if (m_ThreadID != thread::id()) + BOOST_LOG_THROW_DESCR(unexpected_call, "Asynchronous sink frontend already runs a record feeding thread"); + m_ThreadID = this_thread::get_id(); + } + //! Initializing constructor + scoped_thread_id(unique_lock< frontend_mutex_type >& l, condition_variable_any& cond, thread::id& tid, bool volatile& sr) + : m_Mutex(*l.mutex()), m_Cond(cond), m_ThreadID(tid), m_StopRequested(sr) + { + unique_lock< frontend_mutex_type > lock(move(l)); + if (m_ThreadID != thread::id()) + BOOST_LOG_THROW_DESCR(unexpected_call, "Asynchronous sink frontend already runs a record feeding thread"); + m_ThreadID = this_thread::get_id(); + } + //! Destructor + ~scoped_thread_id() + { + try + { + lock_guard< frontend_mutex_type > lock(m_Mutex); + m_StopRequested = false; + m_ThreadID = thread::id(); + m_Cond.notify_all(); + } + catch (...) + { + } + } + + private: + scoped_thread_id(scoped_thread_id const&); + scoped_thread_id& operator= (scoped_thread_id const&); + }; + + //! A scope guard that resets a flag on destructor + class scoped_flag + { + private: + frontend_mutex_type& m_Mutex; + condition_variable_any& m_Cond; + volatile bool& m_Flag; + + public: + explicit scoped_flag(frontend_mutex_type& mut, condition_variable_any& cond, volatile bool& f) : + m_Mutex(mut), m_Cond(cond), m_Flag(f) + { + } + ~scoped_flag() + { + try + { + lock_guard< frontend_mutex_type > lock(m_Mutex); + m_Flag = false; + m_Cond.notify_all(); + } + catch (...) + { + } + } + + private: + scoped_flag(scoped_flag const&); + scoped_flag& operator= (scoped_flag const&); + }; + +public: + //! Sink implementation type + typedef SinkBackendT sink_backend_type; + //! \cond + BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, synchronized_feeding >::value), "Asynchronous sink frontend is incompatible with the specified backend: thread synchronization requirements are not met"); + //! \endcond + +#ifndef BOOST_LOG_DOXYGEN_PASS + + //! A pointer type that locks the backend until it's destroyed + typedef boost::log::aux::locking_ptr< sink_backend_type, backend_mutex_type > locked_backend_ptr; + +#else // BOOST_LOG_DOXYGEN_PASS + + //! A pointer type that locks the backend until it's destroyed + typedef implementation_defined locked_backend_ptr; + +#endif // BOOST_LOG_DOXYGEN_PASS + +private: + //! Synchronization mutex + backend_mutex_type m_BackendMutex; + //! Pointer to the backend + const shared_ptr< sink_backend_type > m_pBackend; + + //! Dedicated record feeding thread + thread m_DedicatedFeedingThread; + //! Feeding thread ID + thread::id m_FeedingThreadID; + //! Condition variable to implement blocking operations + condition_variable_any m_BlockCond; + + //! The flag indicates that the feeding loop has to be stopped + volatile bool m_StopRequested; // TODO: make it a real atomic + //! The flag indicates that queue flush has been requested + volatile bool m_FlushRequested; // TODO: make it a real atomic + +public: + /*! + * Default constructor. Constructs the sink backend instance. + * Requires the backend to be default-constructible. + * + * \param start_thread If \c true, the frontend creates a thread to feed + * log records to the backend. Otherwise no thread is + * started and it is assumed that the user will call + * either \c run or \c feed_records himself. + */ + asynchronous_sink(bool start_thread = true) : + base_type(true), + m_pBackend(boost::make_shared< sink_backend_type >()), + m_StopRequested(false), + m_FlushRequested(false) + { + if (start_thread) + start_feeding_thread(); + } + /*! + * Constructor attaches user-constructed backend instance + * + * \param backend Pointer to the backend instance. + * \param start_thread If \c true, the frontend creates a thread to feed + * log records to the backend. Otherwise no thread is + * started and it is assumed that the user will call + * either \c run or \c feed_records himself. + * + * \pre \a backend is not \c NULL. + */ + explicit asynchronous_sink(shared_ptr< sink_backend_type > const& backend, bool start_thread = true) : + base_type(true), + m_pBackend(backend), + m_StopRequested(false), + m_FlushRequested(false) + { + if (start_thread) + start_feeding_thread(); + } + + // Constructors that pass arbitrary parameters to the backend constructor + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~) + + /*! + * Destructor. Implicitly stops the dedicated feeding thread, if one is running. + */ + ~asynchronous_sink() + { + boost::this_thread::disable_interruption no_interrupts; + stop(); + } + + /*! + * Locking accessor to the attached backend + */ + locked_backend_ptr locked_backend() + { + return locked_backend_ptr(m_pBackend, m_BackendMutex); + } + + /*! + * Enqueues the log record to the backend + */ + void consume(record_view const& rec) + { + if (m_FlushRequested) + { + unique_lock< frontend_mutex_type > lock(base_type::frontend_mutex()); + // Wait until flush is done + while (m_FlushRequested) + m_BlockCond.wait(lock); + } + queue_base_type::enqueue(rec); + } + + /*! + * The method attempts to pass logging record to the backend + */ + bool try_consume(record_view const& rec) + { + if (!m_FlushRequested) + { + return queue_base_type::try_enqueue(rec); + } + else + return false; + } + + /*! + * The method starts record feeding loop and effectively blocks until either of this happens: + * + * \li the thread is interrupted due to either standard thread interruption or a call to \c stop + * \li an exception is thrown while processing a log record in the backend, and the exception is + * not terminated by the exception handler, if one is installed + * + * \pre The sink frontend must be constructed without spawning a dedicated thread + */ + void run() + { + // First check that no other thread is running + scoped_thread_id guard(base_type::frontend_mutex(), m_BlockCond, m_FeedingThreadID, m_StopRequested); + + // Now start the feeding loop + while (true) + { + do_feed_records(); + if (!m_StopRequested) + { + // Block until new record is available + record_view rec; + if (queue_base_type::dequeue_ready(rec)) + base_type::feed_record(rec, m_BackendMutex, *m_pBackend); + } + else + break; + } + } + + /*! + * The method softly interrupts record feeding loop. This method must be called when the \c run + * method execution has to be interrupted. Unlike regular thread interruption, calling + * \c stop will not interrupt the record processing in the middle. Instead, the sink frontend + * will attempt to finish its business with the record in progress and return afterwards. + * This method can be called either if the sink was created with a dedicated thread, + * or if the feeding loop was initiated by user. + * + * \note Returning from this method does not guarantee that there are no records left buffered + * in the sink frontend. It is possible that log records keep coming during and after this + * method is called. At some point of execution of this method log records stop being processed, + * and all records that come after this point are put into the queue. These records will be + * processed upon further calls to \c run or \c feed_records. + */ + void stop() + { + unique_lock< frontend_mutex_type > lock(base_type::frontend_mutex()); + if (m_FeedingThreadID != thread::id() || m_DedicatedFeedingThread.joinable()) + { + try + { + m_StopRequested = true; + queue_base_type::interrupt_dequeue(); + while (m_StopRequested) + m_BlockCond.wait(lock); + } + catch (...) + { + m_StopRequested = false; + throw; + } + + lock.unlock(); + m_DedicatedFeedingThread.join(); + } + } + + /*! + * The method feeds log records that may have been buffered to the backend and returns + * + * \pre The sink frontend must be constructed without spawning a dedicated thread + */ + void feed_records() + { + // First check that no other thread is running + scoped_thread_id guard(base_type::frontend_mutex(), m_BlockCond, m_FeedingThreadID, m_StopRequested); + + // Now start the feeding loop + do_feed_records(); + } + + /*! + * The method feeds all log records that may have been buffered to the backend and returns. + * Unlike \c feed_records, in case of ordering queueing the method also feeds records + * that were enqueued during the ordering window, attempting to empty the queue completely. + * + * \pre The sink frontend must be constructed without spawning a dedicated thread + */ + void flush() + { + unique_lock< frontend_mutex_type > lock(base_type::frontend_mutex()); + if (m_FeedingThreadID != thread::id() || m_DedicatedFeedingThread.joinable()) + { + // There is already a thread feeding records, let it do the job + m_FlushRequested = true; + queue_base_type::interrupt_dequeue(); + while (!m_StopRequested && m_FlushRequested) + m_BlockCond.wait(lock); + + // The condition may have been signalled when the feeding thread was finishing. + // In that case records may not have been flushed, and we do the flush ourselves. + if (m_FeedingThreadID != thread::id()) + return; + } + + m_FlushRequested = true; + + // Flush records ourselves. The guard releases the lock. + scoped_thread_id guard(lock, m_BlockCond, m_FeedingThreadID, m_StopRequested); + + do_feed_records(); + } + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! The method spawns record feeding thread + void start_feeding_thread() + { + boost::thread(boost::bind(&asynchronous_sink::run, this)).swap(m_DedicatedFeedingThread); + } + + //! The record feeding loop + void do_feed_records() + { + while (!m_StopRequested) + { + record_view rec; + bool dequeued = false; + if (!m_FlushRequested) + dequeued = queue_base_type::try_dequeue_ready(rec); + else + dequeued = queue_base_type::try_dequeue(rec); + + if (dequeued) + base_type::feed_record(rec, m_BackendMutex, *m_pBackend); + else + break; + } + + if (m_FlushRequested) + { + scoped_flag guard(base_type::frontend_mutex(), m_BlockCond, m_FlushRequested); + base_type::flush_backend(m_BackendMutex, *m_pBackend); + } + } +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_ASYNC_FRONTEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/attribute_mapping.hpp b/boost/log/sinks/attribute_mapping.hpp new file mode 100644 index 0000000000..a336265ff4 --- /dev/null +++ b/boost/log/sinks/attribute_mapping.hpp @@ -0,0 +1,290 @@ +/* + * 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 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_ diff --git a/boost/log/sinks/basic_sink_backend.hpp b/boost/log/sinks/basic_sink_backend.hpp new file mode 100644 index 0000000000..9517bd2803 --- /dev/null +++ b/boost/log/sinks/basic_sink_backend.hpp @@ -0,0 +1,97 @@ +/* + * 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 basic_sink_backend.hpp + * \author Andrey Semashev + * \date 04.11.2007 + * + * The header contains implementation of base classes for sink backends. + */ + +#ifndef BOOST_LOG_SINKS_BASIC_SINK_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_BASIC_SINK_BACKEND_HPP_INCLUDED_ + +#include <string> +#include <boost/type_traits/is_same.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Base class for a logging sink backend + * + * The \c basic_sink_backend class template defines a number of types that + * all sink backends are required to define. All sink backends have to derive from the class. + */ +template< typename FrontendRequirementsT > +struct basic_sink_backend +{ + //! Frontend requirements tag + typedef FrontendRequirementsT frontend_requirements; + + BOOST_DEFAULTED_FUNCTION(basic_sink_backend(), {}) + + BOOST_DELETED_FUNCTION(basic_sink_backend(basic_sink_backend const&)) + BOOST_DELETED_FUNCTION(basic_sink_backend& operator= (basic_sink_backend const&)) +}; + +/*! + * \brief A base class for a logging sink backend with message formatting support + * + * The \c basic_formatted_sink_backend class template indicates to the frontend that + * the backend requires logging record formatting. + * + * The class allows to request encoding conversion in case if the sink backend + * requires the formatted string in some particular encoding (e.g. if underlying API + * supports only narrow or wide characters). In order to perform conversion one + * should specify the desired final character type in the \c TargetCharT template + * parameter. + */ +template< + typename CharT, + typename FrontendRequirementsT = synchronized_feeding +> +struct basic_formatted_sink_backend : + public basic_sink_backend< + typename combine_requirements< FrontendRequirementsT, formatted_records >::type + > +{ +private: + typedef basic_sink_backend< + typename combine_requirements< FrontendRequirementsT, formatted_records >::type + > base_type; + +public: + //! Character type + typedef CharT char_type; + //! Formatted string type + typedef std::basic_string< char_type > string_type; + //! Frontend requirements + typedef typename base_type::frontend_requirements frontend_requirements; +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_BASIC_SINK_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/basic_sink_frontend.hpp b/boost/log/sinks/basic_sink_frontend.hpp new file mode 100644 index 0000000000..3072cae6dc --- /dev/null +++ b/boost/log/sinks/basic_sink_frontend.hpp @@ -0,0 +1,524 @@ +/* + * 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 basic_sink_frontend.hpp + * \author Andrey Semashev + * \date 14.07.2009 + * + * The header contains implementation of a base class for sink frontends. + */ + +#ifndef BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/cleanup_scope_guard.hpp> +#include <boost/log/detail/code_conversion.hpp> +#include <boost/log/detail/attachable_sstream_buf.hpp> +#include <boost/log/detail/fake_mutex.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/sinks/sink.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/expressions/filter.hpp> +#include <boost/log/expressions/formatter.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/thread/exceptions.hpp> +#include <boost/thread/tss.hpp> +#include <boost/thread/locks.hpp> +#include <boost/log/detail/locks.hpp> +#include <boost/log/detail/light_rw_mutex.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +//! A base class for a logging sink frontend +class BOOST_LOG_NO_VTABLE basic_sink_frontend : + public sink +{ + //! Base type + typedef sink base_type; + +public: + //! An exception handler type + typedef base_type::exception_handler_type exception_handler_type; + +#if !defined(BOOST_LOG_NO_THREADS) +protected: + //! Mutex type + typedef boost::log::aux::light_rw_mutex mutex_type; + +private: + //! Synchronization mutex + mutable mutex_type m_Mutex; +#endif + +private: + //! Filter + filter m_Filter; + //! Exception handler + exception_handler_type m_ExceptionHandler; + +public: + /*! + * \brief Initializing constructor + * + * \param cross_thread The flag indicates whether the sink passes log records between different threads + */ + explicit basic_sink_frontend(bool cross_thread) : sink(cross_thread) + { + } + + /*! + * The method sets sink-specific filter functional object + */ + template< typename FunT > + void set_filter(FunT const& filter) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) + m_Filter = filter; + } + /*! + * The method resets the filter + */ + void reset_filter() + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) + m_Filter.reset(); + } + + /*! + * The method sets an exception handler function + */ + template< typename FunT > + void set_exception_handler(FunT const& handler) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) + m_ExceptionHandler = handler; + } + + /*! + * The method resets the exception handler function + */ + void reset_exception_handler() + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) + m_ExceptionHandler.clear(); + } + + /*! + * The method returns \c true if no filter is set or the attribute values pass the filter + * + * \param attrs A set of attribute values of a logging record + */ + bool will_consume(attribute_value_set const& attrs) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);) + try + { + return m_Filter(attrs); + } +#if !defined(BOOST_LOG_NO_THREADS) + catch (thread_interrupted&) + { + throw; + } +#endif + catch (...) + { + if (m_ExceptionHandler.empty()) + throw; + m_ExceptionHandler(); + return false; + } + } + +protected: +#if !defined(BOOST_LOG_NO_THREADS) + //! Returns reference to the frontend mutex + mutex_type& frontend_mutex() const { return m_Mutex; } +#endif + + //! Returns reference to the exception handler + exception_handler_type& exception_handler() { return m_ExceptionHandler; } + //! Returns reference to the exception handler + exception_handler_type const& exception_handler() const { return m_ExceptionHandler; } + + //! Feeds log record to the backend + template< typename BackendMutexT, typename BackendT > + void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) + { + try + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);) + backend.consume(rec); + } +#if !defined(BOOST_LOG_NO_THREADS) + catch (thread_interrupted&) + { + throw; + } +#endif + catch (...) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);) + if (m_ExceptionHandler.empty()) + throw; + m_ExceptionHandler(); + } + } + + //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked + template< typename BackendMutexT, typename BackendT > + bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) + { +#if !defined(BOOST_LOG_NO_THREADS) + unique_lock< BackendMutexT > lock; + try + { + unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock); + if (!tmp_lock.owns_lock()) + return false; + lock.swap(tmp_lock); + } + catch (thread_interrupted&) + { + throw; + } + catch (...) + { + boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex()); + if (this->exception_handler().empty()) + throw; + this->exception_handler()(); + return false; + } +#endif + // No need to lock anything in the feed_record method + boost::log::aux::fake_mutex m; + feed_record(rec, m, backend); + return true; + } + + //! Flushes record buffers in the backend, if one supports it + template< typename BackendMutexT, typename BackendT > + void flush_backend(BackendMutexT& backend_mutex, BackendT& backend) + { + typedef typename BackendT::frontend_requirements frontend_requirements; + flush_backend_impl(backend_mutex, backend, + typename has_requirement< frontend_requirements, flushing >::type()); + } + +private: + //! Flushes record buffers in the backend (the actual implementation) + template< typename BackendMutexT, typename BackendT > + void flush_backend_impl(BackendMutexT& backend_mutex, BackendT& backend, mpl::true_) + { + try + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);) + backend.flush(); + } +#if !defined(BOOST_LOG_NO_THREADS) + catch (thread_interrupted&) + { + throw; + } +#endif + catch (...) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);) + if (m_ExceptionHandler.empty()) + throw; + m_ExceptionHandler(); + } + } + //! Flushes record buffers in the backend (stub for backends that don't support flushing) + template< typename BackendMutexT, typename BackendT > + void flush_backend_impl(BackendMutexT&, BackendT&, mpl::false_) + { + } +}; + +//! A base class for a logging sink frontend with formatting support +template< typename CharT > +class BOOST_LOG_NO_VTABLE basic_formatting_sink_frontend : + public basic_sink_frontend +{ + typedef basic_sink_frontend base_type; + +public: + //! Character type + typedef CharT char_type; + //! Formatted string type + typedef std::basic_string< char_type > string_type; + + //! Formatter function object type + typedef basic_formatter< char_type > formatter_type; + //! Output stream type + typedef typename formatter_type::stream_type stream_type; + +#if !defined(BOOST_LOG_NO_THREADS) +protected: + //! Mutex type + typedef typename base_type::mutex_type mutex_type; +#endif + +private: + struct formatting_context + { +#if !defined(BOOST_LOG_NO_THREADS) + //! Object version + const unsigned int m_Version; +#endif + //! Formatted log record storage + string_type m_FormattedRecord; + //! Formatting stream + stream_type m_FormattingStream; + //! Formatter functor + formatter_type m_Formatter; + + formatting_context() : +#if !defined(BOOST_LOG_NO_THREADS) + m_Version(0), +#endif + m_FormattingStream(m_FormattedRecord) + { + m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); + } +#if !defined(BOOST_LOG_NO_THREADS) + formatting_context(unsigned int version, std::locale const& loc, formatter_type const& formatter) : + m_Version(version), + m_FormattingStream(m_FormattedRecord), + m_Formatter(formatter) + { + m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); + m_FormattingStream.imbue(loc); + } +#endif + }; + +private: +#if !defined(BOOST_LOG_NO_THREADS) + + //! State version + volatile unsigned int m_Version; + + //! Formatter functor + formatter_type m_Formatter; + //! Locale to perform formatting + std::locale m_Locale; + + //! Formatting state + thread_specific_ptr< formatting_context > m_pContext; + +#else + + //! Formatting state + formatting_context m_Context; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +public: + /*! + * \brief Initializing constructor + * + * \param cross_thread The flag indicates whether the sink passes log records between different threads + */ + explicit basic_formatting_sink_frontend(bool cross_thread) : + basic_sink_frontend(cross_thread) +#if !defined(BOOST_LOG_NO_THREADS) + , m_Version(0) +#endif + { + } + + /*! + * The method sets sink-specific formatter function object + */ + template< typename FunT > + void set_formatter(FunT const& formatter) + { +#if !defined(BOOST_LOG_NO_THREADS) + boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); + m_Formatter = formatter; + ++m_Version; +#else + m_Context.m_Formatter = formatter; +#endif + } + /*! + * The method resets the formatter + */ + void reset_formatter() + { +#if !defined(BOOST_LOG_NO_THREADS) + boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); + m_Formatter.reset(); + ++m_Version; +#else + m_Context.m_Formatter.reset(); +#endif + } + + /*! + * The method returns the current locale used for formatting + */ + std::locale getloc() const + { +#if !defined(BOOST_LOG_NO_THREADS) + boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); + return m_Locale; +#else + return m_Context.m_FormattingStream.getloc(); +#endif + } + /*! + * The method sets the locale used for formatting + */ + void imbue(std::locale const& loc) + { +#if !defined(BOOST_LOG_NO_THREADS) + boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); + m_Locale = loc; + ++m_Version; +#else + m_Context.m_FormattingStream.imbue(loc); +#endif + } + +protected: + //! Returns reference to the formatter + formatter_type& formatter() + { +#if !defined(BOOST_LOG_NO_THREADS) + return m_Formatter; +#else + return m_Context.m_Formatter; +#endif + } + + //! Feeds log record to the backend + template< typename BackendMutexT, typename BackendT > + void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) + { + formatting_context* context; + +#if !defined(BOOST_LOG_NO_THREADS) + context = m_pContext.get(); + if (!context || context->m_Version != m_Version) + { + { + boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex()); + context = new formatting_context(m_Version, m_Locale, m_Formatter); + } + m_pContext.reset(context); + } +#else + context = &m_Context; +#endif + + boost::log::aux::cleanup_guard< stream_type > cleanup1(context->m_FormattingStream); + boost::log::aux::cleanup_guard< string_type > cleanup2(context->m_FormattedRecord); + + try + { + // Perform the formatting + context->m_Formatter(rec, context->m_FormattingStream); + context->m_FormattingStream.flush(); + + // Feed the record + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);) + backend.consume(rec, context->m_FormattedRecord); + } +#if !defined(BOOST_LOG_NO_THREADS) + catch (thread_interrupted&) + { + throw; + } +#endif + catch (...) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex());) + if (this->exception_handler().empty()) + throw; + this->exception_handler()(); + } + } + + //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked + template< typename BackendMutexT, typename BackendT > + bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) + { +#if !defined(BOOST_LOG_NO_THREADS) + unique_lock< BackendMutexT > lock; + try + { + unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock); + if (!tmp_lock.owns_lock()) + return false; + lock.swap(tmp_lock); + } + catch (thread_interrupted&) + { + throw; + } + catch (...) + { + boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex()); + if (this->exception_handler().empty()) + throw; + this->exception_handler()(); + return false; + } +#endif + // No need to lock anything in the feed_record method + boost::log::aux::fake_mutex m; + feed_record(rec, m, backend); + return true; + } +}; + +namespace aux { + + template< + typename BackendT, + bool RequiresFormattingV = has_requirement< + typename BackendT::frontend_requirements, + formatted_records + >::value + > + struct make_sink_frontend_base + { + typedef basic_sink_frontend type; + }; + template< typename BackendT > + struct make_sink_frontend_base< BackendT, true > + { + typedef basic_formatting_sink_frontend< typename BackendT::char_type > type; + }; + +} // namespace aux + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/block_on_overflow.hpp b/boost/log/sinks/block_on_overflow.hpp new file mode 100644 index 0000000000..a23b5ff875 --- /dev/null +++ b/boost/log/sinks/block_on_overflow.hpp @@ -0,0 +1,147 @@ +/* + * 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 block_on_overflow.hpp + * \author Andrey Semashev + * \date 04.01.2012 + * + * The header contains implementation of \c block_on_overflow strategy for handling + * queue overflows in bounded queues for the asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: This header content is only supported in multithreaded environment +#endif + +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/list.hpp> +#include <boost/intrusive/list_hook.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Blocking strategy for handling log record queue overflows + * + * This strategy will cause enqueueing threads to block when the + * log record queue overflows. The blocked threads will be woken as + * soon as there appears free space in the queue, in the same order + * they attempted to enqueue records. + */ +class block_on_overflow +{ +#ifndef BOOST_LOG_DOXYGEN_PASS +private: + typedef intrusive::list_base_hook< + intrusive::link_mode< intrusive::auto_unlink > + > thread_context_hook_t; + + struct thread_context : + public thread_context_hook_t + { + condition_variable cond; + bool result; + + thread_context() : result(true) {} + }; + + typedef intrusive::list< + thread_context, + intrusive::base_hook< thread_context_hook_t >, + intrusive::constant_time_size< false > + > thread_contexts; + +private: + //! Blocked threads + thread_contexts m_thread_contexts; + +public: + /*! + * Default constructor. + */ + BOOST_DEFAULTED_FUNCTION(block_on_overflow(), {}) + + /*! + * This method is called by the queue when overflow is detected. + * + * \param lock An internal lock that protects the queue + * + * \retval true Attempt to enqueue the record again. + * \retval false Discard the record. + */ + template< typename LockT > + bool on_overflow(record_view const&, LockT& lock) + { + thread_context context; + m_thread_contexts.push_back(context); + do + { + context.cond.wait(lock); + } + while (context.is_linked()); + + return context.result; + } + + /*! + * This method is called by the queue when there appears a free space. + * The internal lock protecting the queue is locked when calling this method. + */ + void on_queue_space_available() + { + if (!m_thread_contexts.empty()) + { + m_thread_contexts.front().cond.notify_one(); + m_thread_contexts.pop_front(); + } + } + + /*! + * This method is called by the queue to interrupt any possible waits in \c on_overflow. + * The internal lock protecting the queue is locked when calling this method. + */ + void interrupt() + { + while (!m_thread_contexts.empty()) + { + thread_context& context = m_thread_contexts.front(); + context.result = false; + context.cond.notify_one(); + m_thread_contexts.pop_front(); + } + } + + // Copying prohibited + BOOST_DELETED_FUNCTION(block_on_overflow(block_on_overflow const&)) + BOOST_DELETED_FUNCTION(block_on_overflow& operator= (block_on_overflow const&)) +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_ diff --git a/boost/log/sinks/bounded_fifo_queue.hpp b/boost/log/sinks/bounded_fifo_queue.hpp new file mode 100644 index 0000000000..59b157e259 --- /dev/null +++ b/boost/log/sinks/bounded_fifo_queue.hpp @@ -0,0 +1,192 @@ +/* + * 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 bounded_fifo_queue.hpp + * \author Andrey Semashev + * \date 04.01.2012 + * + * The header contains implementation of bounded FIFO queueing strategy for + * the asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: This header content is only supported in multithreaded environment +#endif + +#include <cstddef> +#include <queue> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Bounded FIFO log record queueing strategy + * + * The \c bounded_fifo_queue class is intended to be used with + * the \c asynchronous_sink frontend as a log record queueing strategy. + * + * This strategy describes log record queueing logic. + * The queue has a limited capacity, upon reaching which the enqueue operation will + * invoke the overflow handling strategy specified in the \c OverflowStrategyT + * template parameter to handle the situation. The library provides overflow handling + * strategies for most common cases: \c drop_on_overflow will silently discard the log record, + * and \c block_on_overflow will put the enqueueing thread to wait until there is space + * in the queue. + * + * The log record queue imposes no ordering over the queued + * elements aside from the order in which they are enqueued. + */ +template< std::size_t MaxQueueSizeV, typename OverflowStrategyT > +class bounded_fifo_queue : + private OverflowStrategyT +{ +private: + typedef OverflowStrategyT overflow_strategy; + typedef std::queue< record_view > queue_type; + typedef boost::mutex mutex_type; + +private: + //! Synchronization primitive + mutex_type m_mutex; + //! Condition to block the consuming thread on + condition_variable m_cond; + //! Log record queue + queue_type m_queue; + //! Interruption flag + bool m_interruption_requested; + +protected: + //! Default constructor + bounded_fifo_queue() : m_interruption_requested(false) + { + } + //! Initializing constructor + template< typename ArgsT > + explicit bounded_fifo_queue(ArgsT const&) : m_interruption_requested(false) + { + } + + //! Enqueues log record to the queue + void enqueue(record_view const& rec) + { + unique_lock< mutex_type > lock(m_mutex); + std::size_t size = m_queue.size(); + for (; size >= MaxQueueSizeV; size = m_queue.size()) + { + if (!overflow_strategy::on_overflow(rec, lock)) + return; + } + + m_queue.push(rec); + if (size == 0) + m_cond.notify_one(); + } + + //! Attempts to enqueue log record to the queue + bool try_enqueue(record_view const& rec) + { + unique_lock< mutex_type > lock(m_mutex, try_to_lock); + if (lock.owns_lock()) + { + const std::size_t size = m_queue.size(); + + // Do not invoke the bounding strategy in case of overflow as it may block + if (size < MaxQueueSizeV) + { + m_queue.push(rec); + if (size == 0) + m_cond.notify_one(); + return true; + } + } + + return false; + } + + //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty + bool try_dequeue_ready(record_view& rec) + { + return try_dequeue(rec); + } + + //! Attempts to dequeue log record from the queue, does not block if the queue is empty + bool try_dequeue(record_view& rec) + { + lock_guard< mutex_type > lock(m_mutex); + const std::size_t size = m_queue.size(); + if (size > 0) + { + rec.swap(m_queue.front()); + m_queue.pop(); + overflow_strategy::on_queue_space_available(); + return true; + } + + return false; + } + + //! Dequeues log record from the queue, blocks if the queue is empty + bool dequeue_ready(record_view& rec) + { + unique_lock< mutex_type > lock(m_mutex); + + while (!m_interruption_requested) + { + const std::size_t size = m_queue.size(); + if (size > 0) + { + rec.swap(m_queue.front()); + m_queue.pop(); + overflow_strategy::on_queue_space_available(); + return true; + } + else + { + m_cond.wait(lock); + } + } + m_interruption_requested = false; + + return false; + } + + //! Wakes a thread possibly blocked in the \c dequeue method + void interrupt_dequeue() + { + lock_guard< mutex_type > lock(m_mutex); + m_interruption_requested = true; + overflow_strategy::interrupt(); + m_cond.notify_one(); + } +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_ diff --git a/boost/log/sinks/bounded_ordering_queue.hpp b/boost/log/sinks/bounded_ordering_queue.hpp new file mode 100644 index 0000000000..76fe8d6044 --- /dev/null +++ b/boost/log/sinks/bounded_ordering_queue.hpp @@ -0,0 +1,262 @@ +/* + * 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 bounded_ordering_queue.hpp + * \author Andrey Semashev + * \date 06.01.2012 + * + * The header contains implementation of bounded ordering queueing strategy for + * the asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_BOUNDED_ORDERING_QUEUE_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_BOUNDED_ORDERING_QUEUE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: This header content is only supported in multithreaded environment +#endif + +#include <cstddef> +#include <queue> +#include <vector> +#include <boost/cstdint.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/log/detail/timestamp.hpp> +#include <boost/log/detail/enqueued_record.hpp> +#include <boost/log/keywords/order.hpp> +#include <boost/log/keywords/ordering_window.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Bounded ordering log record queueing strategy + * + * The \c bounded_ordering_queue class is intended to be used with + * the \c asynchronous_sink frontend as a log record queueing strategy. + * + * This strategy provides the following properties to the record queueing mechanism: + * + * \li The queue has limited capacity specified by the \c MaxQueueSizeV template parameter. + * \li Upon reaching the size limit, the queue invokes the overflow handling strategy + * specified in the \c OverflowStrategyT template parameter to handle the situation. + * The library provides overflow handling strategies for most common cases: + * \c drop_on_overflow will silently discard the log record, and \c block_on_overflow + * will put the enqueueing thread to wait until there is space in the queue. + * \li The queue has a fixed latency window. This means that each log record put + * into the queue will normally not be dequeued for a certain period of time. + * \li The queue performs stable record ordering within the latency window. + * The ordering predicate can be specified in the \c OrderT template parameter. + */ +template< typename OrderT, std::size_t MaxQueueSizeV, typename OverflowStrategyT > +class bounded_ordering_queue : + private OverflowStrategyT +{ +private: + typedef OverflowStrategyT overflow_strategy; + typedef boost::mutex mutex_type; + typedef sinks::aux::enqueued_record enqueued_record; + + typedef std::priority_queue< + enqueued_record, + std::vector< enqueued_record >, + enqueued_record::order< OrderT > + > queue_type; + +private: + //! Ordering window duration, in milliseconds + const uint64_t m_ordering_window; + //! Synchronization primitive + mutex_type m_mutex; + //! Condition to block the consuming thread on + condition_variable m_cond; + //! Log record queue + queue_type m_queue; + //! Interruption flag + bool m_interruption_requested; + +public: + /*! + * Returns ordering window size specified during initialization + */ + posix_time::time_duration get_ordering_window() const + { + return posix_time::milliseconds(m_ordering_window); + } + + /*! + * Returns default ordering window size. + * The default window size is specific to the operating system thread scheduling mechanism. + */ + static posix_time::time_duration get_default_ordering_window() + { + // The main idea behind this parameter is that the ordering window should be large enough + // to allow the frontend to order records from different threads on an attribute + // that contains system time. Thus this value should be: + // * No less than the minimum time resolution quant that Boost.DateTime provides on the current OS. + // For instance, on Windows it defaults to around 15-16 ms. + // * No less than thread switching quant on the current OS. For now 30 ms is large enough window size to + // switch threads on any known OS. It can be tuned for other platforms as needed. + return posix_time::milliseconds(30); + } + +protected: + //! Initializing constructor + template< typename ArgsT > + explicit bounded_ordering_queue(ArgsT const& args) : + m_ordering_window(args[keywords::ordering_window || &bounded_ordering_queue::get_default_ordering_window].total_milliseconds()), + m_queue(args[keywords::order]), + m_interruption_requested(false) + { + } + + //! Enqueues log record to the queue + void enqueue(record_view const& rec) + { + unique_lock< mutex_type > lock(m_mutex); + std::size_t size = m_queue.size(); + for (; size >= MaxQueueSizeV; size = m_queue.size()) + { + if (!overflow_strategy::on_overflow(rec, lock)) + return; + } + + m_queue.push(enqueued_record(rec)); + if (size == 0) + m_cond.notify_one(); + } + + //! Attempts to enqueue log record to the queue + bool try_enqueue(record_view const& rec) + { + unique_lock< mutex_type > lock(m_mutex, try_to_lock); + if (lock.owns_lock()) + { + const std::size_t size = m_queue.size(); + + // Do not invoke the bounding strategy in case of overflow as it may block + if (size < MaxQueueSizeV) + { + m_queue.push(enqueued_record(rec)); + if (size == 0) + m_cond.notify_one(); + return true; + } + } + + return false; + } + + //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty + bool try_dequeue_ready(record_view& rec) + { + lock_guard< mutex_type > lock(m_mutex); + const std::size_t size = m_queue.size(); + if (size > 0) + { + const boost::log::aux::timestamp now = boost::log::aux::get_timestamp(); + enqueued_record const& elem = m_queue.top(); + if (static_cast< uint64_t >((now - elem.m_timestamp).milliseconds()) >= m_ordering_window) + { + // We got a new element + rec = elem.m_record; + m_queue.pop(); + overflow_strategy::on_queue_space_available(); + return true; + } + } + + return false; + } + + //! Attempts to dequeue log record from the queue, does not block if the queue is empty + bool try_dequeue(record_view& rec) + { + lock_guard< mutex_type > lock(m_mutex); + const std::size_t size = m_queue.size(); + if (size > 0) + { + enqueued_record const& elem = m_queue.top(); + rec = elem.m_record; + m_queue.pop(); + overflow_strategy::on_queue_space_available(); + return true; + } + + return false; + } + + //! Dequeues log record from the queue, blocks if the queue is empty + bool dequeue_ready(record_view& rec) + { + unique_lock< mutex_type > lock(m_mutex); + + while (!m_interruption_requested) + { + const std::size_t size = m_queue.size(); + if (size > 0) + { + const boost::log::aux::timestamp now = boost::log::aux::get_timestamp(); + enqueued_record const& elem = m_queue.top(); + const uint64_t difference = (now - elem.m_timestamp).milliseconds(); + if (difference >= m_ordering_window) + { + rec = elem.m_record; + m_queue.pop(); + overflow_strategy::on_queue_space_available(); + return true; + } + else + { + // Wait until the element becomes ready to be processed + m_cond.timed_wait(lock, posix_time::milliseconds(m_ordering_window - difference)); + } + } + else + { + m_cond.wait(lock); + } + } + m_interruption_requested = false; + + return false; + } + + //! Wakes a thread possibly blocked in the \c dequeue method + void interrupt_dequeue() + { + lock_guard< mutex_type > lock(m_mutex); + m_interruption_requested = true; + overflow_strategy::interrupt(); + m_cond.notify_one(); + } +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_BOUNDED_ORDERING_QUEUE_HPP_INCLUDED_ diff --git a/boost/log/sinks/debug_output_backend.hpp b/boost/log/sinks/debug_output_backend.hpp new file mode 100644 index 0000000000..034390595a --- /dev/null +++ b/boost/log/sinks/debug_output_backend.hpp @@ -0,0 +1,93 @@ +/* + * 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 debug_output_backend.hpp + * \author Andrey Semashev + * \date 07.11.2008 + * + * The header contains a logging sink backend that outputs log records to the debugger. + */ + +#ifndef BOOST_LOG_SINKS_DEBUG_OUTPUT_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_DEBUG_OUTPUT_BACKEND_HPP_INCLUDED_ + +#include <string> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT + +#include <boost/log/sinks/basic_sink_backend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief An implementation of a logging sink backend that outputs to the debugger + * + * The sink uses Windows API in order to write log records as debug messages, if the + * application process is run under debugger. The sink backend also provides a specific + * filter that allows to check whether the debugger is available and thus elide unnecessary + * formatting. + */ +template< typename CharT > +class basic_debug_output_backend : + public basic_formatted_sink_backend< CharT, concurrent_feeding > +{ + //! Base type + typedef basic_formatted_sink_backend< CharT, concurrent_feeding > base_type; + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! String type to be used as a message text holder + typedef typename base_type::string_type string_type; + +public: + /*! + * Constructor. Initializes the sink backend. + */ + BOOST_LOG_API basic_debug_output_backend(); + /*! + * Destructor + */ + BOOST_LOG_API ~basic_debug_output_backend(); + + /*! + * The method passes the formatted message to debugger + */ + BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); +}; + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_debug_output_backend< char > debug_output_backend; //!< Convenience typedef for narrow-character logging +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_debug_output_backend< wchar_t > wdebug_output_backend; //!< Convenience typedef for wide-character logging +#endif + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_WITHOUT_DEBUG_OUTPUT + +#endif // BOOST_LOG_SINKS_DEBUG_OUTPUT_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/drop_on_overflow.hpp b/boost/log/sinks/drop_on_overflow.hpp new file mode 100644 index 0000000000..cbc2d6370c --- /dev/null +++ b/boost/log/sinks/drop_on_overflow.hpp @@ -0,0 +1,80 @@ +/* + * 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 drop_on_overflow.hpp + * \author Andrey Semashev + * \date 04.01.2012 + * + * The header contains implementation of \c drop_on_overflow strategy for handling + * queue overflows in bounded queues for the asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_DROP_ON_OVERFLOW_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_DROP_ON_OVERFLOW_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Log record dropping strategy + * + * This strategy will cause log records to be discarded in case of + * queue overflow in bounded asynchronous sinks. It should not be used + * if losing log records is not acceptable. + */ +class drop_on_overflow +{ +#ifndef BOOST_LOG_DOXYGEN_PASS +public: + /*! + * This method is called by the queue when overflow is detected. + * + * \retval true Attempt to enqueue the record again. + * \retval false Discard the record. + */ + template< typename LockT > + static bool on_overflow(record_view const&, LockT&) + { + return false; + } + + /*! + * This method is called by the queue when there appears a free space. + */ + static void on_queue_space_available() + { + } + + /*! + * This method is called by the queue to interrupt any possible waits in \c on_overflow. + */ + static void interrupt() + { + } +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_DROP_ON_OVERFLOW_HPP_INCLUDED_ diff --git a/boost/log/sinks/event_log_backend.hpp b/boost/log/sinks/event_log_backend.hpp new file mode 100644 index 0000000000..5e539e57a9 --- /dev/null +++ b/boost/log/sinks/event_log_backend.hpp @@ -0,0 +1,662 @@ +/* + * 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 event_log_backend.hpp + * \author Andrey Semashev + * \date 07.11.2008 + * + * The header contains a logging sink backend that uses Windows NT event log API + * for signaling application events. + */ + +#ifndef BOOST_LOG_SINKS_EVENT_LOG_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_EVENT_LOG_BACKEND_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_WITHOUT_EVENT_LOG + +#include <map> +#include <vector> +#include <string> +#include <iosfwd> +#include <boost/filesystem/path.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/keywords/message_file.hpp> +#include <boost/log/keywords/log_name.hpp> +#include <boost/log/keywords/log_source.hpp> +#include <boost/log/keywords/registration.hpp> +#include <boost/log/keywords/target.hpp> +#include <boost/log/sinks/basic_sink_backend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/sinks/attribute_mapping.hpp> +#include <boost/log/sinks/event_log_constants.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/expressions/formatter.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace event_log { + + //! Event log source registration modes + enum registration_mode + { + never, //!< Never register event source, even if it's not registered + on_demand, //!< Register if the source is not registered yet + forced //!< Register always, event if the source is already registered + }; + + /*! + * \brief Straightforward event type mapping + * + * This type of mapping assumes that attribute with a particular name always + * provides values that map directly onto the native event types. The mapping + * simply returns the extracted attribute value converted to the native event type. + */ + template< typename AttributeValueT = int > + class direct_event_type_mapping : + public basic_direct_mapping< event_type, AttributeValueT > + { + //! Base type + typedef basic_direct_mapping< event_type, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit direct_event_type_mapping(attribute_name const& name) : + base_type(name, info) + { + } + }; + + /*! + * \brief Customizable event type mapping + * + * The class allows to setup a custom mapping between an attribute and native event types. + * The mapping should be initialized similarly to the standard \c map container, by using + * indexing operator and assignment. + */ + template< typename AttributeValueT = int > + class custom_event_type_mapping : + public basic_custom_mapping< event_type, AttributeValueT > + { + //! Base type + typedef basic_custom_mapping< event_type, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit custom_event_type_mapping(attribute_name const& name) : + base_type(name, info) + { + } + }; + + /*! + * \brief Straightforward event ID mapping + * + * This type of mapping assumes that attribute with a particular name always + * provides values that map directly onto the event identifiers. The mapping + * simply returns the extracted attribute value converted to the event ID. + */ + template< typename AttributeValueT = int > + class direct_event_id_mapping : + public basic_direct_mapping< event_id, AttributeValueT > + { + //! Base type + typedef basic_direct_mapping< event_id, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit direct_event_id_mapping(attribute_name const& name) : + base_type(name, make_event_id(0)) + { + } + }; + + /*! + * \brief Customizable event ID mapping + * + * The class allows to setup a custom mapping between an attribute and event identifiers. + * The mapping should be initialized similarly to the standard \c map container, by using + * indexing operator and assignment. + */ + template< typename AttributeValueT = int > + class custom_event_id_mapping : + public basic_custom_mapping< event_id, AttributeValueT > + { + //! Base type + typedef basic_custom_mapping< event_id, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit custom_event_id_mapping(attribute_name const& name) : + base_type(name, make_event_id(0)) + { + } + }; + + /*! + * \brief Straightforward event category mapping + * + * This type of mapping assumes that attribute with a particular name always + * provides values that map directly onto the event categories. The mapping + * simply returns the extracted attribute value converted to the event category. + */ + template< typename AttributeValueT = int > + class direct_event_category_mapping : + public basic_direct_mapping< event_category, AttributeValueT > + { + //! Base type + typedef basic_direct_mapping< event_category, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit direct_event_category_mapping(attribute_name const& name) : + base_type(name, make_event_category(0)) + { + } + }; + + /*! + * \brief Customizable event category mapping + * + * The class allows to setup a custom mapping between an attribute and event categories. + * The mapping should be initialized similarly to the standard \c map container, by using + * indexing operator and assignment. + */ + template< typename AttributeValueT = int > + class custom_event_category_mapping : + public basic_custom_mapping< event_category, AttributeValueT > + { + //! Base type + typedef basic_custom_mapping< event_category, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit custom_event_category_mapping(attribute_name const& name) : + base_type(name, make_event_category(0)) + { + } + }; + + /*! + * \brief An event composer + * + * This class is a function object that extracts event identifier from the attribute values set + * and formats insertion strings for the particular event. Each insertion string is formatted with + * a distinct formatter, which can be created just like regular sinks formatters. + * + * Before using, the composer must be initialized with the following information: + * \li Event identifier extraction logic. One can use \c basic_direct_event_id_mapping or + * \c basic_custom_event_id_mapping classes in order to create such extractor and pass it + * to the composer constructor. + * \li Event identifiers and insertion string formatters. The composer provides the following + * syntax to provide this information: + * + * \code + * event_composer comp; + * comp[MY_EVENT_ID1] % formatter1 % ... % formatterN; + * comp[MY_EVENT_ID2] % formatter1 % ... % formatterN; + * ... + * \endcode + * + * The event identifiers in square brackets are provided by the message compiler generated + * header (the actual names are specified in the .mc file). The formatters represent + * the insertion strings that will be used to replace placeholders in event messages, + * thus the number and the order of the formatters must correspond to the message definition. + */ + template< typename CharT > + class BOOST_LOG_API basic_event_composer + { + public: + //! Character type + typedef CharT char_type; + //! String type to be used as a message text holder + typedef std::basic_string< char_type > string_type; + + //! Event identifier mapper type + typedef boost::log::aux::light_function< event_id (record_view const&) > event_id_mapper_type; + + //! Type of an insertion composer (a formatter) + typedef basic_formatter< char_type > formatter_type; + //! Type of the composed insertions list + typedef std::vector< string_type > insertion_list; + + private: + //! \cond + + //! The class that implements formatting of insertion strings + class insertion_composer; + + //! Type of the events map + typedef std::map< event_id, insertion_composer > event_map; + + //! A smart reference that puts formatters into the composer + class event_map_reference; + friend class event_map_reference; + class event_map_reference + { + private: + //! Event identifier + event_id m_ID; + //! A reference to the object that created the reference + basic_event_composer< char_type >& m_Owner; + //! A hint for the owner to optimize insertion + insertion_composer* m_Composer; + + public: + //! Initializing constructor + explicit event_map_reference(event_id id, basic_event_composer< char_type >& owner) : + m_ID(id), + m_Owner(owner), + m_Composer(0) + { + } + //! The operator puts the formatter into the composer + template< typename FormatterT > + event_map_reference& operator% (FormatterT const& fmt) + { + m_Composer = m_Owner.add_formatter(m_ID, m_Composer, formatter_type(fmt)); + return *this; + } + }; + + //! \endcond + + private: + //! The mapper that will extract the event identifier + event_id_mapper_type m_EventIDMapper; + //! The map of event identifiers and their insertion composers + event_map m_EventMap; + + public: + /*! + * Default constructor. Creates an empty map of events. + * + * \param id_mapper An event identifier mapping function that will be used to extract event ID from attribute values + */ + explicit basic_event_composer(event_id_mapper_type const& id_mapper); + /*! + * Copy constructor. Performs a deep copy of the object. + */ + basic_event_composer(basic_event_composer const& that); + /*! + * Destructor + */ + ~basic_event_composer(); + + /*! + * Assignment. Provides strong exception guarantee. + */ + basic_event_composer& operator= (basic_event_composer that); + /*! + * Swaps \c *this and \c that objects. + */ + void swap(basic_event_composer& that); + /*! + * Initiates creation of a new event description. The result of the operator can be used to + * add formatters for insertion strings construction. The returned reference type is implementation detail. + * + * \param id Event identifier. + */ + event_map_reference operator[] (event_id id); + /*! + * Initiates creation of a new event description. The result of the operator can be used to + * add formatters for insertion strings construction. The returned reference type is implementation detail. + * + * \param id Event identifier. + */ + event_map_reference operator[] (int id); + /*! + * Event composition operator. Extracts an event identifier from the attribute values by calling event ID mapper. + * Then runs all formatters that were registered for the event with the extracted ID. The results of formatting + * are returned in the \a insertions parameter. + * + * \param rec Log record view + * \param insertions A sequence of formatted insertion strings + * \return An event identifier that was extracted from \c attributes + */ + event_id operator() (record_view const& rec, insertion_list& insertions) const; + + private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! Adds a formatter to the insertion composers list + insertion_composer* add_formatter(event_id id, insertion_composer* composer, formatter_type const& fmt); +#endif // BOOST_LOG_DOXYGEN_PASS + }; + +#ifdef BOOST_LOG_USE_CHAR + typedef basic_event_composer< char > event_composer; //!< Convenience typedef for narrow-character logging +#endif +#ifdef BOOST_LOG_USE_WCHAR_T + typedef basic_event_composer< wchar_t > wevent_composer; //!< Convenience typedef for wide-character logging +#endif + +} // namespace event_log + +/*! + * \brief An implementation of a simple logging sink backend that emits events into Windows NT event log + * + * The sink uses Windows NT 5 (Windows 2000) and later event log API to emit events + * to an event log. The sink acts as an event source in terms of the API, it implements all needed resources + * and source registration in the Windows registry that is needed for the event delivery. + * + * The backend performs message text formatting. The composed text is then passed as the first + * and only string parameter of the event. The resource embedded into the backend describes the event + * so that the parameter is inserted into the event description text, thus making it visible + * in the event log. + * + * The backend allows to customize mapping of application severity levels to the native Windows event types. + * This allows to write portable code even if OS-specific sinks, such as this one, are used. + * + * \note Since the backend registers itself into Windows registry as the resource file that contains + * event description, it is important to keep the library binary in a stable place of the filesystem. + * Otherwise Windows might not be able to load event resources from the library and display + * events correctly. + * + * \note It is known that Windows is not able to find event resources in the application executable, + * which is linked against the static build of the library. Users are advised to use dynamic + * builds of the library to solve this problem. + */ +template< typename CharT > +class basic_simple_event_log_backend : + public basic_formatted_sink_backend< CharT, concurrent_feeding > +{ + //! Base type + typedef basic_formatted_sink_backend< CharT, concurrent_feeding > base_type; + //! Implementation type + struct implementation; + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! String type to be used as a message text holder + typedef typename base_type::string_type string_type; + + //! Mapper type for the event type + typedef boost::log::aux::light_function< event_log::event_type (record_view const&) > event_type_mapper_type; + +private: + //! Pointer to the backend implementation that hides various types from windows.h + implementation* m_pImpl; + +public: + /*! + * Default constructor. Registers event source with name based on the application + * executable file name in the Application log. If such a registration is already + * present, it is not overridden. + */ + BOOST_LOG_API basic_simple_event_log_backend(); + /*! + * Constructor. Registers event log source with the specified parameters. + * The following named parameters are supported: + * + * \li \c target - Specifies an UNC path to the remote server which log records should be sent to. + * The local machine will be used to process log records, if not specified. + * \li \c log_name - Specifies the log in which the source should be registered. + * The result of \c get_default_log_name is used, if the parameter is not specified. + * \li \c log_source - Specifies the source name. The result of \c get_default_source_name + * is used, if the parameter is not specified. + * \li \c registration - Specifies the event source registration mode in the Windows registry. + * Can have values of the \c registration_mode enum. Default value: \c on_demand. + * + * \param args A set of named parameters. + */ +#ifndef BOOST_LOG_DOXYGEN_PASS + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(basic_simple_event_log_backend, construct) +#else + template< typename... ArgsT > + explicit basic_simple_event_log_backend(ArgsT... const& args); +#endif + + /*! + * Destructor. Unregisters event source. The log source description is not removed from the Windows registry. + */ + BOOST_LOG_API ~basic_simple_event_log_backend(); + + /*! + * The method installs the function object that maps application severity levels to WinAPI event types + */ + BOOST_LOG_API void set_event_type_mapper(event_type_mapper_type const& mapper); + + /*! + * \returns Default log name: Application + */ + BOOST_LOG_API static string_type get_default_log_name(); + /*! + * \returns Default log source name that is based on the application executable file name and the sink name + */ + BOOST_LOG_API static string_type get_default_source_name(); + + /*! + * The method puts the formatted message to the event log + */ + BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! Constructs backend implementation + template< typename ArgsT > + void construct(ArgsT const& args) + { + construct( + args[keywords::target | string_type()], + args[keywords::log_name || &basic_simple_event_log_backend::get_default_log_name], + args[keywords::log_source || &basic_simple_event_log_backend::get_default_source_name], + args[keywords::registration | event_log::on_demand]); + } + BOOST_LOG_API void construct( + string_type const& target, + string_type const& log_name, + string_type const& source_name, + event_log::registration_mode reg_mode); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +/*! + * \brief An implementation of a logging sink backend that emits events into Windows NT event log + * + * The sink uses Windows NT 5 (Windows 2000) and later event log API to emit events + * to an event log. The sink acts as an event source. Unlike \c basic_simple_event_log_backend, + * this sink backend allows users to specify the custom event message file and supports + * mapping attribute values onto several insertion strings. Although it requires considerably + * more scaffolding than the simple backend, this allows to support localizable event descriptions. + * + * Besides the file name of the module with event resources, the backend provides the following + * customizations: + * \li Remote server UNC address, log name and source name. These parameters have similar meaning + * to \c basic_simple_event_log_backend. + * \li Event type and category mappings. These are function object that allow to map attribute + * values to the according event parameters. One can use mappings in the \c event_log namespace. + * \li Event composer. This function object extracts event identifier and formats string insertions, + * that will be used by the API to compose the final event message text. + */ +template< typename CharT > +class basic_event_log_backend : + public basic_sink_backend< synchronized_feeding > +{ + //! Base type + typedef basic_sink_backend< synchronized_feeding > base_type; + //! Implementation type + struct implementation; + +public: + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Type of the composed insertions list + typedef std::vector< string_type > insertion_list; + + //! Mapper type for the event type + typedef boost::log::aux::light_function< event_log::event_type (record_view const&) > event_type_mapper_type; + //! Mapper type for the event category + typedef boost::log::aux::light_function< event_log::event_category (record_view const&) > event_category_mapper_type; + //! Event composer type + typedef boost::log::aux::light_function< event_log::event_id (record_view const&, insertion_list&) > event_composer_type; + +private: + //! Pointer to the backend implementation that hides various types from windows.h + implementation* m_pImpl; + +public: + /*! + * Constructor. Registers event source with name based on the application + * executable file name in the Application log. If such a registration is already + * present, it is not overridden. + */ + template< typename T > + explicit basic_event_log_backend(std::basic_string< T > const& message_file_name) + { + construct(keywords::message_file = message_file_name); + } + /*! + * Constructor. Registers event source with name based on the application + * executable file name in the Application log. If such a registration is already + * present, it is not overridden. + */ + explicit basic_event_log_backend(filesystem::path const& message_file_name) + { + construct(keywords::message_file = message_file_name); + } + /*! + * Constructor. Registers event log source with the specified parameters. + * The following named parameters are supported: + * + * \li \c message_file - Specifies the file name that contains resources that + * describe events and categories. + * \li \c target - Specifies an UNC path to the remote server to which log records should be sent to. + * The local machine will be used to process log records, if not specified. + * \li \c log_name - Specifies the log in which the source should be registered. + * The result of \c get_default_log_name is used, if the parameter is not specified. + * \li \c log_source - Specifies the source name. The result of \c get_default_source_name + * is used, if the parameter is not specified. + * \li \c registration - Specifies the event source registration mode in the Windows registry. + * Can have values of the \c registration_mode enum. Default value: \c on_demand. + * + * \param args A set of named parameters. + */ +#ifndef BOOST_LOG_DOXYGEN_PASS + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(basic_event_log_backend, construct) +#else + template< typename... ArgsT > + explicit basic_event_log_backend(ArgsT... const& args); +#endif + + /*! + * Destructor. Unregisters event source. The log source description is not removed from the Windows registry. + */ + BOOST_LOG_API ~basic_event_log_backend(); + + /*! + * The method creates an event in the event log + * + * \param rec Log record to consume + */ + BOOST_LOG_API void consume(record_view const& rec); + + /*! + * The method installs the function object that maps application severity levels to WinAPI event types + */ + BOOST_LOG_API void set_event_type_mapper(event_type_mapper_type const& mapper); + + /*! + * The method installs the function object that extracts event category from attribute values + */ + BOOST_LOG_API void set_event_category_mapper(event_category_mapper_type const& mapper); + + /*! + * The method installs the function object that extracts event identifier from the attributes and creates + * insertion strings that will replace placeholders in the event message. + */ + BOOST_LOG_API void set_event_composer(event_composer_type const& composer); + + /*! + * \returns Default log name: Application + */ + BOOST_LOG_API static string_type get_default_log_name(); + /*! + * \returns Default log source name that is based on the application executable file name and the sink name + */ + BOOST_LOG_API static string_type get_default_source_name(); + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! Constructs backend implementation + template< typename ArgsT > + void construct(ArgsT const& args) + { + construct( + filesystem::path(args[keywords::message_file]), + args[keywords::target | string_type()], + args[keywords::log_name || &basic_event_log_backend::get_default_log_name], + args[keywords::log_source || &basic_event_log_backend::get_default_source_name], + args[keywords::registration | event_log::on_demand]); + } + BOOST_LOG_API void construct( + filesystem::path const& message_file_name, + string_type const& target, + string_type const& log_name, + string_type const& source_name, + event_log::registration_mode reg_mode); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_simple_event_log_backend< char > simple_event_log_backend; //!< Convenience typedef for narrow-character logging +typedef basic_event_log_backend< char > event_log_backend; //!< Convenience typedef for narrow-character logging +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_simple_event_log_backend< wchar_t > wsimple_event_log_backend; //!< Convenience typedef for wide-character logging +typedef basic_event_log_backend< wchar_t > wevent_log_backend; //!< Convenience typedef for wide-character logging +#endif + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_WITHOUT_EVENT_LOG + +#endif // BOOST_LOG_SINKS_EVENT_LOG_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/event_log_constants.hpp b/boost/log/sinks/event_log_constants.hpp new file mode 100644 index 0000000000..e6c361a420 --- /dev/null +++ b/boost/log/sinks/event_log_constants.hpp @@ -0,0 +1,88 @@ +/* + * 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 event_log_constants.hpp + * \author Andrey Semashev + * \date 07.11.2008 + * + * The header contains definition of constants related to Windows NT Event Log API. + * The constants can be used in other places without the event log backend. + */ + +#ifndef BOOST_LOG_SINKS_EVENT_LOG_CONSTANTS_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_EVENT_LOG_CONSTANTS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_WITHOUT_EVENT_LOG + +#include <boost/log/detail/tagged_integer.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace event_log { + + struct event_id_tag; + //! A tagged integral type that represents event identifier for the Windows API + typedef boost::log::aux::tagged_integer< unsigned int, event_id_tag > event_id; + /*! + * The function constructs event identifier from an integer + */ + inline event_id make_event_id(unsigned int id) + { + event_id iden = { id }; + return iden; + } + + struct event_category_tag; + //! A tagged integral type that represents event category for the Windows API + typedef boost::log::aux::tagged_integer< unsigned short, event_category_tag > event_category; + /*! + * The function constructs event category from an integer + */ + inline event_category make_event_category(unsigned short cat) + { + event_category category = { cat }; + return category; + } + + //! Windows event types + enum event_type + { + success = 0, //!< Equivalent to EVENTLOG_SUCCESS + info = 4, //!< Equivalent to EVENTLOG_INFORMATION_TYPE + warning = 2, //!< Equivalent to EVENTLOG_WARNING_TYPE + error = 1 //!< Equivalent to EVENTLOG_ERROR_TYPE + }; + + /*! + * The function constructs log record level from an integer + */ + BOOST_LOG_API event_type make_event_type(unsigned short lev); + +} // namespace event_log + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_WITHOUT_EVENT_LOG + +#endif // BOOST_LOG_SINKS_EVENT_LOG_CONSTANTS_HPP_INCLUDED_ diff --git a/boost/log/sinks/frontend_requirements.hpp b/boost/log/sinks/frontend_requirements.hpp new file mode 100644 index 0000000000..086b023b29 --- /dev/null +++ b/boost/log/sinks/frontend_requirements.hpp @@ -0,0 +1,119 @@ +/* + * 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 sinks/frontend_requirements.hpp + * \author Andrey Semashev + * \date 22.04.2007 + * + * The header contains definition of requirement tags that sink backend may declare + * with regard to frontends. These requirements ensure that a backend will not + * be used with an incompatible frontend. + */ + +#ifndef BOOST_LOG_SINKS_FRONTEND_REQUIREMENTS_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_FRONTEND_REQUIREMENTS_HPP_INCLUDED_ + +#include <boost/mpl/aux_/na.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/inherit.hpp> +#include <boost/mpl/inherit_linearly.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> +#include <boost/type_traits/is_base_of.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT +//! The macro specifies the maximum number of requirements that can be combined with the \c combine_requirements metafunction +#define BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT 5 +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * The sink backend expects pre-synchronized calls, all needed synchronization is implemented + * in the frontend (IOW, only one thread is feeding records to the backend concurrently, but + * it is possible for several threads to write sequentially). Note that if a frontend supports + * synchronized record feeding, it will also report capable of concurrent record feeding. + */ +struct synchronized_feeding {}; + +#if !defined(BOOST_LOG_NO_THREADS) + +/*! + * The sink backend ensures all needed synchronization, it is capable to handle multithreaded calls + */ +struct concurrent_feeding : synchronized_feeding {}; + +#else // !defined(BOOST_LOG_NO_THREADS) + +// If multithreading is disabled, threading models become redundant +typedef synchronized_feeding concurrent_feeding; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +/*! + * The sink backend requires the frontend to perform log record formatting before feeding + */ +struct formatted_records {}; + +/*! + * The sink backend supports flushing + */ +struct flushing {}; + +#ifdef BOOST_LOG_DOXYGEN_PASS + +/*! + * The metafunction combines multiple requirement tags into one type. The resulting type will + * satisfy all specified requirements (i.e. \c has_requirement metafunction will return positive result). + */ +template< typename... RequirementsT > +struct combine_requirements; + +#else + +template< BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT, typename ReqT, mpl::na) > +struct combine_requirements : + mpl::inherit_linearly< + mpl::vector< BOOST_PP_ENUM_PARAMS(BOOST_LOG_COMBINE_REQUIREMENTS_LIMIT, ReqT) >, + mpl::inherit2< mpl::_1, mpl::_2 > + > +{ +}; + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * A helper metafunction to check if a requirement is satisfied. The \c TestedT template argument + * should be the type combining one or several requirements and \c RequiredT is the requirement + * to test against. The metafunction will yield a positive result if \c TestedT supports \c RequiredT. + */ +template< typename TestedT, typename RequiredT > +struct has_requirement : + public is_base_of< RequiredT, TestedT > +{ +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_FRONTEND_REQUIREMENTS_HPP_INCLUDED_ diff --git a/boost/log/sinks/sink.hpp b/boost/log/sinks/sink.hpp new file mode 100644 index 0000000000..516957d44b --- /dev/null +++ b/boost/log/sinks/sink.hpp @@ -0,0 +1,115 @@ +/* + * 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 sink.hpp + * \author Andrey Semashev + * \date 22.04.2007 + * + * The header contains an interface declaration for all sinks. This interface is used by the + * logging core to feed log records to sinks. + */ + +#ifndef BOOST_LOG_SINKS_SINK_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_SINK_HPP_INCLUDED_ + +#include <string> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +//! A base class for a logging sink frontend +class BOOST_LOG_NO_VTABLE sink +{ +public: + //! An exception handler type + typedef boost::log::aux::light_function< void () > exception_handler_type; + +private: + //! The flag indicates that the sink passes log records across thread boundaries + const bool m_cross_thread; + +public: + /*! + * Default constructor + */ + explicit sink(bool cross_thread) : m_cross_thread(cross_thread) + { + } + + /*! + * Virtual destructor + */ + virtual ~sink() {} + + /*! + * The method returns \c true if no filter is set or the attribute values pass the filter + * + * \param attributes A set of attribute values of a logging record + */ + virtual bool will_consume(attribute_value_set const& attributes) = 0; + + /*! + * The method puts logging record to the sink + * + * \param rec Logging record to consume + */ + virtual void consume(record_view const& rec) = 0; + + /*! + * The method attempts to put logging record to the sink. The method may be used by the + * core in order to determine the most efficient order of sinks to feed records to in + * case of heavy contention. Sink implementations may implement try/backoff logic in + * order to improve overall logging throughput. + * + * \param rec Logging record to consume + * \return \c true, if the record was consumed, \c false, if not. + */ + virtual bool try_consume(record_view const& rec) + { + consume(rec); + return true; + } + + /*! + * The method performs flushing of any internal buffers that may hold log records. The method + * may take considerable time to complete and may block both the calling thread and threads + * attempting to put new records into the sink while this call is in progress. + */ + virtual void flush() = 0; + + /*! + * The method indicates that the sink passes log records between different threads. This information is + * needed by the logging core to detach log records from all thread-specific resources before passing it + * to the sink. + */ + bool is_cross_thread() const BOOST_NOEXCEPT { return m_cross_thread; } + + BOOST_DELETED_FUNCTION(sink(sink const&)) + BOOST_DELETED_FUNCTION(sink& operator= (sink const&)) +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_SINK_HPP_INCLUDED_ diff --git a/boost/log/sinks/sync_frontend.hpp b/boost/log/sinks/sync_frontend.hpp new file mode 100644 index 0000000000..146cc9dc44 --- /dev/null +++ b/boost/log/sinks/sync_frontend.hpp @@ -0,0 +1,166 @@ +/* + * 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 sync_frontend.hpp + * \author Andrey Semashev + * \date 14.07.2009 + * + * The header contains implementation of synchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: Synchronous sink frontend is only supported in multithreaded environment +#endif + +#include <boost/static_assert.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/thread/recursive_mutex.hpp> +#include <boost/log/detail/locking_ptr.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/sinks/basic_sink_frontend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit synchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ + base_type(false),\ + m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {} + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Synchronous logging sink frontend + * + * The sink frontend serializes threads before passing logging records to the backend + */ +template< typename SinkBackendT > +class synchronous_sink : + public aux::make_sink_frontend_base< SinkBackendT >::type +{ + typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type; + +private: + //! Synchronization mutex type + typedef boost::recursive_mutex backend_mutex_type; + +public: + //! Sink implementation type + typedef SinkBackendT sink_backend_type; + //! \cond + BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, synchronized_feeding >::value), "Synchronous sink frontend is incompatible with the specified backend: thread synchronization requirements are not met"); + //! \endcond + +#ifndef BOOST_LOG_DOXYGEN_PASS + + //! A pointer type that locks the backend until it's destroyed + typedef boost::log::aux::locking_ptr< sink_backend_type, backend_mutex_type > locked_backend_ptr; + +#else // BOOST_LOG_DOXYGEN_PASS + + //! A pointer type that locks the backend until it's destroyed + typedef implementation_defined locked_backend_ptr; + +#endif // BOOST_LOG_DOXYGEN_PASS + +private: + //! Synchronization mutex + backend_mutex_type m_BackendMutex; + //! Pointer to the backend + const shared_ptr< sink_backend_type > m_pBackend; + +public: + /*! + * Default constructor. Constructs the sink backend instance. + * Requires the backend to be default-constructible. + */ + synchronous_sink() : + base_type(false), + m_pBackend(boost::make_shared< sink_backend_type >()) + { + } + /*! + * Constructor attaches user-constructed backend instance + * + * \param backend Pointer to the backend instance + * + * \pre \a backend is not \c NULL. + */ + explicit synchronous_sink(shared_ptr< sink_backend_type > const& backend) : + base_type(false), + m_pBackend(backend) + { + } + + // Constructors that pass arbitrary parameters to the backend constructor + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~) + + /*! + * Locking accessor to the attached backend + */ + locked_backend_ptr locked_backend() + { + return locked_backend_ptr(m_pBackend, m_BackendMutex); + } + + /*! + * Passes the log record to the backend + */ + void consume(record_view const& rec) + { + base_type::feed_record(rec, m_BackendMutex, *m_pBackend); + } + + /*! + * The method attempts to pass logging record to the backend + */ + bool try_consume(record_view const& rec) + { + return base_type::try_feed_record(rec, m_BackendMutex, *m_pBackend); + } + + /*! + * The method performs flushing of any internal buffers that may hold log records. The method + * may take considerable time to complete and may block both the calling thread and threads + * attempting to put new records into the sink while this call is in progress. + */ + void flush() + { + base_type::flush_backend(m_BackendMutex, *m_pBackend); + } +}; + +#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/syslog_backend.hpp b/boost/log/sinks/syslog_backend.hpp new file mode 100644 index 0000000000..35cfb540ab --- /dev/null +++ b/boost/log/sinks/syslog_backend.hpp @@ -0,0 +1,288 @@ +/* + * 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 syslog_backend.hpp + * \author Andrey Semashev + * \date 08.01.2008 + * + * The header contains implementation of a Syslog sink backend along with its setup facilities. + */ + +#ifndef BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_WITHOUT_SYSLOG + +#include <string> +#include <boost/log/detail/asio_fwd.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/sinks/basic_sink_backend.hpp> +#include <boost/log/sinks/syslog_constants.hpp> +#include <boost/log/sinks/attribute_mapping.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/keywords/facility.hpp> +#include <boost/log/keywords/use_impl.hpp> +#include <boost/log/keywords/ident.hpp> +#include <boost/log/keywords/ip_version.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +//! Supported IP protocol versions +enum ip_versions +{ + v4, + v6 +}; + +namespace syslog { + + //! The enumeration defined the possible implementation types for the syslog backend + enum impl_types + { +#ifdef BOOST_LOG_USE_NATIVE_SYSLOG + native = 0 //!< Use native syslog API +#ifndef BOOST_LOG_NO_ASIO + , +#endif +#endif +#ifndef BOOST_LOG_NO_ASIO + udp_socket_based = 1 //!< Use UDP sockets, according to RFC3164 +#endif + }; + + /*! + * \brief Straightforward severity level mapping + * + * This type of mapping assumes that attribute with a particular name always + * provides values that map directly onto the Syslog levels. The mapping + * simply returns the extracted attribute value converted to the Syslog severity level. + */ + template< typename AttributeValueT = int > + class direct_severity_mapping : + public basic_direct_mapping< level, AttributeValueT > + { + //! Base type + typedef basic_direct_mapping< level, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit direct_severity_mapping(attribute_name const& name) : + base_type(name, info) + { + } + }; + + /*! + * \brief Customizable severity level mapping + * + * The class allows to setup a custom mapping between an attribute and Syslog severity levels. + * The mapping should be initialized similarly to the standard \c map container, by using + * indexing operator and assignment. + */ + template< typename AttributeValueT = int > + class custom_severity_mapping : + public basic_custom_mapping< level, AttributeValueT > + { + //! Base type + typedef basic_custom_mapping< level, AttributeValueT > base_type; + + public: + /*! + * Constructor + * + * \param name Attribute name + */ + explicit custom_severity_mapping(attribute_name const& name) : + base_type(name, info) + { + } + }; + +} // namespace syslog + +/*! + * \brief An implementation of a syslog sink backend + * + * The backend provides support for the syslog protocol, defined in RFC3164. + * The backend sends log records to a remote host via UDP. The host name can + * be specified by calling the \c set_target_address method. By default log + * records will be sent to localhost:514. The local address can be specified + * as well, by calling the \c set_local_address method. By default syslog + * packets will be sent from any local address available. + * + * It is safe to create several sink backends with the same local addresses - + * the backends within the process will share the same socket. The same applies + * to different processes that use the syslog backends to send records from + * the same socket. However, it is not guaranteed to work if some third party + * facility is using the socket. + * + * On systems with native syslog implementation it may be preferable to utilize + * the POSIX syslog API instead of direct socket management in order to bypass + * possible security limitations that may be in action. To do so one has to pass + * the <tt>use_impl = native</tt> to the backend constructor. Note, however, + * that in that case you will only have one chance to specify syslog facility and + * process identification string - on the first native syslog backend construction. + * Other native syslog backends will ignore these parameters. + * Obviously, the \c set_local_address and \c set_target_address + * methods have no effect for native backends. Using <tt>use_impl = native</tt> + * on platforms with no native support for POSIX syslog API will have no effect. + */ +class syslog_backend : + public basic_formatted_sink_backend< char > +{ + //! Base type + typedef basic_formatted_sink_backend< char > base_type; + //! Implementation type + struct implementation; + +public: + //! Character type + typedef base_type::char_type char_type; + //! String type that is used to pass message test + typedef base_type::string_type string_type; + + //! Syslog severity level mapper type + typedef boost::log::aux::light_function< syslog::level (record_view const&) > severity_mapper_type; + +private: + //! Pointer to the implementation + implementation* m_pImpl; + +public: + /*! + * Constructor. Creates a UDP socket-based backend with <tt>syslog::user</tt> facility code. + * IPv4 protocol will be used. + */ + BOOST_LOG_API syslog_backend(); + /*! + * Constructor. Creates a sink backend with the specified named parameters. + * The following named parameters are supported: + * + * \li \c facility - Specifies the facility code. If not specified, <tt>syslog::user</tt> will be used. + * \li \c use_impl - Specifies the backend implementation. Can be one of: + * \li \c native - Use the native syslog API, if available. If no native API + * is available, it is equivalent to \c udp_socket_based. + * \li \c udp_socket_based - Use the UDP socket-based implementation, conforming to + * RFC3164 protocol specification. This is the default. + * \li \c ip_version - Specifies IP protocol version to use, in case if socket-based implementation + * is used. Can be either \c v4 (the default one) or \c v6. + * \li \c ident - Process identification string. This parameter is only supported by native syslog implementation. + */ +#ifndef BOOST_LOG_DOXYGEN_PASS + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(syslog_backend, construct) +#else + template< typename... ArgsT > + explicit syslog_backend(ArgsT... const& args); +#endif + + /*! + * Destructor + */ + BOOST_LOG_API ~syslog_backend(); + + /*! + * The method installs the function object that maps application severity levels to syslog levels + */ + BOOST_LOG_API void set_severity_mapper(severity_mapper_type const& mapper); + +#if !defined(BOOST_LOG_NO_ASIO) + + /*! + * The method sets the local host name which log records will be sent from. The host name + * is resolved to obtain the final IP address. + * + * \note Does not have effect if the backend was constructed to use native syslog API + * + * \param addr The local address + * \param port The local port number + */ + BOOST_LOG_API void set_local_address(std::string const& addr, unsigned short port = 514); + /*! + * The method sets the local address which log records will be sent from. + * + * \note Does not have effect if the backend was constructed to use native syslog API + * + * \param addr The local address + * \param port The local port number + */ + BOOST_LOG_API void set_local_address(boost::asio::ip::address const& addr, unsigned short port = 514); + + /*! + * The method sets the remote host name where log records will be sent to. The host name + * is resolved to obtain the final IP address. + * + * \note Does not have effect if the backend was constructed to use native syslog API + * + * \param addr The remote host address + * \param port The port number on the remote host + */ + BOOST_LOG_API void set_target_address(std::string const& addr, unsigned short port = 514); + /*! + * The method sets the address of the remote host where log records will be sent to. + * + * \note Does not have effect if the backend was constructed to use native syslog API + * + * \param addr The remote host address + * \param port The port number on the remote host + */ + BOOST_LOG_API void set_target_address(boost::asio::ip::address const& addr, unsigned short port = 514); + +#endif // !defined(BOOST_LOG_NO_ASIO) + + /*! + * The method passes the formatted message to the syslog API or sends to a syslog server + */ + BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! The method creates the backend implementation + template< typename ArgsT > + void construct(ArgsT const& args) + { + construct( + args[keywords::facility | syslog::user], +#if !defined(BOOST_LOG_NO_ASIO) + args[keywords::use_impl | syslog::udp_socket_based], +#else + args[keywords::use_impl | syslog::native], +#endif + args[keywords::ip_version | v4], + args[keywords::ident | std::string()]); + } + BOOST_LOG_API void construct( + syslog::facility facility, syslog::impl_types use_impl, ip_versions ip_version, std::string const& ident); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_WITHOUT_SYSLOG + +#endif // BOOST_LOG_SINKS_SYSLOG_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/syslog_constants.hpp b/boost/log/sinks/syslog_constants.hpp new file mode 100644 index 0000000000..d320ebbbac --- /dev/null +++ b/boost/log/sinks/syslog_constants.hpp @@ -0,0 +1,101 @@ +/* + * 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 syslog_constants.hpp + * \author Andrey Semashev + * \date 08.01.2008 + * + * The header contains definition of constants related to Syslog API. The constants can be + * used in other places without the Syslog backend. + */ + +#ifndef BOOST_LOG_SINKS_SYSLOG_CONSTANTS_HPP_INCLUDED_HPP_ +#define BOOST_LOG_SINKS_SYSLOG_CONSTANTS_HPP_INCLUDED_HPP_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_WITHOUT_SYSLOG + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace syslog { + + //! Syslog record levels + enum level + { + emergency = 0, //!< Equivalent to LOG_EMERG in syslog API + alert = 1, //!< Equivalent to LOG_ALERT in syslog API + critical = 2, //!< Equivalent to LOG_CRIT in syslog API + error = 3, //!< Equivalent to LOG_ERROR in syslog API + warning = 4, //!< Equivalent to LOG_WARNING in syslog API + notice = 5, //!< Equivalent to LOG_NOTICE in syslog API + info = 6, //!< Equivalent to LOG_INFO in syslog API + debug = 7 //!< Equivalent to LOG_DEBUG in syslog API + }; + + /*! + * The function constructs log record level from an integer + */ + BOOST_LOG_API level make_level(int lev); + + //! Syslog facility codes + enum facility + { + kernel = 0 * 8, //!< Kernel messages + user = 1 * 8, //!< User-level messages. Equivalent to LOG_USER in syslog API. + mail = 2 * 8, //!< Mail system messages. Equivalent to LOG_MAIL in syslog API. + daemon = 3 * 8, //!< System daemons. Equivalent to LOG_DAEMON in syslog API. + security0 = 4 * 8, //!< Security/authorization messages + syslogd = 5 * 8, //!< Messages from the syslogd daemon. Equivalent to LOG_SYSLOG in syslog API. + printer = 6 * 8, //!< Line printer subsystem. Equivalent to LOG_LPR in syslog API. + news = 7 * 8, //!< Network news subsystem. Equivalent to LOG_NEWS in syslog API. + uucp = 8 * 8, //!< Messages from UUCP subsystem. Equivalent to LOG_UUCP in syslog API. + clock0 = 9 * 8, //!< Messages from the clock daemon + security1 = 10 * 8, //!< Security/authorization messages + ftp = 11 * 8, //!< Messages from FTP daemon + ntp = 12 * 8, //!< Messages from NTP daemon + log_audit = 13 * 8, //!< Security/authorization messages + log_alert = 14 * 8, //!< Security/authorization messages + clock1 = 15 * 8, //!< Messages from the clock daemon + local0 = 16 * 8, //!< For local use. Equivalent to LOG_LOCAL0 in syslog API + local1 = 17 * 8, //!< For local use. Equivalent to LOG_LOCAL1 in syslog API + local2 = 18 * 8, //!< For local use. Equivalent to LOG_LOCAL2 in syslog API + local3 = 19 * 8, //!< For local use. Equivalent to LOG_LOCAL3 in syslog API + local4 = 20 * 8, //!< For local use. Equivalent to LOG_LOCAL4 in syslog API + local5 = 21 * 8, //!< For local use. Equivalent to LOG_LOCAL5 in syslog API + local6 = 22 * 8, //!< For local use. Equivalent to LOG_LOCAL6 in syslog API + local7 = 23 * 8 //!< For local use. Equivalent to LOG_LOCAL7 in syslog API + }; + + /*! + * The function constructs log source facility from an integer + */ + BOOST_LOG_API facility make_facility(int fac); + +} // namespace syslog + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_WITHOUT_SYSLOG + +#endif // BOOST_LOG_SINKS_SYSLOG_CONSTANTS_HPP_INCLUDED_HPP_ diff --git a/boost/log/sinks/text_file_backend.hpp b/boost/log/sinks/text_file_backend.hpp new file mode 100644 index 0000000000..1d39a633c0 --- /dev/null +++ b/boost/log/sinks/text_file_backend.hpp @@ -0,0 +1,539 @@ +/* + * 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 text_file_backend.hpp + * \author Andrey Semashev + * \date 09.06.2009 + * + * The header contains implementation of a text file sink backend. + */ + +#ifndef BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_ + +#include <ios> +#include <string> +#include <ostream> +#include <boost/limits.hpp> +#include <boost/cstdint.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/date_time/date_defs.hpp> +#include <boost/date_time/special_defs.hpp> +#include <boost/date_time/gregorian/greg_day.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/log/keywords/max_size.hpp> +#include <boost/log/keywords/min_free_space.hpp> +#include <boost/log/keywords/target.hpp> +#include <boost/log/keywords/file_name.hpp> +#include <boost/log/keywords/open_mode.hpp> +#include <boost/log/keywords/auto_flush.hpp> +#include <boost/log/keywords/rotation_size.hpp> +#include <boost/log/keywords/time_based_rotation.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/sinks/basic_sink_backend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace file { + +//! The enumeration of the stored files scan methods +enum scan_method +{ + no_scan, //!< Don't scan for stored files + scan_matching, //!< Scan for files with names matching the specified mask + scan_all //!< Scan for all files in the directory +}; + +/*! + * \brief Base class for file collectors + * + * All file collectors, supported by file sink backends, should inherit this class. + */ +struct BOOST_LOG_NO_VTABLE collector +{ + /*! + * Default constructor + */ + BOOST_DEFAULTED_FUNCTION(collector(), {}) + + /*! + * Virtual destructor + */ + virtual ~collector() {} + + /*! + * The function stores the specified file in the storage. May lead to an older file + * deletion and a long file moving. + * + * \param src_path The name of the file to be stored + */ + virtual void store_file(filesystem::path const& src_path) = 0; + + /*! + * Scans the target directory for the files that have already been stored. The found + * files are added to the collector in order to be tracked and erased, if needed. + * + * The function may scan the directory in two ways: it will either consider every + * file in the directory a log file, or will only consider files with names that + * match the specified pattern. The pattern may contain the following placeholders: + * + * \li %y, %Y, %m, %d - date components, in Boost.DateTime meaning. + * \li %H, %M, %S, %f - time components, in Boost.DateTime meaning. + * \li %N - numeric file counter. May also contain width specification + * in printf-compatible form (e.g. %5N). The resulting number will always be zero-filled. + * \li %% - a percent sign + * + * All other placeholders are not supported. + * + * \param method The method of scanning. If \c no_scan is specified, the call has no effect. + * \param pattern The file name pattern if \a method is \c scan_matching. Otherwise the parameter + * is not used. + * \param counter If not \c NULL and \a method is \c scan_matching, the method suggests initial value + * of a file counter that may be used in the file name pattern. The parameter + * is not used otherwise. + * \return The number of found files. + * + * \note In case if \a method is \c scan_matching the effect of this function is highly dependent + * on the \a pattern definition. It is recommended to choose patterns with easily + * distinguished placeholders (i.e. having delimiters between them). Otherwise + * either some files can be mistakenly found or not found, which in turn may lead + * to an incorrect file deletion. + */ + virtual uintmax_t scan_for_files( + scan_method method, filesystem::path const& pattern = filesystem::path(), unsigned int* counter = 0) = 0; + + BOOST_DELETED_FUNCTION(collector(collector const&)) + BOOST_DELETED_FUNCTION(collector& operator= (collector const&)) +}; + +namespace aux { + + //! Creates and returns a file collector with the specified parameters + BOOST_LOG_API shared_ptr< collector > make_collector( + filesystem::path const& target_dir, + uintmax_t max_size, + uintmax_t min_free_space + ); + template< typename ArgsT > + inline shared_ptr< collector > make_collector(ArgsT const& args) + { + return aux::make_collector( + filesystem::path(args[keywords::target]), + args[keywords::max_size | (std::numeric_limits< uintmax_t >::max)()], + args[keywords::min_free_space | static_cast< uintmax_t >(0)]); + } + +} // namespace aux + +#ifndef BOOST_LOG_DOXYGEN_PASS + +template< typename T1 > +inline shared_ptr< collector > make_collector(T1 const& a1) +{ + return aux::make_collector(a1); +} +template< typename T1, typename T2 > +inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2) +{ + return aux::make_collector((a1, a2)); +} +template< typename T1, typename T2, typename T3 > +inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 const& a3) +{ + return aux::make_collector((a1, a2, a3)); +} + +#else + +/*! + * The function creates a file collector for the specified target directory. + * Each target directory is managed by a single file collector, so if + * this function is called several times for the same directory, + * it will return a reference to the same file collector. It is safe + * to use the same collector in different sinks, even in a multithreaded + * application. + * + * One can specify certain restrictions for the stored files, such as + * maximum total size or minimum free space left in the target directory. + * If any of the specified restrictions is not met, the oldest stored file + * is deleted. If the same collector is requested more than once with + * different restrictions, the collector will act according to the most strict + * combination of all specified restrictions. + * + * The following named parameters are supported: + * + * \li \c target - Specifies the target directory for the files being stored in. This parameter + * is mandatory. + * \li \c max_size - Specifies the maximum total size, in bytes, of stored files that the collector + * will try not to exceed. If the size exceeds this threshold the oldest file(s) is + * deleted to free space. Note that the threshold may be exceeded if the size of + * individual files exceed the \c max_size value. The threshold is not maintained, + * if not specified. + * \li \c min_free_space - Specifies the minimum free space, in bytes, in the target directory that + * the collector tries to maintain. If the threshold is exceeded, the oldest + * file(s) is deleted to free space. The threshold is not maintained, if not + * specified. + * + * \return The file collector. + */ +template< typename... ArgsT > +shared_ptr< collector > make_collector(ArgsT... const& args); + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * The class represents the time point of log file rotation. One can specify one of three + * types of time point based rotation: + * + * \li rotation takes place every day, at the specified time + * \li rotation takes place on the specified day of every week, at the specified time + * \li rotation takes place on the specified day of every month, at the specified time + * + * The time points are considered to be local time. + */ +class rotation_at_time_point +{ +public: + typedef bool result_type; + +private: + enum day_kind + { + not_specified, + weekday, + monthday + }; + + day_kind m_DayKind : 2; + unsigned char m_Day : 6; + unsigned char m_Hour, m_Minute, m_Second; + + mutable posix_time::ptime m_Previous; + +public: + /*! + * Creates a rotation time point of every day at the specified time + * + * \param hour The rotation hour, should be within 0 and 23 + * \param minute The rotation minute, should be within 0 and 59 + * \param second The rotation second, should be within 0 and 59 + */ + BOOST_LOG_API explicit rotation_at_time_point(unsigned char hour, unsigned char minute, unsigned char second); + + /*! + * Creates a rotation time point of each specified weekday at the specified time + * + * \param wday The weekday of the rotation + * \param hour The rotation hour, should be within 0 and 23 + * \param minute The rotation minute, should be within 0 and 59 + * \param second The rotation second, should be within 0 and 59 + */ + BOOST_LOG_API explicit rotation_at_time_point( + date_time::weekdays wday, + unsigned char hour = 0, + unsigned char minute = 0, + unsigned char second = 0); + + /*! + * Creates a rotation time point of each specified day of month at the specified time + * + * \param mday The monthday of the rotation, should be within 1 and 31 + * \param hour The rotation hour, should be within 0 and 23 + * \param minute The rotation minute, should be within 0 and 59 + * \param second The rotation second, should be within 0 and 59 + */ + BOOST_LOG_API explicit rotation_at_time_point( + gregorian::greg_day mday, + unsigned char hour = 0, + unsigned char minute = 0, + unsigned char second = 0); + + /*! + * Checks if it's time to rotate the file + */ + BOOST_LOG_API bool operator() () const; +}; + +/*! + * The class represents the time interval of log file rotation. The log file will be rotated + * after the specified time interval has passed. + */ +class rotation_at_time_interval +{ +public: + typedef bool result_type; + +private: + posix_time::time_duration m_Interval; + mutable posix_time::ptime m_Previous; + +public: + /*! + * Creates a rotation time interval of the specified duration + * + * \param interval The interval of the rotation, should be no less than 1 second + */ + explicit rotation_at_time_interval(posix_time::time_duration const& interval) : + m_Interval(interval) + { + BOOST_ASSERT(!interval.is_special()); + BOOST_ASSERT(interval.total_seconds() > 0); + } + + /*! + * Checks if it's time to rotate the file + */ + BOOST_LOG_API bool operator() () const; +}; + +} // namespace file + + +/*! + * \brief An implementation of a text file logging sink backend + * + * The sink backend puts formatted log records to a text file. + * The sink supports file rotation and advanced file control, such as + * size and file count restriction. + */ +class text_file_backend : + public basic_formatted_sink_backend< + char, + combine_requirements< synchronized_feeding, flushing >::type + > +{ + //! Base type + typedef basic_formatted_sink_backend< + char, + combine_requirements< synchronized_feeding, flushing >::type + > base_type; + +public: + //! Character type + typedef base_type::char_type char_type; + //! String type to be used as a message text holder + typedef base_type::string_type string_type; + //! Stream type + typedef std::basic_ostream< char_type > stream_type; + + //! File open handler + typedef boost::log::aux::light_function< void (stream_type&) > open_handler_type; + //! File close handler + typedef boost::log::aux::light_function< void (stream_type&) > close_handler_type; + + //! Predicate that defines the time-based condition for file rotation + typedef boost::log::aux::light_function< bool () > time_based_rotation_predicate; + +private: + //! \cond + + struct implementation; + implementation* m_pImpl; + + //! \endcond + +public: + /*! + * Default constructor. The constructed sink backend uses default values of all the parameters. + */ + BOOST_LOG_API text_file_backend(); + + /*! + * Constructor. Creates a sink backend with the specified named parameters. + * The following named parameters are supported: + * + * \li \c file_name - Specifies the file name pattern where logs are actually written to. The pattern may + * contain directory and file name portions, but only the file name may contain + * placeholders. The backend supports Boost.DateTime placeholders for injecting + * current time and date into the file name. Also, an additional %N placeholder is + * supported, it will be replaced with an integral increasing file counter. The placeholder + * may also contain width specification in the printf-compatible form (e.g. %5N). The + * printed file counter will always be zero-filled. If \c file_name is not specified, + * pattern "%5N.log" will be used. + * \li \c open_mode - File open mode. The mode should be presented in form of mask compatible to + * <tt>std::ios_base::openmode</tt>. If not specified, <tt>trunc | out</tt> will be used. + * \li \c rotation_size - Specifies the approximate size, in characters written, of the temporary file + * upon which the file is passed to the file collector. Note the size does + * not count any possible character conversions that may take place during + * writing to the file. If not specified, the file won't be rotated upon reaching + * any size. + * \li \c time_based_rotation - Specifies the predicate for time-based file rotation. + * No time-based file rotations will be performed, if not specified. + * \li \c auto_flush - Specifies a flag, whether or not to automatically flush the file after each + * written log record. By default, is \c false. + * + * \note Read the caution note regarding file name pattern in the <tt>sinks::file::collector::scan_for_files</tt> + * documentation. + */ +#ifndef BOOST_LOG_DOXYGEN_PASS + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(text_file_backend, construct) +#else + template< typename... ArgsT > + explicit text_file_backend(ArgsT... const& args); +#endif + + /*! + * Destructor + */ + BOOST_LOG_API ~text_file_backend(); + + /*! + * The method sets file name wildcard for the files being written. The wildcard supports + * date and time injection into the file name. + * + * \param pattern The name pattern for the file being written. + */ + template< typename PathT > + void set_file_name_pattern(PathT const& pattern) + { + set_file_name_pattern_internal(filesystem::path(pattern)); + } + + /*! + * The method sets the file open mode + * + * \param mode File open mode + */ + BOOST_LOG_API void set_open_mode(std::ios_base::openmode mode); + + /*! + * The method sets the log file collector function. The function is called + * on file rotation and is being passed the written file name. + * + * \param collector The file collector function object + */ + BOOST_LOG_API void set_file_collector(shared_ptr< file::collector > const& collector); + + /*! + * The method sets file opening handler. The handler will be called every time + * the backend opens a new temporary file. The handler may write a header to the + * opened file in order to maintain file validity. + * + * \param handler The file open handler function object + */ + BOOST_LOG_API void set_open_handler(open_handler_type const& handler); + + /*! + * The method sets file closing handler. The handler will be called every time + * the backend closes a temporary file. The handler may write a footer to the + * opened file in order to maintain file validity. + * + * \param handler The file close handler function object + */ + BOOST_LOG_API void set_close_handler(close_handler_type const& handler); + + /*! + * The method sets maximum file size. When the size is reached, file rotation is performed. + * + * \note The size does not count any possible character translations that may happen in + * the underlying API. This may result in greater actual sizes of the written files. + * + * \param size The maximum file size, in characters. + */ + BOOST_LOG_API void set_rotation_size(uintmax_t size); + + /*! + * The method sets the predicate that defines the time-based condition for file rotation. + * + * \note The rotation always occurs on writing a log record, so the rotation is + * not strictly bound to the specified condition. + * + * \param predicate The predicate that defines the time-based condition for file rotation. + * If empty, no time-based rotation will take place. + */ + BOOST_LOG_API void set_time_based_rotation(time_based_rotation_predicate const& predicate); + + /*! + * Sets the flag to automatically flush buffers of all attached streams after each log record + */ + BOOST_LOG_API void auto_flush(bool f = true); + + /*! + * Performs scanning of the target directory for log files that may have been left from + * previous runs of the application. The found files are considered by the file collector + * as if they were rotated. + * + * The file scan can be performed in two ways: either all files in the target directory will + * be considered as log files, or only those files that satisfy the file name pattern. + * See documentation on <tt>sinks::file::collector::scan_for_files</tt> for more information. + * + * \pre File collector and the proper file name pattern have already been set. + * + * \param method File scanning method + * \param update_counter If \c true and \a method is \c scan_matching, the method attempts + * to update the internal file counter according to the found files. The counter + * is unaffected otherwise. + * \return The number of files found. + * + * \note The method essentially delegates to the same-named function of the file collector. + */ + BOOST_LOG_API uintmax_t scan_for_files( + file::scan_method method = file::scan_matching, bool update_counter = true); + + /*! + * The method writes the message to the sink + */ + BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); + + /*! + * The method flushes the currently open log file + */ + BOOST_LOG_API void flush(); + + /*! + * The method rotates the file + */ + BOOST_LOG_API void rotate_file(); + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! Constructor implementation + template< typename ArgsT > + void construct(ArgsT const& args) + { + construct( + filesystem::path(args[keywords::file_name | filesystem::path()]), + args[keywords::open_mode | (std::ios_base::trunc | std::ios_base::out)], + args[keywords::rotation_size | (std::numeric_limits< uintmax_t >::max)()], + args[keywords::time_based_rotation | time_based_rotation_predicate()], + args[keywords::auto_flush | false]); + } + //! Constructor implementation + BOOST_LOG_API void construct( + filesystem::path const& pattern, + std::ios_base::openmode mode, + uintmax_t rotation_size, + time_based_rotation_predicate const& time_based_rotation, + bool auto_flush); + + //! The method sets file name mask + BOOST_LOG_API void set_file_name_pattern_internal(filesystem::path const& pattern); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/text_multifile_backend.hpp b/boost/log/sinks/text_multifile_backend.hpp new file mode 100644 index 0000000000..d2f897892e --- /dev/null +++ b/boost/log/sinks/text_multifile_backend.hpp @@ -0,0 +1,201 @@ +/* + * 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 text_multifile_backend.hpp + * \author Andrey Semashev + * \date 09.06.2009 + * + * The header contains implementation of a text multi-file sink backend. + */ + +#ifndef BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_ + +#include <ios> +#include <string> +#include <locale> +#include <ostream> +#include <boost/mpl/if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/cleanup_scope_guard.hpp> +#include <boost/log/sinks/basic_sink_backend.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace file { + + /*! + * An adapter class that allows to use regular formatters as file name generators. + */ + template< typename FormatterT > + class file_name_composer_adapter + { + public: + //! Functor result type + typedef filesystem::path result_type; + //! File name character type + typedef result_type::string_type::value_type native_char_type; + //! The adopted formatter type + typedef FormatterT formatter_type; + //! Formatting stream type + typedef basic_formatting_ostream< native_char_type > stream_type; + + private: + //! The adopted formatter + formatter_type m_Formatter; + //! Formatted file name storage + mutable result_type::string_type m_FileName; + //! Formatting stream + mutable stream_type m_FormattingStream; + + public: + /*! + * Initializing constructor + */ + explicit file_name_composer_adapter(formatter_type const& formatter, std::locale const& loc = std::locale()) : + m_Formatter(formatter), + m_FormattingStream(m_FileName) + { + m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); + m_FormattingStream.imbue(loc); + } + /*! + * Copy constructor + */ + file_name_composer_adapter(file_name_composer_adapter const& that) : + m_Formatter(that.m_Formatter), + m_FormattingStream(m_FileName) + { + m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); + m_FormattingStream.imbue(that.m_FormattingStream.getloc()); + } + /*! + * Assignment + */ + file_name_composer_adapter& operator= (file_name_composer_adapter const& that) + { + m_Formatter = that.m_Formatter; + return *this; + } + + /*! + * The operator generates a file name based on the log record + */ + result_type operator() (record_view const& rec) const + { + boost::log::aux::cleanup_guard< stream_type > cleanup1(m_FormattingStream); + boost::log::aux::cleanup_guard< result_type::string_type > cleanup2(m_FileName); + + m_Formatter(rec, m_FormattingStream); + m_FormattingStream.flush(); + + return result_type(m_FileName); + } + }; + + /*! + * The function adopts a log record formatter into a file name generator + */ + template< typename FormatterT > + inline file_name_composer_adapter< FormatterT > as_file_name_composer( + FormatterT const& fmt, std::locale const& loc = std::locale()) + { + return file_name_composer_adapter< FormatterT >(fmt, loc); + } + +} // namespace file + + +/*! + * \brief An implementation of a text multiple files logging sink backend + * + * The sink backend puts formatted log records to one of the text files. + * The particular file is chosen upon each record's attribute values, which allows + * to distribute records into individual files or to group records related to + * some entity or process in a separate file. + */ +class text_multifile_backend : + public basic_formatted_sink_backend< char > +{ + //! Base type + typedef basic_formatted_sink_backend< char > base_type; + +public: + //! Character type + typedef base_type::char_type char_type; + //! String type to be used as a message text holder + typedef base_type::string_type string_type; + + //! File name composer functor type + typedef boost::log::aux::light_function< filesystem::path (record_view const&) > file_name_composer_type; + +private: + //! \cond + + struct implementation; + implementation* m_pImpl; + + //! \endcond + +public: + /*! + * Default constructor. The constructed sink backend has no file name composer and + * thus will not write any files. + */ + BOOST_LOG_API text_multifile_backend(); + + /*! + * Destructor + */ + BOOST_LOG_API ~text_multifile_backend(); + + /*! + * The method sets file name composer functional object. Log record formatters are accepted, too. + * + * \param composer File name composer functor + */ + template< typename ComposerT > + void set_file_name_composer(ComposerT const& composer) + { + set_file_name_composer_internal(composer); + } + + /*! + * The method writes the message to the sink + */ + BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! The method sets the file name composer + BOOST_LOG_API void set_file_name_composer_internal(file_name_composer_type const& composer); +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/text_ostream_backend.hpp b/boost/log/sinks/text_ostream_backend.hpp new file mode 100644 index 0000000000..4c93d31357 --- /dev/null +++ b/boost/log/sinks/text_ostream_backend.hpp @@ -0,0 +1,124 @@ +/* + * 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 text_ostream_backend.hpp + * \author Andrey Semashev + * \date 22.04.2007 + * + * The header contains implementation of a text output stream sink backend. + */ + +#ifndef BOOST_LOG_SINKS_TEXT_OSTREAM_BACKEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_TEXT_OSTREAM_BACKEND_HPP_INCLUDED_ + +#include <ostream> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/sinks/basic_sink_backend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief An implementation of a text output stream logging sink backend + * + * The sink backend puts formatted log records to one or more text streams. + */ +template< typename CharT > +class basic_text_ostream_backend : + public basic_formatted_sink_backend< + CharT, + combine_requirements< synchronized_feeding, flushing >::type + > +{ + //! Base type + typedef basic_formatted_sink_backend< + CharT, + combine_requirements< synchronized_feeding, flushing >::type + > base_type; + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! String type to be used as a message text holder + typedef typename base_type::string_type string_type; + //! Output stream type + typedef std::basic_ostream< char_type > stream_type; + +private: + //! \cond + + struct implementation; + implementation* m_pImpl; + + //! \endcond + +public: + /*! + * Constructor. No streams attached to the constructed backend, auto flush feature disabled. + */ + BOOST_LOG_API basic_text_ostream_backend(); + /*! + * Destructor + */ + BOOST_LOG_API ~basic_text_ostream_backend(); + + /*! + * The method adds a new stream to the sink. + * + * \param strm Pointer to the stream. Must not be NULL. + */ + BOOST_LOG_API void add_stream(shared_ptr< stream_type > const& strm); + /*! + * The method removes a stream from the sink. If the stream is not attached to the sink, + * the method has no effect. + * + * \param strm Pointer to the stream. Must not be NULL. + */ + BOOST_LOG_API void remove_stream(shared_ptr< stream_type > const& strm); + + /*! + * Sets the flag to automatically flush buffers of all attached streams after each log record + */ + BOOST_LOG_API void auto_flush(bool f = true); + + /*! + * The method writes the message to the sink + */ + BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); + + /*! + * The method flushes the associated streams + */ + BOOST_LOG_API void flush(); +}; + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_text_ostream_backend< char > text_ostream_backend; //!< Convenience typedef for narrow-character logging +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_text_ostream_backend< wchar_t > wtext_ostream_backend; //!< Convenience typedef for wide-character logging +#endif + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_TEXT_OSTREAM_BACKEND_HPP_INCLUDED_ diff --git a/boost/log/sinks/unbounded_fifo_queue.hpp b/boost/log/sinks/unbounded_fifo_queue.hpp new file mode 100644 index 0000000000..2782c5476c --- /dev/null +++ b/boost/log/sinks/unbounded_fifo_queue.hpp @@ -0,0 +1,142 @@ +/* + * 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 unbounded_fifo_queue.hpp + * \author Andrey Semashev + * \date 24.07.2011 + * + * The header contains implementation of unbounded FIFO queueing strategy for + * the asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: This header content is only supported in multithreaded environment +#endif + +#include <boost/log/detail/event.hpp> +#include <boost/log/detail/threadsafe_queue.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Unbounded FIFO log record queueing strategy + * + * The \c unbounded_fifo_queue class is intended to be used with + * the \c asynchronous_sink frontend as a log record queueing strategy. + * + * This strategy implements the simplest logic of log record buffering between + * threads: the queue has no limits and imposes no ordering over the queued + * elements aside from the order in which they are enqueued. + * Because of this the queue provides decent performance and scalability, + * however if sink backends can't consume log records fast enough the queue + * may grow uncontrollably. When this is an issue, it is recommended to + * use one of the bounded strategies. + */ +class unbounded_fifo_queue +{ +private: + typedef boost::log::aux::threadsafe_queue< record_view > queue_type; + +private: + //! Thread-safe queue + queue_type m_queue; + //! Event object to block on + boost::log::aux::event m_event; + //! Interruption flag + volatile bool m_interruption_requested; // TODO: make it atomic + +protected: + //! Default constructor + unbounded_fifo_queue() : m_interruption_requested(false) + { + } + //! Initializing constructor + template< typename ArgsT > + explicit unbounded_fifo_queue(ArgsT const&) : m_interruption_requested(false) + { + } + + //! Enqueues log record to the queue + void enqueue(record_view const& rec) + { + m_queue.push(rec); + m_event.set_signalled(); + } + + //! Attempts to enqueue log record to the queue + bool try_enqueue(record_view const& rec) + { + // Assume the call never blocks + enqueue(rec); + return true; + } + + //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty + bool try_dequeue_ready(record_view& rec) + { + return m_queue.try_pop(rec); + } + + //! Attempts to dequeue log record from the queue, does not block if the queue is empty + bool try_dequeue(record_view& rec) + { + return m_queue.try_pop(rec); + } + + //! Dequeues log record from the queue, blocks if the queue is empty + bool dequeue_ready(record_view& rec) + { + // Try the fast way first + if (m_queue.try_pop(rec)) + return true; + + // Ok, we probably have to wait for new records + while (true) + { + m_event.wait(); + if (m_interruption_requested) + { + m_interruption_requested = false; + return false; + } + if (m_queue.try_pop(rec)) + return true; + } + } + + //! Wakes a thread possibly blocked in the \c dequeue method + void interrupt_dequeue() + { + m_interruption_requested = true; + m_event.set_signalled(); + } +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_ diff --git a/boost/log/sinks/unbounded_ordering_queue.hpp b/boost/log/sinks/unbounded_ordering_queue.hpp new file mode 100644 index 0000000000..f67e629a3e --- /dev/null +++ b/boost/log/sinks/unbounded_ordering_queue.hpp @@ -0,0 +1,245 @@ +/* + * 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 unbounded_ordering_queue.hpp + * \author Andrey Semashev + * \date 24.07.2011 + * + * The header contains implementation of unbounded ordering record queueing strategy for + * the asynchronous sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_UNBOUNDED_ORDERING_QUEUE_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_UNBOUNDED_ORDERING_QUEUE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_LOG_NO_THREADS) +#error Boost.Log: This header content is only supported in multithreaded environment +#endif + +#include <queue> +#include <vector> +#include <boost/cstdint.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/thread_time.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/log/detail/timestamp.hpp> +#include <boost/log/detail/enqueued_record.hpp> +#include <boost/log/keywords/order.hpp> +#include <boost/log/keywords/ordering_window.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +/*! + * \brief Unbounded ordering log record queueing strategy + * + * The \c unbounded_ordering_queue class is intended to be used with + * the \c asynchronous_sink frontend as a log record queueing strategy. + * + * This strategy provides the following properties to the record queueing mechanism: + * + * \li The queue has no size limits. + * \li The queue has a fixed latency window. This means that each log record put + * into the queue will normally not be dequeued for a certain period of time. + * \li The queue performs stable record ordering within the latency window. + * The ordering predicate can be specified in the \c OrderT template parameter. + * + * Since this queue has no size limits, it may grow uncontrollably if sink backends + * dequeue log records not fast enough. When this is an issue, it is recommended to + * use one of the bounded strategies. + */ +template< typename OrderT > +class unbounded_ordering_queue +{ +private: + typedef boost::mutex mutex_type; + typedef sinks::aux::enqueued_record enqueued_record; + + typedef std::priority_queue< + enqueued_record, + std::vector< enqueued_record >, + enqueued_record::order< OrderT > + > queue_type; + +private: + //! Ordering window duration, in milliseconds + const uint64_t m_ordering_window; + //! Synchronization mutex + mutex_type m_mutex; + //! Condition for blocking + condition_variable m_cond; + //! Thread-safe queue + queue_type m_queue; + //! Interruption flag + bool m_interruption_requested; + +public: + /*! + * Returns ordering window size specified during initialization + */ + posix_time::time_duration get_ordering_window() const + { + return posix_time::milliseconds(m_ordering_window); + } + + /*! + * Returns default ordering window size. + * The default window size is specific to the operating system thread scheduling mechanism. + */ + static posix_time::time_duration get_default_ordering_window() + { + // The main idea behind this parameter is that the ordering window should be large enough + // to allow the frontend to order records from different threads on an attribute + // that contains system time. Thus this value should be: + // * No less than the minimum time resolution quant that Boost.DateTime provides on the current OS. + // For instance, on Windows it defaults to around 15-16 ms. + // * No less than thread switching quant on the current OS. For now 30 ms is large enough window size to + // switch threads on any known OS. It can be tuned for other platforms as needed. + return posix_time::milliseconds(30); + } + +protected: + //! Initializing constructor + template< typename ArgsT > + explicit unbounded_ordering_queue(ArgsT const& args) : + m_ordering_window(args[keywords::ordering_window || &unbounded_ordering_queue::get_default_ordering_window].total_milliseconds()), + m_queue(args[keywords::order]), + m_interruption_requested(false) + { + } + + //! Enqueues log record to the queue + void enqueue(record_view const& rec) + { + lock_guard< mutex_type > lock(m_mutex); + enqueue_unlocked(rec); + } + + //! Attempts to enqueue log record to the queue + bool try_enqueue(record_view const& rec) + { + unique_lock< mutex_type > lock(m_mutex, try_to_lock); + if (lock.owns_lock()) + { + enqueue_unlocked(rec); + return true; + } + else + return false; + } + + //! Attempts to dequeue a log record ready for processing from the queue, does not block if no log records are ready to be processed + bool try_dequeue_ready(record_view& rec) + { + lock_guard< mutex_type > lock(m_mutex); + if (!m_queue.empty()) + { + const boost::log::aux::timestamp now = boost::log::aux::get_timestamp(); + enqueued_record const& elem = m_queue.top(); + if (static_cast< uint64_t >((now - elem.m_timestamp).milliseconds()) >= m_ordering_window) + { + // We got a new element + rec = elem.m_record; + m_queue.pop(); + return true; + } + } + + return false; + } + + //! Attempts to dequeue log record from the queue, does not block. + bool try_dequeue(record_view& rec) + { + lock_guard< mutex_type > lock(m_mutex); + if (!m_queue.empty()) + { + enqueued_record const& elem = m_queue.top(); + rec = elem.m_record; + m_queue.pop(); + return true; + } + + return false; + } + + //! Dequeues log record from the queue, blocks if no log records are ready to be processed + bool dequeue_ready(record_view& rec) + { + unique_lock< mutex_type > lock(m_mutex); + while (!m_interruption_requested) + { + if (!m_queue.empty()) + { + const boost::log::aux::timestamp now = boost::log::aux::get_timestamp(); + enqueued_record const& elem = m_queue.top(); + const uint64_t difference = (now - elem.m_timestamp).milliseconds(); + if (difference >= m_ordering_window) + { + // We got a new element + rec = elem.m_record; + m_queue.pop(); + return true; + } + else + { + // Wait until the element becomes ready to be processed + m_cond.timed_wait(lock, posix_time::milliseconds(m_ordering_window - difference)); + } + } + else + { + // Wait for an element to come + m_cond.wait(lock); + } + } + m_interruption_requested = false; + + return false; + } + + //! Wakes a thread possibly blocked in the \c dequeue method + void interrupt_dequeue() + { + lock_guard< mutex_type > lock(m_mutex); + m_interruption_requested = true; + m_cond.notify_one(); + } + +private: + //! Enqueues a log record + void enqueue_unlocked(record_view const& rec) + { + const bool was_empty = m_queue.empty(); + m_queue.push(enqueued_record(rec)); + if (was_empty) + m_cond.notify_one(); + } +}; + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_UNBOUNDED_ORDERING_QUEUE_HPP_INCLUDED_ diff --git a/boost/log/sinks/unlocked_frontend.hpp b/boost/log/sinks/unlocked_frontend.hpp new file mode 100644 index 0000000000..ab144d57b8 --- /dev/null +++ b/boost/log/sinks/unlocked_frontend.hpp @@ -0,0 +1,142 @@ +/* + * 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 unlocked_frontend.hpp + * \author Andrey Semashev + * \date 14.07.2009 + * + * The header contains declaration of an unlocked sink frontend. + */ + +#ifndef BOOST_LOG_SINKS_UNLOCKED_FRONTEND_HPP_INCLUDED_ +#define BOOST_LOG_SINKS_UNLOCKED_FRONTEND_HPP_INCLUDED_ + +#include <boost/static_assert.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/detail/fake_mutex.hpp> +#include <boost/log/sinks/basic_sink_frontend.hpp> +#include <boost/log/sinks/frontend_requirements.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, types)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit unlocked_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ + base_type(false),\ + m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {} + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Non-blocking logging sink frontend + * + * The sink frontend does not perform thread synchronization and + * simply passes logging records to the sink backend. + */ +template< typename SinkBackendT > +class unlocked_sink : + public aux::make_sink_frontend_base< SinkBackendT >::type +{ + typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type; + +public: + //! Sink implementation type + typedef SinkBackendT sink_backend_type; + //! \cond + BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, concurrent_feeding >::value), "Unlocked sink frontend is incompatible with the specified backend: thread synchronization requirements are not met"); + //! \endcond + + //! Type of pointer to the backend + typedef shared_ptr< sink_backend_type > locked_backend_ptr; + +private: + //! Pointer to the backend + const shared_ptr< sink_backend_type > m_pBackend; + +public: + /*! + * Default constructor. Constructs the sink backend instance. + * Requires the backend to be default-constructible. + */ + unlocked_sink() : + base_type(false), + m_pBackend(boost::make_shared< sink_backend_type >()) + { + } + /*! + * Constructor attaches user-constructed backend instance + * + * \param backend Pointer to the backend instance + * + * \pre \a backend is not \c NULL. + */ + explicit unlocked_sink(shared_ptr< sink_backend_type > const& backend) : + base_type(false), + m_pBackend(backend) + { + } + + // Constructors that pass arbitrary parameters to the backend constructor + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~) + + /*! + * Locking accessor to the attached backend. + * + * \note Does not do any actual locking, provided only for interface consistency + * with other frontends. + */ + locked_backend_ptr locked_backend() + { + return m_pBackend; + } + + /*! + * Passes the log record to the backend + */ + void consume(record_view const& rec) + { + boost::log::aux::fake_mutex m; + base_type::feed_record(rec, m, *m_pBackend); + } + + /*! + * The method performs flushing of any internal buffers that may hold log records. The method + * may take considerable time to complete and may block both the calling thread and threads + * attempting to put new records into the sink while this call is in progress. + */ + void flush() + { + boost::log::aux::fake_mutex m; + base_type::flush_backend(m, *m_pBackend); + } +}; + +#undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SINKS_UNLOCKED_FRONTEND_HPP_INCLUDED_ diff --git a/boost/log/sources/basic_logger.hpp b/boost/log/sources/basic_logger.hpp new file mode 100644 index 0000000000..0f0842934b --- /dev/null +++ b/boost/log/sources/basic_logger.hpp @@ -0,0 +1,742 @@ +/* + * 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 basic_logger.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * The header contains implementation of a base class for loggers. Convenience macros + * for defining custom loggers are also provided. + */ + +#ifndef BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_ + +#include <exception> +#include <utility> +#include <ostream> +#include <boost/assert.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/preprocessor/facilities/empty.hpp> +#include <boost/preprocessor/facilities/identity.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/seq/enum.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/attributes/attribute_set.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/core/core.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/sources/features.hpp> +#include <boost/log/sources/threading_models.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +/*! + * \brief Basic logger class + * + * The \c basic_logger class template serves as a base class for all loggers + * provided by the library. It can also be used as a base for user-defined + * loggers. The template parameters are: + * + * \li \c CharT - logging character type + * \li \c FinalT - final type of the logger that eventually derives from + * the \c basic_logger. There may be other classes in the hierarchy + * between the final class and \c basic_logger. + * \li \c ThreadingModelT - threading model policy. Must provide methods + * of the Boost.Thread locking concept used in \c basic_logger class + * and all its derivatives in the hierarchy up to the \c FinalT class. + * The \c basic_logger class itself requires methods of the + * SharedLockable concept. The threading model policy must also be + * default and copy-constructible and support member function \c swap. + * There are currently two policies provided: \c single_thread_model + * and \c multi_thread_model. + * + * The logger implements fundamental facilities of loggers, such as storing + * source-specific attribute set and formatting log record messages. The basic + * logger interacts with the logging core in order to apply filtering and + * pass records to sinks. + */ +template< typename CharT, typename FinalT, typename ThreadingModelT > +class basic_logger : + public ThreadingModelT +{ + typedef basic_logger this_type; + BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) + +public: + //! Character type + typedef CharT char_type; + //! Final logger type + typedef FinalT final_type; + //! Threading model type + typedef ThreadingModelT threading_model; + +#if !defined(BOOST_LOG_NO_THREADS) + //! Lock requirement for the swap_unlocked method + typedef boost::log::aux::exclusive_lock_guard< threading_model > swap_lock; + //! Lock requirement for the add_attribute_unlocked method + typedef boost::log::aux::exclusive_lock_guard< threading_model > add_attribute_lock; + //! Lock requirement for the remove_attribute_unlocked method + typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_attribute_lock; + //! Lock requirement for the remove_all_attributes_unlocked method + typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_all_attributes_lock; + //! Lock requirement for the get_attributes method + typedef boost::log::aux::shared_lock_guard< const threading_model > get_attributes_lock; + //! Lock requirement for the open_record_unlocked method + typedef boost::log::aux::shared_lock_guard< threading_model > open_record_lock; + //! Lock requirement for the set_attributes method + typedef boost::log::aux::exclusive_lock_guard< threading_model > set_attributes_lock; +#else + typedef no_lock< threading_model > swap_lock; + typedef no_lock< threading_model > add_attribute_lock; + typedef no_lock< threading_model > remove_attribute_lock; + typedef no_lock< threading_model > remove_all_attributes_lock; + typedef no_lock< const threading_model > get_attributes_lock; + typedef no_lock< threading_model > open_record_lock; + typedef no_lock< threading_model > set_attributes_lock; +#endif + + //! Lock requirement for the push_record_unlocked method + typedef no_lock< threading_model > push_record_lock; + +private: + //! A pointer to the logging system + core_ptr m_pCore; + + //! Logger-specific attribute set + attribute_set m_Attributes; + +public: + /*! + * Constructor. Initializes internal data structures of the basic logger class, + * acquires reference to the logging core. + */ + basic_logger() : + threading_model(), + m_pCore(core::get()) + { + } + /*! + * Copy constructor. Copies all attributes from the source logger. + * + * \note Not thread-safe. The source logger must be locked in the final class before copying. + * + * \param that Source logger + */ + basic_logger(basic_logger const& that) : + threading_model(static_cast< threading_model const& >(that)), + m_pCore(core::get()), + m_Attributes(that.m_Attributes) + { + } + /*! + * Move constructor. Moves all attributes from the source logger. + * + * \note Not thread-safe. The source logger must be locked in the final class before copying. + * + * \param that Source logger + */ + basic_logger(BOOST_RV_REF(basic_logger) that) : + threading_model(boost::move(static_cast< threading_model& >(that))) + { + m_pCore.swap(that.m_pCore); + m_Attributes.swap(that.m_Attributes); + } + /*! + * Constructor with named arguments. The constructor ignores all arguments. The result of + * construction is equivalent to default construction. + */ + template< typename ArgsT > + explicit basic_logger(ArgsT const&) : + threading_model(), + m_pCore(core::get()) + { + } + +protected: + /*! + * An accessor to the logging system pointer + */ + core_ptr const& core() const { return m_pCore; } + /*! + * An accessor to the logger attributes + */ + attribute_set& attributes() { return m_Attributes; } + /*! + * An accessor to the logger attributes + */ + attribute_set const& attributes() const { return m_Attributes; } + /*! + * An accessor to the threading model base + */ + threading_model& get_threading_model() { return *this; } + /*! + * An accessor to the threading model base + */ + threading_model const& get_threading_model() const { return *this; } + /*! + * An accessor to the final logger + */ + final_type* final_this() + { + BOOST_LOG_ASSUME(this != NULL); + return static_cast< final_type* >(this); + } + /*! + * An accessor to the final logger + */ + final_type const* final_this() const + { + BOOST_LOG_ASSUME(this != NULL); + return static_cast< final_type const* >(this); + } + + /*! + * Unlocked \c swap + */ + void swap_unlocked(basic_logger& that) + { + get_threading_model().swap(that.get_threading_model()); + m_Attributes.swap(that.m_Attributes); + } + + /*! + * Unlocked \c add_attribute + */ + std::pair< attribute_set::iterator, bool > add_attribute_unlocked(attribute_name const& name, attribute const& attr) + { + return m_Attributes.insert(name, attr); + } + + /*! + * Unlocked \c remove_attribute + */ + void remove_attribute_unlocked(attribute_set::iterator it) + { + m_Attributes.erase(it); + } + + /*! + * Unlocked \c remove_all_attributes + */ + void remove_all_attributes_unlocked() + { + m_Attributes.clear(); + } + + /*! + * Unlocked \c open_record + */ + record open_record_unlocked() + { + return m_pCore->open_record(m_Attributes); + } + /*! + * Unlocked \c open_record + */ + template< typename ArgsT > + record open_record_unlocked(ArgsT const&) + { + return m_pCore->open_record(m_Attributes); + } + + /*! + * Unlocked \c push_record + */ + void push_record_unlocked(BOOST_RV_REF(record) rec) + { + m_pCore->push_record(boost::move(rec)); + } + + /*! + * Unlocked \c get_attributes + */ + attribute_set get_attributes_unlocked() const + { + return m_Attributes; + } + + /*! + * Unlocked \c set_attributes + */ + void set_attributes_unlocked(attribute_set const& attrs) + { + m_Attributes = attrs; + } + + //! Assignment is closed (should be implemented through copy and swap in the final class) + BOOST_DELETED_FUNCTION(basic_logger& operator= (basic_logger const&)) +}; + +/*! + * Free-standing swap for all loggers + */ +template< typename CharT, typename FinalT, typename ThreadingModelT > +inline void swap( + basic_logger< CharT, FinalT, ThreadingModelT >& left, + basic_logger< CharT, FinalT, ThreadingModelT >& right) +{ + static_cast< FinalT& >(left).swap(static_cast< FinalT& >(right)); +} + +/*! + * \brief A composite logger that inherits a number of features + * + * The composite logger is a helper class that simplifies feature composition into the final logger. + * The user's logger class is expected to derive from the composite logger class, instantiated with + * the character type, the user's logger class, the threading model and the list of the required features. + * The former three parameters are passed to the \c basic_logger class template. The feature list + * must be an MPL type sequence, where each element is a unary MPL metafunction class, that upon + * applying on its argument results in a logging feature class that derives from the argument. + * Every logger feature provided by the library can participate in the feature list. + */ +template< typename CharT, typename FinalT, typename ThreadingModelT, typename FeaturesT > +class basic_composite_logger : + public boost::log::sources::aux::inherit_features< + basic_logger< CharT, FinalT, ThreadingModelT >, + FeaturesT + >::type +{ +private: + //! Base type (the hierarchy of features) + typedef typename boost::log::sources::aux::inherit_features< + basic_logger< CharT, FinalT, ThreadingModelT >, + FeaturesT + >::type base_type; + +protected: + //! The composite logger type (for use in the user's logger class) + typedef basic_composite_logger logger_base; + BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base) + +public: + //! Threading model being used + typedef typename base_type::threading_model threading_model; + +#if !defined(BOOST_LOG_NO_THREADS) + +public: + /*! + * Default constructor (default-constructs all features) + */ + basic_composite_logger() {} + /*! + * Copy constructor + */ + basic_composite_logger(basic_composite_logger const& that) : + base_type + (( + boost::log::aux::shared_lock_guard< const threading_model >(that.get_threading_model()), + static_cast< base_type const& >(that) + )) + { + } + /*! + * Move constructor + */ + basic_composite_logger(BOOST_RV_REF(logger_base) that) : + base_type(boost::move(static_cast< base_type& >(that))) + { + } + /*! + * Constructor with named parameters + */ + template< typename ArgsT > + explicit basic_composite_logger(ArgsT const& args) : base_type(args) + { + } + + /*! + * The method adds an attribute to the source-specific attribute set. The attribute will be implicitly added to + * every log record made with the current logger. + * + * \param name The attribute name. + * \param attr The attribute factory. + * \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the + * attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents + * addition. + */ + std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr) + { + typename base_type::add_attribute_lock lock(base_type::get_threading_model()); + return base_type::add_attribute_unlocked(name, attr); + } + /*! + * The method removes an attribute from the source-specific attribute set. + * + * \pre The attribute was added with the add_attribute call for this instance of the logger. + * \post The attribute is no longer registered as a source-specific attribute for this logger. The iterator is invalidated after removal. + * + * \param it Iterator to the previously added attribute. + */ + void remove_attribute(attribute_set::iterator it) + { + typename base_type::remove_attribute_lock lock(base_type::get_threading_model()); + base_type::remove_attribute_unlocked(it); + } + + /*! + * The method removes all attributes from the logger. All iterators and references to the removed attributes are invalidated. + */ + void remove_all_attributes() + { + typename base_type::remove_all_attributes_lock lock(base_type::get_threading_model()); + base_type::remove_all_attributes_unlocked(); + } + + /*! + * The method retrieves a copy of a set with all attributes from the logger. + * + * \return The copy of the attribute set. Attributes are shallow-copied. + */ + attribute_set get_attributes() const + { + typename base_type::get_attributes_lock lock(base_type::get_threading_model()); + return base_type::get_attributes_unlocked(); + } + + /*! + * The method installs the whole attribute set into the logger. All iterators and references to elements of + * the previous set are invalidated. Iterators to the \a attrs set are not valid to be used with the logger (that is, + * the logger owns a copy of \a attrs after completion). + * + * \param attrs The set of attributes to install into the logger. Attributes are shallow-copied. + */ + void set_attributes(attribute_set const& attrs) + { + typename base_type::set_attributes_lock lock(base_type::get_threading_model()); + base_type::set_attributes_unlocked(attrs); + } + + /*! + * The method opens a new log record in the logging core. + * + * \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise. + */ + record open_record() + { + // Perform a quick check first + if (this->core()->get_logging_enabled()) + { + typename base_type::open_record_lock lock(base_type::get_threading_model()); + return base_type::open_record_unlocked(boost::log::aux::empty_arg_list()); + } + else + return record(); + } + /*! + * The method opens a new log record in the logging core. + * + * \param args A set of additional named arguments. The parameter is ignored. + * \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise. + */ + template< typename ArgsT > + record open_record(ArgsT const& args) + { + // Perform a quick check first + if (this->core()->get_logging_enabled()) + { + typename base_type::open_record_lock lock(base_type::get_threading_model()); + return base_type::open_record_unlocked(args); + } + else + return record(); + } + /*! + * The method pushes the constructed message to the logging core + * + * \param rec The log record with the formatted message + */ + void push_record(BOOST_RV_REF(record) rec) + { + typename base_type::push_record_lock lock(base_type::get_threading_model()); + base_type::push_record_unlocked(boost::move(rec)); + } + /*! + * Thread-safe implementation of swap + */ + void swap(basic_composite_logger& that) + { + boost::log::aux::multiple_unique_lock2< + threading_model, + threading_model + > lock(base_type::get_threading_model(), that.get_threading_model()); + base_type::swap_unlocked(that); + } + +protected: + /*! + * Assignment for the final class. Threadsafe, provides strong exception guarantee. + */ + FinalT& assign(FinalT const& that) + { + BOOST_LOG_ASSUME(this != NULL); + if (static_cast< FinalT* >(this) != boost::addressof(that)) + { + // We'll have to explicitly create the copy in order to make sure it's unlocked when we attempt to lock *this + FinalT tmp(that); + boost::log::aux::exclusive_lock_guard< threading_model > lock(base_type::get_threading_model()); + base_type::swap_unlocked(tmp); + } + return static_cast< FinalT& >(*this); + } +}; + +//! An optimized composite logger version with no multithreading support +template< typename CharT, typename FinalT, typename FeaturesT > +class basic_composite_logger< CharT, FinalT, single_thread_model, FeaturesT > : + public boost::log::sources::aux::inherit_features< + basic_logger< CharT, FinalT, single_thread_model >, + FeaturesT + >::type +{ +private: + typedef typename boost::log::sources::aux::inherit_features< + basic_logger< CharT, FinalT, single_thread_model >, + FeaturesT + >::type base_type; + +protected: + typedef basic_composite_logger logger_base; + BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base) + +public: + typedef typename base_type::threading_model threading_model; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +public: + basic_composite_logger() {} + basic_composite_logger(basic_composite_logger const& that) : + base_type(static_cast< base_type const& >(that)) + { + } + basic_composite_logger(BOOST_RV_REF(logger_base) that) : + base_type(boost::move(static_cast< base_type& >(that))) + { + } + template< typename ArgsT > + explicit basic_composite_logger(ArgsT const& args) : base_type(args) + { + } + + std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr) + { + return base_type::add_attribute_unlocked(name, attr); + } + void remove_attribute(attribute_set::iterator it) + { + base_type::remove_attribute_unlocked(it); + } + void remove_all_attributes() + { + base_type::remove_all_attributes_unlocked(); + } + attribute_set get_attributes() const + { + return base_type::get_attributes_unlocked(); + } + void set_attributes(attribute_set const& attrs) + { + base_type::set_attributes_unlocked(attrs); + } + record open_record() + { + // Perform a quick check first + if (this->core()->get_logging_enabled()) + return base_type::open_record_unlocked(boost::log::aux::empty_arg_list()); + else + return record(); + } + template< typename ArgsT > + record open_record(ArgsT const& args) + { + // Perform a quick check first + if (this->core()->get_logging_enabled()) + return base_type::open_record_unlocked(args); + else + return record(); + } + void push_record(BOOST_RV_REF(record) rec) + { + base_type::push_record_unlocked(boost::move(rec)); + } + void swap(basic_composite_logger& that) + { + base_type::swap_unlocked(that); + } + +protected: + FinalT& assign(FinalT that) + { + base_type::swap_unlocked(that); + return static_cast< FinalT& >(*this); + } +}; + + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, typename_keyword)\ + public:\ + BOOST_DEFAULTED_FUNCTION(class_type(), {})\ + class_type(class_type const& that) : class_type::logger_base(\ + static_cast< typename_keyword() class_type::logger_base const& >(that)) {}\ + class_type(BOOST_RV_REF(class_type) that) : class_type::logger_base(\ + ::boost::move(static_cast< typename_keyword() class_type::logger_base& >(that))) {}\ + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, class_type::logger_base)\ + +#endif // BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\ + BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_EMPTY) + +#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\ + BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_IDENTITY(typename)) + +#define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)\ + public:\ + class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\ + {\ + return class_type::logger_base::assign(static_cast< class_type const& >(that));\ + }\ + class_type& operator= (BOOST_RV_REF(class_type) that)\ + {\ + BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< class_type::threading_model > lock(this->get_threading_model());)\ + this->swap_unlocked(that);\ + return *this;\ + } + +#define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)\ + public:\ + class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\ + {\ + return class_type::logger_base::assign(static_cast< class_type const& >(that));\ + }\ + class_type& operator= (BOOST_RV_REF(class_type) that)\ + {\ + BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< typename class_type::threading_model > lock(this->get_threading_model());)\ + this->swap_unlocked(that);\ + return *this;\ + } + +#define BOOST_LOG_FORWARD_LOGGER_MEMBERS(class_type)\ + BOOST_COPYABLE_AND_MOVABLE(class_type)\ + BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\ + BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type) + +#define BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(class_type)\ + BOOST_COPYABLE_AND_MOVABLE(class_type)\ + BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\ + BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type) + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +/*! + * \brief The macro declares a logger class that inherits a number of base classes + * + * \param type_name The name of the logger class to declare + * \param char_type The character type of the logger. Either char or wchar_t expected. + * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates + * \param threading A threading model class + */ +#define BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char_type, base_seq, threading)\ + class type_name :\ + public ::boost::log::sources::basic_composite_logger<\ + char_type,\ + type_name,\ + threading,\ + ::boost::log::sources::features< BOOST_PP_SEQ_ENUM(base_seq) >\ + >\ + {\ + BOOST_LOG_FORWARD_LOGGER_MEMBERS(type_name)\ + } + + + +#ifdef BOOST_LOG_USE_CHAR + +/*! + * \brief The macro declares a narrow-char logger class that inherits a number of base classes + * + * Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, single_thread_model) + * + * \param type_name The name of the logger class to declare + * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates + */ +#define BOOST_LOG_DECLARE_LOGGER(type_name, base_seq)\ + BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, ::boost::log::sources::single_thread_model) + +#if !defined(BOOST_LOG_NO_THREADS) + +/*! + * \brief The macro declares a narrow-char thread-safe logger class that inherits a number of base classes + * + * Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, multi_thread_model< shared_mutex >)</tt> + * + * \param type_name The name of the logger class to declare + * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates + */ +#define BOOST_LOG_DECLARE_LOGGER_MT(type_name, base_seq)\ + BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq,\ + ::boost::log::sources::multi_thread_model< ::boost::shared_mutex >) + +#endif // !defined(BOOST_LOG_NO_THREADS) +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T + +/*! + * \brief The macro declares a wide-char logger class that inherits a number of base classes + * + * Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, single_thread_model) + * + * \param type_name The name of the logger class to declare + * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates + */ +#define BOOST_LOG_DECLARE_WLOGGER(type_name, base_seq)\ + BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, ::boost::log::sources::single_thread_model) + +#if !defined(BOOST_LOG_NO_THREADS) + +/*! + * \brief The macro declares a wide-char thread-safe logger class that inherits a number of base classes + * + * Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, multi_thread_model< shared_mutex >)</tt> + * + * \param type_name The name of the logger class to declare + * \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates + */ +#define BOOST_LOG_DECLARE_WLOGGER_MT(type_name, base_seq)\ + BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq,\ + ::boost::log::sources::multi_thread_model< ::boost::shared_mutex >) + +#endif // !defined(BOOST_LOG_NO_THREADS) +#endif // BOOST_LOG_USE_WCHAR_T + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_ diff --git a/boost/log/sources/channel_feature.hpp b/boost/log/sources/channel_feature.hpp new file mode 100644 index 0000000000..c93ee6fa2d --- /dev/null +++ b/boost/log/sources/channel_feature.hpp @@ -0,0 +1,242 @@ +/* + * 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 channel_feature.hpp + * \author Andrey Semashev + * \date 28.02.2008 + * + * The header contains implementation of a channel support feature. + */ + +#ifndef BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_ + +#include <string> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/locks.hpp> +#include <boost/log/detail/default_attribute_names.hpp> +#include <boost/log/keywords/channel.hpp> +#include <boost/log/attributes/mutable_constant.hpp> +#include <boost/log/utility/strictest_lock.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +/*! + * \brief Channel feature implementation + */ +template< typename BaseT, typename ChannelT > +class basic_channel_logger : + public BaseT +{ + //! Base type + typedef BaseT base_type; + typedef basic_channel_logger this_type; + BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! Final type + typedef typename base_type::final_type final_type; + //! Threading model being used + typedef typename base_type::threading_model threading_model; + + //! Channel type + typedef ChannelT channel_type; + //! Channel attribute type + typedef attributes::mutable_constant< channel_type > channel_attribute; + + //! Lock requirement for the \c open_record_unlocked method + typedef typename strictest_lock< + typename base_type::open_record_lock, +#ifndef BOOST_LOG_NO_THREADS + boost::log::aux::exclusive_lock_guard< threading_model > +#else + no_lock< threading_model > +#endif // !defined(BOOST_LOG_NO_THREADS) + >::type open_record_lock; + + //! Lock requirement for the \c swap_unlocked method + typedef typename strictest_lock< + typename base_type::swap_lock, +#ifndef BOOST_LOG_NO_THREADS + boost::log::aux::exclusive_lock_guard< threading_model > +#else + no_lock< threading_model > +#endif // !defined(BOOST_LOG_NO_THREADS) + >::type swap_lock; + +private: + //! Default channel name generator + struct make_default_channel_name + { + typedef channel_type result_type; + result_type operator() () const { return result_type(); } + }; + +private: + //! Channel attribute + channel_attribute m_ChannelAttr; + +public: + /*! + * Default constructor. The constructed logger has the default-constructed channel name. + */ + basic_channel_logger() : base_type(), m_ChannelAttr(channel_type()) + { + base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr); + } + /*! + * Copy constructor + */ + basic_channel_logger(basic_channel_logger const& that) : + base_type(static_cast< base_type const& >(that)), + m_ChannelAttr(that.m_ChannelAttr) + { + base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr; + } + /*! + * Move constructor + */ + basic_channel_logger(BOOST_RV_REF(basic_channel_logger) that) : + base_type(boost::move(static_cast< base_type& >(that))), + m_ChannelAttr(boost::move(that.m_ChannelAttr)) + { + base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr; + } + /*! + * Constructor with arguments. Allows to register a channel name attribute on construction. + * + * \param args A set of named arguments. The following arguments are supported: + * \li \c channel - a string that represents the channel name + */ + template< typename ArgsT > + explicit basic_channel_logger(ArgsT const& args) : + base_type(args), + m_ChannelAttr(args[keywords::channel || make_default_channel_name()]) + { + base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr); + } + + /*! + * The observer of the channel name + * + * \return The channel name that was set by the logger + */ + channel_type channel() const + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< const threading_model > lock(this->get_threading_model());) + return m_ChannelAttr.get(); + } + + /*! + * The setter of the channel name + * + * \param ch The channel name to be set for the logger + */ + void channel(channel_type const& ch) + { + BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());) + m_ChannelAttr.set(ch); + } + +protected: + /*! + * Channel attribute accessor + */ + channel_attribute const& get_channel_attribute() const { return m_ChannelAttr; } + + /*! + * Unlocked \c open_record + */ + template< typename ArgsT > + record open_record_unlocked(ArgsT const& args) + { + return open_record_with_channel_unlocked(args, args[keywords::channel | parameter::void_()]); + } + + /*! + * Unlocked swap + */ + void swap_unlocked(basic_channel_logger& that) + { + base_type::swap_unlocked(static_cast< base_type& >(that)); + m_ChannelAttr.swap(that.m_ChannelAttr); + } + +private: + //! The \c open_record implementation for the case when the channel is specified in log statement + template< typename ArgsT, typename T > + record open_record_with_channel_unlocked(ArgsT const& args, T const& ch) + { + m_ChannelAttr.set(ch); + return base_type::open_record_unlocked(args); + } + //! The \c open_record implementation for the case when the channel is not specified in log statement + template< typename ArgsT > + record open_record_with_channel_unlocked(ArgsT const& args, parameter::void_) + { + return base_type::open_record_unlocked(args); + } +}; + +/*! + * \brief Channel support feature + * + * The logger with this feature automatically registers an attribute with the specified + * on construction value, which is a channel name. The channel name can be modified + * through the logger life time, either by calling the \c channel method or by specifying + * the name in the logging statement. + * + * The type of the channel name can be customized by providing it as a template parameter + * to the feature template. By default, a string will be used. + */ +template< typename ChannelT = std::string > +struct channel +{ + template< typename BaseT > + struct apply + { + typedef basic_channel_logger< + BaseT, + ChannelT + > type; + }; +}; + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +//! The macro allows to put a record with a specific channel name into log +#define BOOST_LOG_STREAM_CHANNEL(logger, chan)\ + BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan))) + +#ifndef BOOST_LOG_NO_SHORTHAND_NAMES + +//! An equivalent to BOOST_LOG_STREAM_CHANNEL(logger, chan) +#define BOOST_LOG_CHANNEL(logger, chan) BOOST_LOG_STREAM_CHANNEL(logger, chan) + +#endif // BOOST_LOG_NO_SHORTHAND_NAMES + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_ diff --git a/boost/log/sources/channel_logger.hpp b/boost/log/sources/channel_logger.hpp new file mode 100644 index 0000000000..737faa1f17 --- /dev/null +++ b/boost/log/sources/channel_logger.hpp @@ -0,0 +1,325 @@ +/* + * 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 channel_logger.hpp + * \author Andrey Semashev + * \date 28.02.2008 + * + * The header contains implementation of a logger with channel support. + */ + +#ifndef BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/detail/light_rw_mutex.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/sources/features.hpp> +#include <boost/log/sources/basic_logger.hpp> +#include <boost/log/sources/threading_models.hpp> +#include <boost/log/sources/channel_feature.hpp> +#include <boost/log/keywords/channel.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#ifdef BOOST_LOG_USE_CHAR + +//! Narrow-char logger with channel support +template< typename ChannelT = std::string > +class channel_logger : + public basic_composite_logger< + char, + channel_logger< ChannelT >, + single_thread_model, + features< channel< ChannelT > > + > +{ + typedef typename channel_logger::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(channel_logger) + + explicit channel_logger(ChannelT const& channel) : base_type(keywords::channel = channel) + { + } +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Narrow-char thread-safe logger with channel support +template< typename ChannelT = std::string > +class channel_logger_mt : + public basic_composite_logger< + char, + channel_logger_mt< ChannelT >, + multi_thread_model< boost::log::aux::light_rw_mutex >, + features< channel< ChannelT > > + > +{ + typedef typename channel_logger_mt::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(channel_logger_mt) + + explicit channel_logger_mt(ChannelT const& channel) : base_type(keywords::channel = channel) + { + } +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T + +//! Wide-char logger with channel support +template< typename ChannelT = std::wstring > +class wchannel_logger : + public basic_composite_logger< + wchar_t, + wchannel_logger< ChannelT >, + single_thread_model, + features< channel< ChannelT > > + > +{ + typedef typename wchannel_logger::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wchannel_logger) + + explicit wchannel_logger(ChannelT const& channel) : base_type(keywords::channel = channel) + { + } +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Wide-char thread-safe logger with channel support +template< typename ChannelT = std::wstring > +class wchannel_logger_mt : + public basic_composite_logger< + wchar_t, + wchannel_logger< ChannelT >, + multi_thread_model< boost::log::aux::light_rw_mutex >, + features< channel< ChannelT > > + > +{ + typedef typename wchannel_logger_mt::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wchannel_logger_mt) + + explicit wchannel_logger_mt(ChannelT const& channel) : base_type(keywords::channel = channel) + { + } +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif // BOOST_LOG_USE_WCHAR_T + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Narrow-char logger. Functionally equivalent to \c basic_channel_logger. + * + * See \c channel class template for a more detailed description + */ +template< typename ChannelT = std::string > +class channel_logger : + public basic_composite_logger< + char, + channel_logger< ChannelT >, + single_thread_model, + features< channel< ChannelT > > + > +{ +public: + /*! + * Default constructor + */ + channel_logger(); + /*! + * Copy constructor + */ + channel_logger(channel_logger const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit channel_logger(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified channel name + * + * \param channel The channel name + */ + explicit channel_logger(ChannelT const& channel); + /*! + * Assignment operator + */ + channel_logger& operator= (channel_logger const& that) + /*! + * Swaps two loggers + */ + void swap(channel_logger& that); +}; + +/*! + * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_channel_logger. + * + * See \c channel class template for a more detailed description + */ +template< typename ChannelT = std::string > +class channel_logger_mt : + public basic_composite_logger< + char, + channel_logger_mt< ChannelT >, + multi_thread_model< implementation_defined >, + features< channel< ChannelT > > + > +{ +public: + /*! + * Default constructor + */ + channel_logger_mt(); + /*! + * Copy constructor + */ + channel_logger_mt(channel_logger_mt const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit channel_logger_mt(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified channel name + * + * \param channel The channel name + */ + explicit channel_logger_mt(ChannelT const& channel); + /*! + * Assignment operator + */ + channel_logger_mt& operator= (channel_logger_mt const& that) + /*! + * Swaps two loggers + */ + void swap(channel_logger_mt& that); +}; + +/*! + * \brief Wide-char logger. Functionally equivalent to \c basic_channel_logger. + * + * See \c channel class template for a more detailed description + */ +template< typename ChannelT = std::wstring > +class wchannel_logger : + public basic_composite_logger< + wchar_t, + wchannel_logger< ChannelT >, + single_thread_model, + features< channel< ChannelT > > + > +{ +public: + /*! + * Default constructor + */ + wchannel_logger(); + /*! + * Copy constructor + */ + wchannel_logger(wchannel_logger const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit wchannel_logger(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified channel name + * + * \param channel The channel name + */ + explicit wchannel_logger(ChannelT const& channel); + /*! + * Assignment operator + */ + wchannel_logger& operator= (wchannel_logger const& that) + /*! + * Swaps two loggers + */ + void swap(wchannel_logger& that); +}; + +/*! + * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_channel_logger. + * + * See \c channel class template for a more detailed description + */ +template< typename ChannelT = std::wstring > +class wchannel_logger_mt : + public basic_composite_logger< + wchar_t, + wchannel_logger< ChannelT >, + multi_thread_model< implementation_defined >, + features< channel< ChannelT > > + > +{ +public: + /*! + * Default constructor + */ + wchannel_logger_mt(); + /*! + * Copy constructor + */ + wchannel_logger_mt(wchannel_logger_mt const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit wchannel_logger_mt(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified channel name + * + * \param channel The channel name + */ + explicit wchannel_logger_mt(ChannelT const& channel); + /*! + * Assignment operator + */ + wchannel_logger_mt& operator= (wchannel_logger_mt const& that) + /*! + * Swaps two loggers + */ + void swap(wchannel_logger_mt& that); +}; + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_ diff --git a/boost/log/sources/exception_handler_feature.hpp b/boost/log/sources/exception_handler_feature.hpp new file mode 100644 index 0000000000..d665d0d84b --- /dev/null +++ b/boost/log/sources/exception_handler_feature.hpp @@ -0,0 +1,253 @@ +/* + * 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 exception_handler_feature.hpp + * \author Andrey Semashev + * \date 17.07.2009 + * + * The header contains implementation of an exception handler support feature. + */ + +#ifndef BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_ + +#include <boost/mpl/if.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/locks.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/sources/threading_models.hpp> +#include <boost/log/utility/strictest_lock.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/thread/exceptions.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +/*! + * \brief Exception handler feature implementation + */ +template< typename BaseT > +class basic_exception_handler_logger : + public BaseT +{ + //! Base type + typedef BaseT base_type; + typedef basic_exception_handler_logger this_type; + BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) + +public: + //! Threading model being used + typedef typename base_type::threading_model threading_model; + //! Final logger type + typedef typename base_type::final_type final_type; + //! Exception handler function type + typedef boost::log::aux::light_function< void () > exception_handler_type; + +#if defined(BOOST_LOG_DOXYGEN_PASS) + //! Lock requirement for the open_record_unlocked method + typedef typename strictest_lock< + typename base_type::open_record_lock, + no_lock< threading_model > + >::type open_record_lock; + //! Lock requirement for the push_record_unlocked method + typedef typename strictest_lock< + typename base_type::push_record_lock, + no_lock< threading_model > + >::type push_record_lock; +#endif // defined(BOOST_LOG_DOXYGEN_PASS) + + //! Lock requirement for the swap_unlocked method + typedef typename strictest_lock< + typename base_type::swap_lock, +#ifndef BOOST_LOG_NO_THREADS + boost::log::aux::exclusive_lock_guard< threading_model > +#else + no_lock< threading_model > +#endif // !defined(BOOST_LOG_NO_THREADS) + >::type swap_lock; + +private: + //! Exception handler + exception_handler_type m_ExceptionHandler; + +public: + /*! + * Default constructor. The constructed logger does not have an exception handler. + */ + basic_exception_handler_logger() : base_type() + { + } + /*! + * Copy constructor + */ + basic_exception_handler_logger(basic_exception_handler_logger const& that) : + base_type(static_cast< base_type const& >(that)), + m_ExceptionHandler(that.m_ExceptionHandler) + { + } + /*! + * Move constructor + */ + basic_exception_handler_logger(BOOST_RV_REF(basic_exception_handler_logger) that) : + base_type(boost::move(static_cast< base_type& >(that))), + m_ExceptionHandler(boost::move(that.m_ExceptionHandler)) + { + } + /*! + * Constructor with arguments. Passes arguments to other features. + */ + template< typename ArgsT > + explicit basic_exception_handler_logger(ArgsT const& args) : + base_type(args) + { + } + + /*! + * The method sets exception handler function. The function will be called with no arguments + * in case if an exception occurs during either \c open_record or \c push_record method + * execution. Since exception handler is called from a \c catch statement, the exception + * can be rethrown in order to determine its type. + * + * By default no handler is installed, thus any exception is propagated as usual. + * + * \sa <tt>utility/exception_handler.hpp</tt> + * \param handler Exception handling function + * + * \note The exception handler can be invoked in several threads concurrently. + * + * \note Thread interruptions are not affected by exception handlers. + */ + template< typename HandlerT > + void set_exception_handler(HandlerT const& handler) + { +#ifndef BOOST_LOG_NO_THREADS + boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model()); +#endif + m_ExceptionHandler = handler; + } + +protected: + /*! + * Unlocked \c open_record + */ + template< typename ArgsT > + record open_record_unlocked(ArgsT const& args) + { + try + { + return base_type::open_record_unlocked(args); + } +#ifndef BOOST_LOG_NO_THREADS + catch (thread_interrupted&) + { + throw; + } +#endif + catch (...) + { + handle_exception(); + return record(); + } + } + + /*! + * Unlocked \c push_record + */ + void push_record_unlocked(BOOST_RV_REF(record) rec) + { + try + { + base_type::push_record_unlocked(boost::move(rec)); + } +#ifndef BOOST_LOG_NO_THREADS + catch (thread_interrupted&) + { + throw; + } +#endif + catch (...) + { + handle_exception(); + } + } + + /*! + * Unlocked swap + */ + void swap_unlocked(basic_exception_handler_logger& that) + { + base_type::swap_unlocked(static_cast< base_type& >(that)); + m_ExceptionHandler.swap(that.m_ExceptionHandler); + } + +private: +#if !defined(BOOST_LOG_DOXYGEN_PASS) + //! The function handles the intercepted exception + void handle_exception() + { +#ifndef BOOST_LOG_NO_THREADS + // Here's the trick with the lock type. Since the lock + // is only needed when an exception is caught, we indicate + // no locking requirements in the push_record_lock type. + // However, if other features don't require locking either, + // we shall acquire a read lock here, when an exception is caught. + // If other features do require locking, the thread model is + // already locked by now, and we don't do locking at all. + typedef typename mpl::if_< + is_same< no_lock< threading_model >, typename final_type::push_record_lock >, + boost::log::aux::shared_lock_guard< threading_model >, + no_lock< threading_model > + >::type lock_type; + lock_type lock(base_type::get_threading_model()); +#endif // !defined(BOOST_LOG_NO_THREADS) + + if (m_ExceptionHandler.empty()) + throw; + m_ExceptionHandler(); + } +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) +}; + +/*! + * \brief Exception handler support feature + * + * The logger with this feature will provide an additional method to + * install an exception handler functional object. This functional + * object will be called if during either opening or pushing a record + * an exception is thrown from the logging core. + */ +struct exception_handler +{ + template< typename BaseT > + struct apply + { + typedef basic_exception_handler_logger< BaseT > type; + }; +}; + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_ diff --git a/boost/log/sources/features.hpp b/boost/log/sources/features.hpp new file mode 100644 index 0000000000..295cc0bb4f --- /dev/null +++ b/boost/log/sources/features.hpp @@ -0,0 +1,150 @@ +/* + * 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 sources/features.hpp + * \author Andrey Semashev + * \date 17.07.2009 + * + * The header contains definition of a features list class template. + */ + +#ifndef BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_ + +#include <boost/mpl/lambda.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_shifted_params.hpp> +#include <boost/preprocessor/facilities/intercept.hpp> + +//! The macro defines the maximum number of features that can be specified for a logger +#ifndef BOOST_LOG_FEATURES_LIMIT +#define BOOST_LOG_FEATURES_LIMIT 10 +#endif // BOOST_LOG_FEATURES_LIMIT + +#endif + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +#if defined(BOOST_LOG_DOXYGEN_PASS) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +/*! + * \brief A type sequence of logger features + * + * This class template can be used to specify logger features in a \c basic_composite_logger instantiation. + */ +template< typename... FeaturesT > +struct features +{ +}; + +namespace aux { + +//! The metafunction produces the inherited features hierarchy with \c RootT as the ultimate base type +template< typename RootT, typename FeaturesT > +struct inherit_features; + +template< typename RootT, typename FeatureT0, typename... FeaturesT > +struct inherit_features< RootT, features< FeatureT0, FeaturesT... > > +{ + typedef typename mpl::lambda< + FeatureT0 + >::type::BOOST_NESTED_TEMPLATE apply< + typename inherit_features< + RootT, + features< FeaturesT... > + >::type + >::type type; +}; + +template< typename RootT, typename FeatureT0 > +struct inherit_features< RootT, features< FeatureT0 > > +{ + typedef typename mpl::lambda< + FeatureT0 + >::type::BOOST_NESTED_TEMPLATE apply< + RootT + >::type type; +}; + +template< typename RootT > +struct inherit_features< RootT, features< > > +{ + typedef RootT type; +}; + +} // namespace aux + +#else + +//! A type sequence of logger features +template< BOOST_PP_ENUM_BINARY_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT, = void BOOST_PP_INTERCEPT) > +struct features +{ +}; + +namespace aux { + +template< typename RootT, typename FeaturesT > +struct inherit_features; + +template< typename RootT, BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT) > +struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) > > +{ + typedef typename mpl::lambda< + FeatureT0 + >::type::BOOST_NESTED_TEMPLATE apply< + typename inherit_features< + RootT, + features< BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) > + >::type + >::type type; +}; + +template< typename RootT, typename FeatureT0 > +struct inherit_features< RootT, features< FeatureT0, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > > +{ + typedef typename mpl::lambda< + FeatureT0 + >::type::BOOST_NESTED_TEMPLATE apply< + RootT + >::type type; +}; + +template< typename RootT > +struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > > +{ + typedef RootT type; +}; + +} // namespace aux + +#endif + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_ diff --git a/boost/log/sources/global_logger_storage.hpp b/boost/log/sources/global_logger_storage.hpp new file mode 100644 index 0000000000..65811edd2e --- /dev/null +++ b/boost/log/sources/global_logger_storage.hpp @@ -0,0 +1,206 @@ +/* + * 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 global_logger_storage.hpp + * \author Andrey Semashev + * \date 21.04.2008 + * + * The header contains implementation of facilities to declare global loggers. + */ + +#ifndef BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_ + +#include <typeinfo> +#include <stdexcept> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/preprocessor/seq/enum.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/singleton.hpp> +#include <boost/log/detail/visible_type.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +namespace aux { + +//! The base class for logger holders +struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE logger_holder_base +{ + //! The source file name where the logger was registered + const char* m_RegistrationFile; + //! The line number where the logger was registered + unsigned int m_RegistrationLine; + + logger_holder_base(const char* file, unsigned int line) : + m_RegistrationFile(file), + m_RegistrationLine(line) + { + } + virtual ~logger_holder_base() {} + virtual std::type_info const& logger_type() const = 0; +}; + +//! The actual logger holder class +template< typename LoggerT > +struct BOOST_SYMBOL_VISIBLE logger_holder : + public logger_holder_base +{ + //! The logger instance + LoggerT m_Logger; + + logger_holder(const char* file, unsigned int line, LoggerT const& logger) : + logger_holder_base(file, line), + m_Logger(logger) + { + } + std::type_info const& logger_type() const { return typeid(LoggerT); } +}; + +//! The class implements a global repository of tagged loggers +struct global_storage +{ + typedef shared_ptr< logger_holder_base >(*initializer_t)(); + + //! Finds or creates the logger and returns its holder + BOOST_LOG_API static shared_ptr< logger_holder_base > get_or_init(std::type_info const& key, initializer_t initializer); + + // Non-constructible, non-copyable, non-assignable + BOOST_DELETED_FUNCTION(global_storage()) + BOOST_DELETED_FUNCTION(global_storage(global_storage const&)) + BOOST_DELETED_FUNCTION(global_storage& operator= (global_storage const&)) +}; + +//! Throws the \c odr_violation exception +BOOST_LOG_API BOOST_LOG_NORETURN void throw_odr_violation( + std::type_info const& tag_type, + std::type_info const& logger_type, + logger_holder_base const& registered); + +//! The class implements a logger singleton +template< typename TagT > +struct logger_singleton : + public boost::log::aux::lazy_singleton< + logger_singleton< TagT >, + shared_ptr< logger_holder< typename TagT::logger_type > > + > +{ + //! Base type + typedef boost::log::aux::lazy_singleton< + logger_singleton< TagT >, + shared_ptr< logger_holder< typename TagT::logger_type > > + > base_type; + //! Logger type + typedef typename TagT::logger_type logger_type; + + //! Returns the logger instance + static logger_type& get() + { + return base_type::get()->m_Logger; + } + + //! Initializes the logger instance (called only once) + static void init_instance() + { + shared_ptr< logger_holder< logger_type > >& instance = base_type::get_instance(); + shared_ptr< logger_holder_base > holder = global_storage::get_or_init( + typeid(boost::log::aux::visible_type< TagT >), + &logger_singleton::construct_logger); + instance = boost::dynamic_pointer_cast< logger_holder< logger_type > >(holder); + if (!instance) + { + // In pure C++ this should never happen, since there cannot be two + // different tag types that have equal type_infos. In real life it can + // happen if the same-named tag is defined differently in two or more + // dlls. This check is intended to detect such ODR violations. However, there + // is no protection against different definitions of the logger type itself. + throw_odr_violation(typeid(TagT), typeid(logger_type), *holder); + } + } + +private: + //! Constructs a logger holder + static shared_ptr< logger_holder_base > construct_logger() + { + return boost::make_shared< logger_holder< logger_type > >( + TagT::registration_file(), + static_cast< unsigned int >(TagT::registration_line), + TagT::construct_logger()); + } +}; + +} // namespace aux + +//! The macro forward-declares a global logger with a custom initialization +#define BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\ + struct tag_name\ + {\ + typedef logger logger_type;\ + enum registration_line_t { registration_line = __LINE__ };\ + static const char* registration_file() { return __FILE__; }\ + static logger_type construct_logger();\ + static inline logger_type& get()\ + {\ + return ::boost::log::sources::aux::logger_singleton< tag_name >::get();\ + }\ + }; + +//! The macro defines a global logger initialization routine +#define BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\ + tag_name::logger_type tag_name::construct_logger() + +//! The macro defines a global logger initializer that will default-construct the logger +#define BOOST_LOG_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\ + BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\ + {\ + return logger_type();\ + } + +//! The macro defines a global logger initializer that will construct the logger with the specified constructor arguments +#define BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\ + BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\ + {\ + return logger_type(BOOST_PP_SEQ_ENUM(args));\ + } + +//! The macro declares a global logger with a custom initialization +#define BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\ + BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\ + inline BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger) + +//! The macro declares a global logger that will be default-constructed +#define BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\ + BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\ + {\ + return logger_type();\ + } + +//! The macro declares a global logger that will be constructed with the specified arguments +#define BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\ + BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\ + {\ + return logger_type(BOOST_PP_SEQ_ENUM(args));\ + } + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_ diff --git a/boost/log/sources/logger.hpp b/boost/log/sources/logger.hpp new file mode 100644 index 0000000000..4f5fbf1ff6 --- /dev/null +++ b/boost/log/sources/logger.hpp @@ -0,0 +1,103 @@ +/* + * 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 logger.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * The header contains implementation of a simplistic logger with no features. + */ + +#ifndef BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/sources/basic_logger.hpp> +#include <boost/log/sources/features.hpp> +#include <boost/log/sources/threading_models.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/detail/light_rw_mutex.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +#ifdef BOOST_LOG_USE_CHAR + +/*! + * \brief Narrow-char logger. Functionally equivalent to \c basic_logger. + * + * See \c basic_logger class template for a more detailed description. + */ +class logger : + public basic_composite_logger< char, logger, single_thread_model, features< > > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS(logger) +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +/*! + * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_logger. + * + * See \c basic_logger class template for a more detailed description. + */ +class logger_mt : + public basic_composite_logger< char, logger_mt, multi_thread_model< boost::log::aux::light_rw_mutex >, features< > > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS(logger_mt) +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T + +/*! + * \brief Wide-char logger. Functionally equivalent to \c basic_logger. + * + * See \c basic_logger class template for a more detailed description. + */ +class wlogger : + public basic_composite_logger< wchar_t, wlogger, single_thread_model, features< > > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS(wlogger) +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +/*! + * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_logger. + * + * See \c basic_logger class template for a more detailed description. + */ +class wlogger_mt : + public basic_composite_logger< wchar_t, wlogger_mt, multi_thread_model< boost::log::aux::light_rw_mutex >, features< > > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS(wlogger_mt) +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) +#endif // BOOST_LOG_USE_WCHAR_T + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_ diff --git a/boost/log/sources/record_ostream.hpp b/boost/log/sources/record_ostream.hpp new file mode 100644 index 0000000000..239f3c9f6a --- /dev/null +++ b/boost/log/sources/record_ostream.hpp @@ -0,0 +1,335 @@ +/* + * 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_ostream.hpp + * \author Andrey Semashev + * \date 09.03.2009 + * + * This header contains a wrapper class around a logging record that allows to compose the + * record message with a streaming expression. + */ + +#ifndef BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_ + +#include <string> +#include <ostream> +#include <boost/assert.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/native_typeof.hpp> +#include <boost/log/detail/unhandled_exception_count.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/utility/unique_identifier_name.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief Logging record adapter with a streaming capability + * + * This class allows to compose the logging record message by streaming operations. It + * aggregates the log record and provides the standard output stream interface. + */ +template< typename CharT > +class basic_record_ostream : + public basic_formatting_ostream< CharT > +{ + //! Self type + typedef basic_record_ostream< CharT > this_type; + //! Base stream class + typedef basic_formatting_ostream< CharT > base_type; + +public: + //! Character type + typedef CharT char_type; + //! String type to be used as a message text holder + typedef std::basic_string< char_type > string_type; + //! Stream type + typedef std::basic_ostream< char_type > stream_type; + +private: + //! Log record + record* m_record; + +public: + /*! + * Default constructor. Creates an empty record that is equivalent to the invalid record handle. + * The stream capability is not available after construction. + * + * \post <tt>!*this == true</tt> + */ + basic_record_ostream() BOOST_NOEXCEPT : m_record(NULL) {} + + /*! + * Constructor from a record object. Attaches to the provided record. + * + * \pre <tt>!!rec == true</tt> + * \post <tt>&this->get_record() == &rec</tt> + * \param rec The record handle being attached to + */ + explicit basic_record_ostream(record& rec) + { + BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record"); + m_record = &rec; + init_stream(); + } + + /*! + * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record. + */ + ~basic_record_ostream() BOOST_NOEXCEPT + { + detach_from_record(); + } + + /*! + * Conversion to an unspecified boolean type + * + * \return \c true, if stream is valid and ready for formatting, \c false, if the stream is not valid. The latter also applies to + * the case when the stream is not attached to a log record. + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * Inverted conversion to an unspecified boolean type + * + * \return \c false, if stream is valid and ready for formatting, \c true, if the stream is not valid. The latter also applies to + * the case when the stream is not attached to a log record. + */ + bool operator! () const BOOST_NOEXCEPT + { + return (!m_record || base_type::fail()); + } + + /*! + * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record + * + * \return The aggregated record object + */ + record& get_record() + { + BOOST_ASSERT(m_record != NULL); + this->flush(); + return *m_record; + } + + /*! + * Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record + * + * \return The aggregated record object + */ + record const& get_record() const + { + BOOST_ASSERT(m_record != NULL); + const_cast< this_type* >(this)->flush(); + return *m_record; + } + + /*! + * If the stream is attached to a log record, flushes internal buffers to complete all pending formatting operations. + * Then reattaches the stream to another log record. + * + * \param rec New log record to attach to + */ + void attach_record(record& rec) + { + BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record"); + detach_from_record(); + m_record = &rec; + init_stream(); + } + + //! The function resets the stream into a detached (default initialized) state + BOOST_LOG_API void detach_from_record() BOOST_NOEXCEPT; + +private: + //! The function initializes the stream and the stream buffer + BOOST_LOG_API void init_stream(); + + // Copy and assignment are closed + BOOST_DELETED_FUNCTION(basic_record_ostream(basic_record_ostream const&)) + BOOST_DELETED_FUNCTION(basic_record_ostream& operator= (basic_record_ostream const&)) +}; + + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_record_ostream< char > record_ostream; //!< Convenience typedef for narrow-character logging +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_record_ostream< wchar_t > wrecord_ostream; //!< Convenience typedef for wide-character logging +#endif + +namespace aux { + +//! Internal class that provides formatting streams for record pumps +template< typename CharT > +struct stream_provider +{ + //! Character type + typedef CharT char_type; + + //! Formatting stream compound + struct stream_compound + { + stream_compound* next; + + //! Log record stream adapter + basic_record_ostream< char_type > stream; + + //! Initializing constructor + explicit stream_compound(record& rec) : next(NULL), stream(rec) {} + }; + + //! The method returns an allocated stream compound + BOOST_LOG_API static stream_compound* allocate_compound(record& rec); + //! The method releases a compound + BOOST_LOG_API static void release_compound(stream_compound* compound) BOOST_NOEXCEPT; + + // Non-constructible, non-copyable, non-assignable + BOOST_DELETED_FUNCTION(stream_provider()) + BOOST_DELETED_FUNCTION(stream_provider(stream_provider const&)) + BOOST_DELETED_FUNCTION(stream_provider& operator= (stream_provider const&)) +}; + + +/*! + * \brief Logging record pump implementation + * + * The pump is used to format the logging record message text and then + * push it to the logging core. It is constructed on each attempt to write + * a log record and destroyed afterwards. + * + * The pump class template is instantiated on the logger type. + */ +template< typename LoggerT > +class record_pump +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(record_pump) + +private: + //! Logger type + typedef LoggerT logger_type; + //! Character type + typedef typename logger_type::char_type char_type; + //! Stream compound provider + typedef stream_provider< char_type > stream_provider_type; + //! Stream compound type + typedef typename stream_provider_type::stream_compound stream_compound; + + //! Stream compound release guard + class auto_release; + friend class auto_release; + class auto_release + { + stream_compound* m_pCompound; + + public: + explicit auto_release(stream_compound* p) BOOST_NOEXCEPT : m_pCompound(p) {} + ~auto_release() BOOST_NOEXCEPT { stream_provider_type::release_compound(m_pCompound); } + }; + +protected: + //! A reference to the logger + logger_type* m_pLogger; + //! Stream compound + stream_compound* m_pStreamCompound; + //! Exception state + const unsigned int m_ExceptionCount; + +public: + //! Constructor + explicit record_pump(logger_type& lg, record& rec) : + m_pLogger(boost::addressof(lg)), + m_pStreamCompound(stream_provider_type::allocate_compound(rec)), + m_ExceptionCount(unhandled_exception_count()) + { + } + //! Move constructor + record_pump(BOOST_RV_REF(record_pump) that) BOOST_NOEXCEPT : + m_pLogger(that.m_pLogger), + m_pStreamCompound(that.m_pStreamCompound), + m_ExceptionCount(that.m_ExceptionCount) + { + that.m_pLogger = 0; + that.m_pStreamCompound = 0; + } + //! Destructor. Pushes the composed message to log. + ~record_pump() BOOST_NOEXCEPT_IF(false) + { + if (m_pLogger) + { + auto_release cleanup(m_pStreamCompound); // destructor doesn't throw + // Only push the record if no exception has been thrown in the streaming expression (if possible) + if (m_ExceptionCount >= unhandled_exception_count()) + m_pLogger->push_record(boost::move(m_pStreamCompound->stream.get_record())); + } + } + + //! Returns the stream to be used for message text formatting + basic_record_ostream< char_type >& stream() const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_pStreamCompound != 0); + return m_pStreamCompound->stream; + } +}; + +template< typename LoggerT > +BOOST_FORCEINLINE record_pump< LoggerT > make_record_pump(LoggerT& lg, record& rec) +{ + return record_pump< LoggerT >(lg, rec); +} + +} // namespace aux + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\ + for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\ + ::boost::log::aux::make_record_pump((logger), rec_var).stream() + +#define BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, rec_var, params_seq)\ + for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\ + ::boost::log::aux::make_record_pump((logger), rec_var).stream() + +#endif // BOOST_LOG_DOXYGEN_PASS + +//! The macro writes a record to the log +#define BOOST_LOG_STREAM(logger)\ + BOOST_LOG_STREAM_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_)) + +//! The macro writes a record to the log and allows to pass additional named arguments to the logger +#define BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)\ + BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_), params_seq) + +#ifndef BOOST_LOG_NO_SHORTHAND_NAMES + +//! An equivalent to BOOST_LOG_STREAM(logger) +#define BOOST_LOG(logger) BOOST_LOG_STREAM(logger) + +//! An equivalent to BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq) +#define BOOST_LOG_WITH_PARAMS(logger, params_seq) BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq) + +#endif // BOOST_LOG_NO_SHORTHAND_NAMES + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_ diff --git a/boost/log/sources/severity_channel_logger.hpp b/boost/log/sources/severity_channel_logger.hpp new file mode 100644 index 0000000000..aa567e82f6 --- /dev/null +++ b/boost/log/sources/severity_channel_logger.hpp @@ -0,0 +1,309 @@ +/* + * 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 severity_channel_logger.hpp + * \author Andrey Semashev + * \date 28.02.2008 + * + * The header contains implementation of a logger with severity level and channel support. + */ + +#ifndef BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_ + +#include <string> +#include <boost/log/detail/config.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/detail/light_rw_mutex.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/sources/features.hpp> +#include <boost/log/sources/basic_logger.hpp> +#include <boost/log/sources/threading_models.hpp> +#include <boost/log/sources/severity_feature.hpp> +#include <boost/log/sources/channel_feature.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#ifdef BOOST_LOG_USE_CHAR + +//! Narrow-char logger with severity level and channel support +template< typename LevelT = int, typename ChannelT = std::string > +class severity_channel_logger : + public basic_composite_logger< + char, + severity_channel_logger< LevelT, ChannelT >, + single_thread_model, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_channel_logger) +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Narrow-char thread-safe logger with severity level and channel support +template< typename LevelT = int, typename ChannelT = std::string > +class severity_channel_logger_mt : + public basic_composite_logger< + char, + severity_channel_logger_mt< LevelT, ChannelT >, + multi_thread_model< boost::log::aux::light_rw_mutex >, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_channel_logger_mt) +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T + +//! Wide-char logger with severity level and channel support +template< typename LevelT = int, typename ChannelT = std::wstring > +class wseverity_channel_logger : + public basic_composite_logger< + wchar_t, + wseverity_channel_logger< LevelT, ChannelT >, + single_thread_model, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_channel_logger) +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Wide-char thread-safe logger with severity level and channel support +template< typename LevelT = int, typename ChannelT = std::wstring > +class wseverity_channel_logger_mt : + public basic_composite_logger< + wchar_t, + wseverity_channel_logger_mt< LevelT, ChannelT >, + multi_thread_model< boost::log::aux::light_rw_mutex >, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_channel_logger_mt) +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif // BOOST_LOG_USE_WCHAR_T + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Narrow-char logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger. + * + * See \c severity and \c channel class templates for a more detailed description + */ +template< typename LevelT = int, typename ChannelT = std::string > +class severity_channel_logger : + public basic_composite_logger< + char, + severity_channel_logger< LevelT, ChannelT >, + single_thread_model, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ +public: + /*! + * Default constructor + */ + severity_channel_logger(); + /*! + * Copy constructor + */ + severity_channel_logger(severity_channel_logger const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit severity_channel_logger(ArgsT... const& args); + /*! + * Assignment operator + */ + severity_channel_logger& operator= (severity_channel_logger const& that) + /*! + * Swaps two loggers + */ + void swap(severity_channel_logger& that); +}; + +/*! + * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger. + * + * See \c severity and \c channel class templates for a more detailed description + */ +template< typename LevelT = int, typename ChannelT = std::string > +class severity_channel_logger_mt : + public basic_composite_logger< + char, + severity_channel_logger_mt< LevelT, ChannelT >, + multi_thread_model< implementation_defined >, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ +public: + /*! + * Default constructor + */ + severity_channel_logger_mt(); + /*! + * Copy constructor + */ + severity_channel_logger_mt(severity_channel_logger_mt const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit severity_channel_logger_mt(ArgsT... const& args); + /*! + * Assignment operator + */ + severity_channel_logger_mt& operator= (severity_channel_logger_mt const& that) + /*! + * Swaps two loggers + */ + void swap(severity_channel_logger_mt& that); +}; + +/*! + * \brief Wide-char logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger. + * + * See \c severity and \c channel class templates for a more detailed description + */ +template< typename LevelT = int, typename ChannelT = std::wstring > +class wseverity_channel_logger : + public basic_composite_logger< + wchar_t, + wseverity_channel_logger< LevelT, ChannelT >, + single_thread_model, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ +public: + /*! + * Default constructor + */ + wseverity_channel_logger(); + /*! + * Copy constructor + */ + wseverity_channel_logger(wseverity_channel_logger const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit wseverity_channel_logger(ArgsT... const& args); + /*! + * Assignment operator + */ + wseverity_channel_logger& operator= (wseverity_channel_logger const& that) + /*! + * Swaps two loggers + */ + void swap(wseverity_channel_logger& that); +}; + +/*! + * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger. + * + * See \c severity and \c channel class templates for a more detailed description + */ +template< typename LevelT = int, typename ChannelT = std::wstring > +class wseverity_channel_logger_mt : + public basic_composite_logger< + wchar_t, + wseverity_channel_logger_mt< LevelT, ChannelT >, + multi_thread_model< implementation_defined >, + features< + severity< LevelT >, + channel< ChannelT > + > + > +{ +public: + /*! + * Default constructor + */ + wseverity_channel_logger_mt(); + /*! + * Copy constructor + */ + wseverity_channel_logger_mt(wseverity_channel_logger_mt const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit wseverity_channel_logger_mt(ArgsT... const& args); + /*! + * Assignment operator + */ + wseverity_channel_logger_mt& operator= (wseverity_channel_logger_mt const& that) + /*! + * Swaps two loggers + */ + void swap(wseverity_channel_logger_mt& that); +}; + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +//! The macro allows to put a record with a specific channel name into log +#define BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)\ + BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan))(::boost::log::keywords::severity = (lvl))) + +#ifndef BOOST_LOG_NO_SHORTHAND_NAMES + +//! An equivalent to BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl) +#define BOOST_LOG_CHANNEL_SEV(logger, chan, lvl) BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl) + +#endif // BOOST_LOG_NO_SHORTHAND_NAMES + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_ diff --git a/boost/log/sources/severity_feature.hpp b/boost/log/sources/severity_feature.hpp new file mode 100644 index 0000000000..ae34c4c587 --- /dev/null +++ b/boost/log/sources/severity_feature.hpp @@ -0,0 +1,310 @@ +/* + * 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 severity_feature.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * The header contains implementation of a severity level support feature. + */ + +#ifndef BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_ + +#include <boost/cstdint.hpp> +#include <boost/static_assert.hpp> +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/locks.hpp> +#include <boost/log/detail/default_attribute_names.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_cast.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/utility/strictest_lock.hpp> +#include <boost/log/utility/type_dispatch/type_dispatcher.hpp> +#include <boost/log/keywords/severity.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +namespace aux { + + //! The method returns the storage for severity level for the current thread + BOOST_LOG_API uintmax_t& get_severity_level(); + + //! Severity level attribute implementation + template< typename LevelT > + class severity_level : + public attribute + { + typedef severity_level this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + + public: + //! Stored level type + typedef LevelT value_type; + BOOST_STATIC_ASSERT_MSG(sizeof(value_type) <= sizeof(uintmax_t), "Boost.Log: Unsupported severity level type, the severity level must fit into uintmax_t"); + + protected: + //! Factory implementation + class BOOST_SYMBOL_VISIBLE impl : + public attribute_value::impl + { + public: + //! The method dispatches the value to the given object + bool dispatch(type_dispatcher& dispatcher) + { + type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >(); + if (callback) + { + callback(reinterpret_cast< value_type const& >(get_severity_level())); + return true; + } + else + return false; + } + + //! The method is called when the attribute value is passed to another thread + intrusive_ptr< attribute_value::impl > detach_from_thread() + { + #if !defined(BOOST_LOG_NO_THREADS) + return new attributes::attribute_value_impl< value_type >( + reinterpret_cast< value_type const& >(get_severity_level())); + #else + // With multithreading disabled we may safely return this here. This method will not be called anyway. + return this; + #endif + } + }; + + public: + //! Default constructor + severity_level() : attribute(new impl()) + { + } + //! Copy constructor + severity_level(severity_level const& that) : attribute(static_cast< attribute const& >(that)) + { + } + //! Move constructor + severity_level(BOOST_RV_REF(severity_level) that) : attribute(boost::move(static_cast< attribute& >(that))) + { + } + //! Constructor for casting support + explicit severity_level(attributes::cast_source const& source) : + attribute(source.as< impl >()) + { + } + + /*! + * Copy assignment + */ + severity_level& operator= (BOOST_COPY_ASSIGN_REF(severity_level) that) + { + attribute::operator= (that); + return *this; + } + + /*! + * Move assignment + */ + severity_level& operator= (BOOST_RV_REF(severity_level) that) + { + this->swap(that); + return *this; + } + + //! The method sets the actual level + void set_value(value_type level) + { + reinterpret_cast< value_type& >(get_severity_level()) = level; + } + }; + +} // namespace aux + +/*! + * \brief Severity level feature implementation + */ +template< typename BaseT, typename LevelT = int > +class basic_severity_logger : + public BaseT +{ + //! Base type + typedef BaseT base_type; + typedef basic_severity_logger this_type; + BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! Final type + typedef typename base_type::final_type final_type; + //! Threading model being used + typedef typename base_type::threading_model threading_model; + + //! Severity level type + typedef LevelT severity_level; + //! Severity attribute type + typedef aux::severity_level< severity_level > severity_attribute; + +#if defined(BOOST_LOG_DOXYGEN_PASS) + //! Lock requirement for the \c open_record_unlocked method + typedef typename strictest_lock< + typename base_type::open_record_lock, + no_lock< threading_model > + >::type open_record_lock; +#endif // defined(BOOST_LOG_DOXYGEN_PASS) + + //! Lock requirement for the \c swap_unlocked method + typedef typename strictest_lock< + typename base_type::swap_lock, +#ifndef BOOST_LOG_NO_THREADS + boost::log::aux::exclusive_lock_guard< threading_model > +#else + no_lock< threading_model > +#endif // !defined(BOOST_LOG_NO_THREADS) + >::type swap_lock; + +private: + //! Default severity + severity_level m_DefaultSeverity; + //! Severity attribute + severity_attribute m_SeverityAttr; + +public: + /*! + * Default constructor. The constructed logger will have a severity attribute registered. + * The default level for log records will be 0. + */ + basic_severity_logger() : + base_type(), + m_DefaultSeverity(static_cast< severity_level >(0)) + { + base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr); + } + /*! + * Copy constructor + */ + basic_severity_logger(basic_severity_logger const& that) : + base_type(static_cast< base_type const& >(that)), + m_DefaultSeverity(that.m_DefaultSeverity), + m_SeverityAttr(that.m_SeverityAttr) + { + base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr; + } + /*! + * Move constructor + */ + basic_severity_logger(BOOST_RV_REF(basic_severity_logger) that) : + base_type(boost::move(static_cast< base_type& >(that))), + m_DefaultSeverity(boost::move(that.m_DefaultSeverity)), + m_SeverityAttr(boost::move(that.m_SeverityAttr)) + { + base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr; + } + /*! + * Constructor with named arguments. Allows to setup the default level for log records. + * + * \param args A set of named arguments. The following arguments are supported: + * \li \c severity - default severity value + */ + template< typename ArgsT > + explicit basic_severity_logger(ArgsT const& args) : + base_type(args), + m_DefaultSeverity(args[keywords::severity | severity_level()]) + { + base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr); + } + + /*! + * Default severity value getter + */ + severity_level default_severity() const { return m_DefaultSeverity; } + +protected: + /*! + * Severity attribute accessor + */ + severity_attribute const& get_severity_attribute() const { return m_SeverityAttr; } + + /*! + * Unlocked \c open_record + */ + template< typename ArgsT > + record open_record_unlocked(ArgsT const& args) + { + m_SeverityAttr.set_value(args[keywords::severity | m_DefaultSeverity]); + return base_type::open_record_unlocked(args); + } + + //! Unlocked \c swap + void swap_unlocked(basic_severity_logger& that) + { + base_type::swap_unlocked(static_cast< base_type& >(that)); + severity_level t = m_DefaultSeverity; + m_DefaultSeverity = that.m_DefaultSeverity; + that.m_DefaultSeverity = t; + m_SeverityAttr.swap(that.m_SeverityAttr); + } +}; + +/*! + * \brief Severity level support feature + * + * The logger with this feature registers a special attribute with an integral value type on construction. + * This attribute will provide severity level for each log record being made through the logger. + * The severity level can be omitted on logging record construction, in which case the default + * level will be used. The default level can also be customized by passing it to the logger constructor. + * + * The type of the severity level attribute can be specified as a template parameter for the feature + * template. By default, \c int will be used. + */ +template< typename LevelT = int > +struct severity +{ + template< typename BaseT > + struct apply + { + typedef basic_severity_logger< + BaseT, + LevelT + > type; + }; +}; + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +//! The macro allows to put a record with a specific severity level into log +#define BOOST_LOG_STREAM_SEV(logger, lvl)\ + BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl))) + +#ifndef BOOST_LOG_NO_SHORTHAND_NAMES + +//! An equivalent to BOOST_LOG_STREAM_SEV(logger, lvl) +#define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl) + +#endif // BOOST_LOG_NO_SHORTHAND_NAMES + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_ diff --git a/boost/log/sources/severity_logger.hpp b/boost/log/sources/severity_logger.hpp new file mode 100644 index 0000000000..4e9fa580c0 --- /dev/null +++ b/boost/log/sources/severity_logger.hpp @@ -0,0 +1,325 @@ +/* + * 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 severity_logger.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * The header contains implementation of a logger with severity level support. + */ + +#ifndef BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/detail/light_rw_mutex.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/sources/features.hpp> +#include <boost/log/sources/basic_logger.hpp> +#include <boost/log/sources/threading_models.hpp> +#include <boost/log/sources/severity_feature.hpp> +#include <boost/log/keywords/severity.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#ifdef BOOST_LOG_USE_CHAR + +//! Narrow-char logger with severity level support +template< typename LevelT = int > +class severity_logger : + public basic_composite_logger< + char, + severity_logger< LevelT >, + single_thread_model, + features< severity< LevelT > > + > +{ + typedef typename severity_logger::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_logger) + + explicit severity_logger(LevelT level) : base_type(keywords::severity = level) + { + } +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Narrow-char thread-safe logger with severity level support +template< typename LevelT = int > +class severity_logger_mt : + public basic_composite_logger< + char, + severity_logger_mt< LevelT >, + multi_thread_model< boost::log::aux::light_rw_mutex >, + features< severity< LevelT > > + > +{ + typedef typename severity_logger_mt::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_logger_mt) + + explicit severity_logger_mt(LevelT level) : base_type(keywords::severity = level) + { + } +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif + +#ifdef BOOST_LOG_USE_WCHAR_T + +//! Wide-char logger with severity level support +template< typename LevelT = int > +class wseverity_logger : + public basic_composite_logger< + wchar_t, + wseverity_logger< LevelT >, + single_thread_model, + features< severity< LevelT > > + > +{ + typedef typename wseverity_logger::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_logger) + + explicit wseverity_logger(LevelT level) : base_type(keywords::severity = level) + { + } +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Wide-char thread-safe logger with severity level support +template< typename LevelT = int > +class wseverity_logger_mt : + public basic_composite_logger< + wchar_t, + wseverity_logger_mt< LevelT >, + multi_thread_model< boost::log::aux::light_rw_mutex >, + features< severity< LevelT > > + > +{ + typedef typename wseverity_logger_mt::logger_base base_type; + +public: + BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_logger_mt) + + explicit wseverity_logger_mt(LevelT level) : base_type(keywords::severity = level) + { + } +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * \brief Narrow-char logger. Functionally equivalent to \c basic_severity_logger. + * + * See \c severity class template for a more detailed description + */ +template< typename LevelT = int > +class severity_logger : + public basic_composite_logger< + char, + severity_logger< LevelT >, + single_thread_model, + features< severity< LevelT > > + > +{ +public: + /*! + * Default constructor + */ + severity_logger(); + /*! + * Copy constructor + */ + severity_logger(severity_logger const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit severity_logger(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified default severity level + * + * \param level The default severity level + */ + explicit severity_logger(LevelT level); + /*! + * Assignment operator + */ + severity_logger& operator= (severity_logger const& that) + /*! + * Swaps two loggers + */ + void swap(severity_logger& that); +}; + +/*! + * \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_severity_logger. + * + * See \c severity class template for a more detailed description + */ +template< typename LevelT = int > +class severity_logger_mt : + public basic_composite_logger< + char, + severity_logger_mt< LevelT >, + multi_thread_model< implementation_defined >, + features< severity< LevelT > > + > +{ +public: + /*! + * Default constructor + */ + severity_logger_mt(); + /*! + * Copy constructor + */ + severity_logger_mt(severity_logger_mt const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit severity_logger_mt(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified default severity level + * + * \param level The default severity level + */ + explicit severity_logger_mt(LevelT level); + /*! + * Assignment operator + */ + severity_logger_mt& operator= (severity_logger_mt const& that) + /*! + * Swaps two loggers + */ + void swap(severity_logger_mt& that); +}; + +/*! + * \brief Wide-char logger. Functionally equivalent to \c basic_severity_logger. + * + * See \c severity class template for a more detailed description + */ +template< typename LevelT = int > +class wseverity_logger : + public basic_composite_logger< + wchar_t, + wseverity_logger< LevelT >, + single_thread_model, + features< severity< LevelT > > + > +{ +public: + /*! + * Default constructor + */ + wseverity_logger(); + /*! + * Copy constructor + */ + wseverity_logger(wseverity_logger const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit wseverity_logger(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified default severity level + * + * \param level The default severity level + */ + explicit wseverity_logger(LevelT level); + /*! + * Assignment operator + */ + wseverity_logger& operator= (wseverity_logger const& that) + /*! + * Swaps two loggers + */ + void swap(wseverity_logger& that); +}; + +/*! + * \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_severity_logger. + * + * See \c severity class template for a more detailed description + */ +template< typename LevelT = int > +class wseverity_logger_mt : + public basic_composite_logger< + wchar_t, + wseverity_logger_mt< LevelT >, + multi_thread_model< implementation_defined >, + features< severity< LevelT > > + > +{ +public: + /*! + * Default constructor + */ + wseverity_logger_mt(); + /*! + * Copy constructor + */ + wseverity_logger_mt(wseverity_logger_mt const& that); + /*! + * Constructor with named arguments + */ + template< typename... ArgsT > + explicit wseverity_logger_mt(ArgsT... const& args); + /*! + * The constructor creates the logger with the specified default severity level + * + * \param level The default severity level + */ + explicit wseverity_logger_mt(LevelT level); + /*! + * Assignment operator + */ + wseverity_logger_mt& operator= (wseverity_logger_mt const& that) + /*! + * Swaps two loggers + */ + void swap(wseverity_logger_mt& that); +}; + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_ diff --git a/boost/log/sources/threading_models.hpp b/boost/log/sources/threading_models.hpp new file mode 100644 index 0000000000..0cfaf80034 --- /dev/null +++ b/boost/log/sources/threading_models.hpp @@ -0,0 +1,125 @@ +/* + * 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 sources/threading_models.hpp + * \author Andrey Semashev + * \date 04.10.2008 + * + * The header contains definition of threading models that can be used in loggers. + * The header also provides a number of tags that can be used to express lock requirements + * on a function callee. + */ + +#ifndef BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_ +#define BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/locks.hpp> // is_mutex_type +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/mpl/bool.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sources { + +//! Single thread locking model +struct single_thread_model +{ + // We provide methods for the most advanced locking concept: UpgradeLockable + void lock_shared() const {} + bool try_lock_shared() const { return true; } + template< typename TimeT > + bool timed_lock_shared(TimeT const&) const { return true; } + void unlock_shared() const {} + void lock() const {} + bool try_lock() const { return true; } + template< typename TimeT > + bool timed_lock(TimeT const&) const { return true; } + void unlock() const {} + void lock_upgrade() const {} + bool try_lock_upgrade() const { return true; } + template< typename TimeT > + bool timed_lock_upgrade(TimeT const&) const { return true; } + void unlock_upgrade() const {} + void unlock_upgrade_and_lock() const {} + void unlock_and_lock_upgrade() const {} + void unlock_and_lock_shared() const {} + void unlock_upgrade_and_lock_shared() const {} + + void swap(single_thread_model&) {} +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +//! Multi-thread locking model with maximum locking capabilities +template< typename MutexT > +struct multi_thread_model +{ + multi_thread_model() {} + multi_thread_model(multi_thread_model const&) {} + multi_thread_model& operator= (multi_thread_model const&) { return *this; } + + void lock_shared() const { m_Mutex.lock_shared(); } + bool try_lock_shared() const { return m_Mutex.try_lock_shared(); } + template< typename TimeT > + bool timed_lock_shared(TimeT const& t) const { return m_Mutex.timed_lock_shared(t); } + void unlock_shared() const { m_Mutex.unlock_shared(); } + void lock() const { m_Mutex.lock(); } + bool try_lock() const { return m_Mutex.try_lock(); } + template< typename TimeT > + bool timed_lock(TimeT const& t) const { return m_Mutex.timed_lock(t); } + void unlock() const { m_Mutex.unlock(); } + void lock_upgrade() const { m_Mutex.lock_upgrade(); } + bool try_lock_upgrade() const { return m_Mutex.try_lock_upgrade(); } + template< typename TimeT > + bool timed_lock_upgrade(TimeT const& t) const { return m_Mutex.timed_lock_upgrade(t); } + void unlock_upgrade() const { m_Mutex.unlock_upgrade(); } + void unlock_upgrade_and_lock() const { m_Mutex.unlock_upgrade_and_lock(); } + void unlock_and_lock_upgrade() const { m_Mutex.unlock_and_lock_upgrade(); } + void unlock_and_lock_shared() const { m_Mutex.unlock_and_lock_shared(); } + void unlock_upgrade_and_lock_shared() const { m_Mutex.unlock_upgrade_and_lock_shared(); } + + void swap(multi_thread_model&) {} + +private: + //! Synchronization primitive + mutable MutexT m_Mutex; +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +} // namespace sources + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_DOXYGEN_PASS) + +template< > +struct is_mutex_type< boost::log::sources::single_thread_model > : mpl::true_ +{ +}; + +template< typename T > +struct is_mutex_type< boost::log::sources::multi_thread_model< T > > : mpl::true_ +{ +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_ diff --git a/boost/log/support/date_time.hpp b/boost/log/support/date_time.hpp new file mode 100644 index 0000000000..97924ec401 --- /dev/null +++ b/boost/log/support/date_time.hpp @@ -0,0 +1,548 @@ +/* + * 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 support/date_time.hpp + * \author Andrey Semashev + * \date 07.11.2012 + * + * This header enables Boost.DateTime support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_ + +#include <ctime> +#include <string> +#include <locale> +#include <ostream> +#include <iterator> +#include <boost/cstdint.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/date_time/time.hpp> +#include <boost/date_time/date.hpp> +#include <boost/date_time/gregorian/gregorian_types.hpp> +#include <boost/date_time/local_time/local_time_types.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/date_time_format_parser.hpp> +#include <boost/log/detail/light_function.hpp> +#include <boost/log/detail/decomposed_time.hpp> +#include <boost/log/detail/date_time_fmt_gen_traits_fwd.hpp> +#include <boost/log/utility/formatting_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +namespace date_time_support { + +template< typename DateT, typename ValueT > +inline void decompose_date(DateT const& d, boost::log::aux::decomposed_time_wrapper< ValueT >& v) +{ + typedef typename DateT::ymd_type ymd_type; + ymd_type ymd = d.year_month_day(); + v.year = ymd.year; + v.month = ymd.month; + v.day = ymd.day; +} + +template< typename TimeDurationT, typename ValueT > +inline void decompose_time_of_day(TimeDurationT const& tod, boost::log::aux::decomposed_time_wrapper< ValueT >& v) +{ + v.hours = tod.hours(); + v.minutes = tod.minutes(); + v.seconds = tod.seconds(); + + typedef typename TimeDurationT::traits_type traits_type; + enum + { + adjustment_ratio = (traits_type::ticks_per_second > boost::log::aux::decomposed_time::subseconds_per_second ? + traits_type::ticks_per_second / boost::log::aux::decomposed_time::subseconds_per_second : + boost::log::aux::decomposed_time::subseconds_per_second / traits_type::ticks_per_second) + }; + uint64_t frac = tod.fractional_seconds(); + v.subseconds = static_cast< uint32_t >(traits_type::ticks_per_second > boost::log::aux::decomposed_time::subseconds_per_second ? frac / adjustment_ratio : frac * adjustment_ratio); +} + +template< typename TimeDurationT, typename ValueT > +inline void decompose_time_duration(TimeDurationT const& dur, boost::log::aux::decomposed_time_wrapper< ValueT >& v) +{ + if (dur.is_negative()) + { + v.negative = true; + (decompose_time_of_day)(-dur, v); + } + else + (decompose_time_of_day)(dur, v); +} + +template< typename DateDurationT, typename ValueT > +inline void decompose_date_duration(DateDurationT const& dur, boost::log::aux::decomposed_time_wrapper< ValueT >& v) +{ + if (dur.is_negative()) + { + v.negative = true; + v.day = (-dur).days(); + } + else + v.day = dur.days(); +} + +template< typename TimeT, typename ValueT > +inline void decompose_time(TimeT const& t, boost::log::aux::decomposed_time_wrapper< ValueT >& v) +{ + (decompose_date)(t.date(), v); + (decompose_time_of_day)(t.time_of_day(), v); +} + +} // namespace date_time_support + +template< typename TimeT, typename CharT > +struct date_time_formatter_generator_traits_impl +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Value type + typedef TimeT value_type; + + //! Formatter function + typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; + + //! Formatter implementation + class formatter : + public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type > + { + BOOST_COPYABLE_AND_MOVABLE_ALT(formatter) + + private: + // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type. + typedef typename formatter::date_time_formatter_ base_type; + + public: + typedef typename base_type::result_type result_type; + // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead. + typedef typename date_time_formatter_generator_traits_impl< TimeT, CharT >::value_type value_type; + + public: + BOOST_DEFAULTED_FUNCTION(formatter(), {}) + formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {} + formatter(BOOST_RV_REF(formatter) that) { this->swap(that); } + + formatter& operator= (formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + if (value.is_not_a_date_time()) + strm << "not-a-date-time"; + else if (value.is_pos_infinity()) + strm << "+infinity"; + else if (value.is_neg_infinity()) + strm << "-infinity"; + else + { + boost::log::aux::decomposed_time_wrapper< value_type > val(value); + date_time_support::decompose_time(value, val); + base_type::operator() (strm, val); + } + } + }; + + //! The function parses format string and constructs formatter function + static formatter_function_type parse(string_type const& format) + { + formatter fmt; + boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt); + boost::log::aux::parse_date_time_format(format, builder); + return formatter_function_type(boost::move(fmt)); + } +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< posix_time::ptime, CharT, VoidT > : + public date_time_formatter_generator_traits_impl< posix_time::ptime, CharT > +{ +}; + +template< typename TimeT, typename TimeZoneT, typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< local_time::local_date_time_base< TimeT, TimeZoneT >, CharT, VoidT > +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Value type + typedef local_time::local_date_time_base< TimeT, TimeZoneT > value_type; + + //! Formatter function + typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; + + //! Formatter implementation + class formatter : + public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type > + { + BOOST_COPYABLE_AND_MOVABLE_ALT(formatter) + + private: + // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type. + typedef typename formatter::date_time_formatter_ base_type; + + public: + typedef typename base_type::result_type result_type; + typedef typename base_type::context context; + // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead. + typedef typename date_time_formatter_generator_traits< local_time::local_date_time_base< TimeT, TimeZoneT >, CharT, VoidT >::value_type value_type; + + public: + BOOST_DEFAULTED_FUNCTION(formatter(), {}) + formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {} + formatter(BOOST_RV_REF(formatter) that) { this->swap(that); } + + formatter& operator= (formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + if (value.is_not_a_date_time()) + strm << "not-a-date-time"; + else if (value.is_pos_infinity()) + strm << "+infinity"; + else if (value.is_neg_infinity()) + strm << "-infinity"; + else + { + boost::log::aux::decomposed_time_wrapper< value_type > val(value); + date_time_support::decompose_time(value.local_time(), val); + base_type::operator() (strm, val); + } + } + + public: + static void format_iso_time_zone(context& ctx) + { + ctx.strm << ctx.value.m_time.zone_abbrev(true); + ctx.strm.flush(); + } + + static void format_extended_iso_time_zone(context& ctx) + { + ctx.strm << ctx.value.m_time.zone_name(true); + ctx.strm.flush(); + } + }; + + class formatter_builder : + public boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > + { + private: + typedef boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > base_type; + + public: + explicit formatter_builder(formatter& fmt) : base_type(fmt) + { + } + + void on_iso_time_zone() + { + this->m_formatter.add_formatter(&formatter::format_iso_time_zone); + } + + void on_extended_iso_time_zone() + { + this->m_formatter.add_formatter(&formatter::format_extended_iso_time_zone); + } + }; + + //! The function parses format string and constructs formatter function + static formatter_function_type parse(string_type const& format) + { + formatter fmt; + formatter_builder builder(fmt); + boost::log::aux::parse_date_time_format(format, builder); + return formatter_function_type(boost::move(fmt)); + } +}; + +template< typename DateT, typename CharT > +struct date_formatter_generator_traits_impl +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Value type + typedef DateT value_type; + + //! Formatter function + typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; + + //! Formatter implementation + class formatter : + public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type > + { + BOOST_COPYABLE_AND_MOVABLE_ALT(formatter) + + private: + // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type. + typedef typename formatter::date_time_formatter_ base_type; + + public: + typedef typename base_type::result_type result_type; + // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead. + typedef typename date_formatter_generator_traits_impl< DateT, CharT >::value_type value_type; + + public: + BOOST_DEFAULTED_FUNCTION(formatter(), {}) + formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {} + formatter(BOOST_RV_REF(formatter) that) { this->swap(that); } + + formatter& operator= (formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + if (value.is_not_a_date()) + strm << "not-a-date-time"; + else if (value.is_pos_infinity()) + strm << "+infinity"; + else if (value.is_neg_infinity()) + strm << "-infinity"; + else + { + boost::log::aux::decomposed_time_wrapper< value_type > val(value); + date_time_support::decompose_date(value, val); + base_type::operator() (strm, val); + } + } + }; + + //! The function parses format string and constructs formatter function + static formatter_function_type parse(string_type const& format) + { + formatter fmt; + boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt); + boost::log::aux::parse_date_format(format, builder); + return formatter_function_type(boost::move(fmt)); + } +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< gregorian::date, CharT, VoidT > : + public date_formatter_generator_traits_impl< gregorian::date, CharT > +{ +}; + +template< typename TimeDurationT, typename CharT > +struct time_duration_formatter_generator_traits_impl +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Value type + typedef TimeDurationT value_type; + + //! Formatter function + typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; + + //! Formatter implementation + class formatter : + public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type > + { + BOOST_COPYABLE_AND_MOVABLE_ALT(formatter) + + private: + // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type. + typedef typename formatter::date_time_formatter_ base_type; + + public: + typedef typename base_type::result_type result_type; + // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead. + typedef typename time_duration_formatter_generator_traits_impl< TimeDurationT, CharT >::value_type value_type; + + public: + BOOST_DEFAULTED_FUNCTION(formatter(), {}) + formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {} + formatter(BOOST_RV_REF(formatter) that) { this->swap(that); } + + formatter& operator= (formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + if (value.is_not_a_date_time()) + strm << "not-a-date-time"; + else if (value.is_pos_infinity()) + strm << "+infinity"; + else if (value.is_neg_infinity()) + strm << "-infinity"; + else + { + boost::log::aux::decomposed_time_wrapper< value_type > val(value); + date_time_support::decompose_time_duration(value, val); + base_type::operator() (strm, val); + } + } + }; + + //! The function parses format string and constructs formatter function + static formatter_function_type parse(string_type const& format) + { + formatter fmt; + boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt); + boost::log::aux::parse_time_format(format, builder); + return formatter_function_type(boost::move(fmt)); + } +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< posix_time::time_duration, CharT, VoidT > : + public time_duration_formatter_generator_traits_impl< posix_time::time_duration, CharT > +{ +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< posix_time::hours, CharT, VoidT > : + public time_duration_formatter_generator_traits_impl< posix_time::hours, CharT > +{ +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< posix_time::minutes, CharT, VoidT > : + public time_duration_formatter_generator_traits_impl< posix_time::minutes, CharT > +{ +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< posix_time::seconds, CharT, VoidT > : + public time_duration_formatter_generator_traits_impl< posix_time::seconds, CharT > +{ +}; + +template< typename BaseDurationT, uint64_t FracOfSecondV, typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< date_time::subsecond_duration< BaseDurationT, FracOfSecondV >, CharT, VoidT > : + public time_duration_formatter_generator_traits_impl< date_time::subsecond_duration< BaseDurationT, FracOfSecondV >, CharT > +{ +}; + +template< typename DateDurationT, typename CharT > +struct date_duration_formatter_generator_traits_impl +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Formatting stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Value type + typedef DateDurationT value_type; + + //! Formatter function + typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; + + //! Formatter implementation + class formatter : + public boost::log::aux::date_time_formatter< boost::log::aux::decomposed_time_wrapper< value_type >, char_type > + { + BOOST_COPYABLE_AND_MOVABLE_ALT(formatter) + + private: + // Do not change this typedef, copy-pasting the inherited class from above will break compilation with MSVC 2012 because it incorrectly binds value_type. + typedef typename formatter::date_time_formatter_ base_type; + + public: + typedef typename base_type::result_type result_type; + // This typedef is needed to work around MSVC 2012 crappy name lookup. Otherwise base_type::value_type is bound instead. + typedef typename date_duration_formatter_generator_traits_impl< DateDurationT, CharT >::value_type value_type; + + public: + BOOST_DEFAULTED_FUNCTION(formatter(), {}) + formatter(formatter const& that) : base_type(static_cast< base_type const& >(that)) {} + formatter(BOOST_RV_REF(formatter) that) { this->swap(that); } + + formatter& operator= (formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + if (value.is_not_a_date()) + strm << "not-a-date-time"; + else if (value.is_pos_infinity()) + strm << "+infinity"; + else if (value.is_neg_infinity()) + strm << "-infinity"; + else + { + boost::log::aux::decomposed_time_wrapper< value_type > val(value); + date_time_support::decompose_date_duration(value, val); + base_type::operator() (strm, val); + } + } + }; + + //! The function parses format string and constructs formatter function + static formatter_function_type parse(string_type const& format) + { + formatter fmt; + boost::log::aux::decomposed_time_formatter_builder< formatter, char_type > builder(fmt); + boost::log::aux::parse_date_format(format, builder); + return formatter_function_type(boost::move(fmt)); + } +}; + +template< typename CharT, typename VoidT > +struct date_time_formatter_generator_traits< gregorian::date_duration, CharT, VoidT > : + public date_formatter_generator_traits_impl< gregorian::date_duration, CharT > +{ +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SUPPORT_DATE_TIME_HPP_INCLUDED_ diff --git a/boost/log/support/exception.hpp b/boost/log/support/exception.hpp new file mode 100644 index 0000000000..3b0ff9767b --- /dev/null +++ b/boost/log/support/exception.hpp @@ -0,0 +1,72 @@ +/* + * 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 support/exception.hpp + * \author Andrey Semashev + * \date 18.07.2009 + * + * This header enables Boost.Exception support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_ + +#include <boost/exception/info.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/named_scope.hpp> +#include <boost/log/utility/type_info_wrapper.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * Attribute name exception information + */ +typedef error_info< struct attribute_name_info_tag, attribute_name > attribute_name_info; + +/*! + * Type info exception information + */ +typedef error_info< struct type_info_info_tag, type_info_wrapper > type_info_info; + +/*! + * Parse position exception information + */ +typedef error_info< struct position_info_tag, unsigned int > position_info; + +/*! + * Current scope exception information + */ +typedef error_info< struct current_scope_info_tag, attributes::named_scope_list > current_scope_info; + +/*! + * The function returns an error information object that contains current stack of scopes. + * This information can then be attached to an exception and extracted at the catch site. + * The extracted scope list won't be affected by any scope changes that may happen during + * the exception propagation. + * + * \note See the \c named_scope attribute documentation on how to maintain scope list. + */ +inline current_scope_info current_scope() +{ + return current_scope_info(attributes::named_scope::get_scopes()); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SUPPORT_EXCEPTION_HPP_INCLUDED_ diff --git a/boost/log/support/regex.hpp b/boost/log/support/regex.hpp new file mode 100644 index 0000000000..cecb106ad6 --- /dev/null +++ b/boost/log/support/regex.hpp @@ -0,0 +1,76 @@ +/* + * 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 support/regex.hpp + * \author Andrey Semashev + * \date 18.07.2009 + * + * This header enables Boost.Regex support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_REGEX_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_REGEX_HPP_INCLUDED_ + +#include <string> +#include <boost/regex.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/matches.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! This tag type is used if an expression is recognized as a Boost.Regex expression +struct boost_regex_expression_tag; + +//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits +template< typename CharT, typename TraitsT > +struct matching_expression_kind< boost::basic_regex< CharT, TraitsT > > +{ + typedef boost_regex_expression_tag type; +}; + +//! The matching function implementation +template< typename ExpressionT > +struct match_traits< ExpressionT, boost_regex_expression_tag > +{ + typedef ExpressionT compiled_type; + static compiled_type compile(ExpressionT const& expr) { return expr; } + + template< typename StringT, typename CharT, typename TraitsT > + static bool matches(StringT const& str, boost::basic_regex< CharT, TraitsT > const& expr, boost::regex_constants::match_flag_type flags = boost::regex_constants::match_default) + { + return boost::regex_match(str.begin(), str.end(), expr, flags); + } + + template< typename CharT, typename StringTraitsT, typename AllocatorT, typename ReTraitsT > + static bool matches( + std::basic_string< CharT, StringTraitsT, AllocatorT > const& str, + boost::basic_regex< CharT, ReTraitsT > const& expr, + boost::regex_constants::match_flag_type flags = boost::regex_constants::match_default) + { + const CharT* p = str.c_str(); + return boost::regex_match(p, p + str.size(), expr, flags); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SUPPORT_REGEX_HPP_INCLUDED_ diff --git a/boost/log/support/spirit_classic.hpp b/boost/log/support/spirit_classic.hpp new file mode 100644 index 0000000000..fb8a6f047d --- /dev/null +++ b/boost/log/support/spirit_classic.hpp @@ -0,0 +1,112 @@ +/* + * 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 support/spirit_classic.hpp + * \author Andrey Semashev + * \date 19.07.2009 + * + * This header enables Boost.Spirit (classic) support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/matches.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_SPIRIT_THREADSAFE) && !defined(BOOST_LOG_DOXYGEN_PASS) +/* + * As Boost.Log filters may be called in multiple threads concurrently, + * this may lead to using Boost.Spirit parsers in a multithreaded context. + * In order to protect parsers properly, BOOST_SPIRIT_THREADSAFE macro should + * be defined. + * + * If we got here, it means that the user did not define that macro and we + * have to define it ourselves. However, it may also lead to ODR violations + * or even total ignorance of this macro, if the user has included Boost.Spirit + * headers before including this header, or uses Boost.Spirit without the macro + * in other translation units. The only reliable way to settle this problem is to + * define the macro for the whole project (i.e. all translation units). + */ +#if defined(__GNUC__) +#pragma message "Boost.Log: Boost.Spirit requires BOOST_SPIRIT_THREADSAFE macro to be defined if parsers are used in a multithreaded context. It is strongly recommended to define this macro project-wide." +#elif defined(_MSC_VER) +#pragma message("Boost.Log: Boost.Spirit requires BOOST_SPIRIT_THREADSAFE macro to be defined if parsers are used in a multithreaded context. It is strongly recommended to define this macro project-wide.") +#endif +#define BOOST_SPIRIT_THREADSAFE 1 +#endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_SPIRIT_THREADSAFE) + +#include <boost/spirit/include/classic_parser.hpp> + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! This tag type is used if an expression is recognized as a Boost.Spirit.Classic expression +struct boost_spirit_classic_expression_tag; + +//! The trait verifies if the type can be converted to a Boost.Spirit (classic) parser +template< typename T > +struct is_spirit_classic_parser +{ +private: + typedef char yes_type; + struct no_type { char dummy[2]; }; + + template< typename U > + static yes_type check_spirit_classic_parser(spirit::classic::parser< U > const&); + static no_type check_spirit_classic_parser(...); + static T& get_T(); + +public: + enum { value = sizeof(check_spirit_classic_parser(get_T())) == sizeof(yes_type) }; + typedef mpl::bool_< value > type; +}; + +//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits +template< typename ExpressionT > +struct matching_expression_kind< ExpressionT, typename boost::enable_if_c< is_spirit_classic_parser< ExpressionT >::value >::type > +{ + typedef boost_spirit_classic_expression_tag type; +}; + +//! The matching function implementation +template< typename ExpressionT > +struct match_traits< ExpressionT, boost_spirit_classic_expression_tag > +{ + typedef ExpressionT compiled_type; + static compiled_type compile(ExpressionT const& expr) { return expr; } + + template< typename StringT > + static bool matches(StringT const& str, ExpressionT const& expr) + { + typedef typename StringT::const_iterator const_iterator; + spirit::classic::parse_info< const_iterator > info = + spirit::classic::parse(str.begin(), str.end(), expr); + return info.full; + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_ diff --git a/boost/log/support/spirit_qi.hpp b/boost/log/support/spirit_qi.hpp new file mode 100644 index 0000000000..48c0059a44 --- /dev/null +++ b/boost/log/support/spirit_qi.hpp @@ -0,0 +1,92 @@ +/* + * 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 support/spirit_qi.hpp + * \author Andrey Semashev + * \date 19.07.2009 + * + * This header enables Boost.Spirit.Qi support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_ + +#include <boost/utility/enable_if.hpp> +#include <boost/spirit/include/qi_parse.hpp> +#include <boost/spirit/include/qi_domain.hpp> +#include <boost/spirit/include/support_unused.hpp> +#include <boost/spirit/home/support/meta_compiler.hpp> // spirit::compile() +#include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp> // rule forward declaration +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/matches.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! This tag type is used if an expression is recognized as a Boost.Spirit.Qi expression +struct boost_spirit_qi_expression_tag; + +//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits +template< typename ExpressionT > +struct matching_expression_kind< ExpressionT, typename boost::enable_if< spirit::traits::matches< spirit::qi::domain, ExpressionT > >::type > +{ + typedef boost_spirit_qi_expression_tag type; +}; + +//! The matching function implementation +template< typename ExpressionT > +struct match_traits< ExpressionT, boost_spirit_qi_expression_tag > +{ + typedef typename spirit::result_of::compile< spirit::qi::domain, ExpressionT, spirit::unused_type >::type compiled_type; + + static compiled_type compile(ExpressionT const& expr) + { + return spirit::compile< spirit::qi::domain >(expr); + } + + template< typename StringT > + static bool matches(StringT const& str, ExpressionT const& expr) + { + typedef typename StringT::const_iterator const_iterator; + const_iterator it = str.begin(), end = str.end(); + return (spirit::qi::parse(it, end, expr) && it == end); + } +}; + +//! The matching function implementation +template< typename IteratorT, typename T1, typename T2, typename T3, typename T4 > +struct match_traits< spirit::qi::rule< IteratorT, T1, T2, T3, T4 >, boost_spirit_qi_expression_tag > +{ + typedef spirit::qi::rule< IteratorT, T1, T2, T3, T4 > compiled_type; + static compiled_type compile(compiled_type const& expr) { return expr; } + + template< typename StringT > + static bool matches(StringT const& str, compiled_type const& expr) + { + typedef typename StringT::const_iterator const_iterator; + const_iterator it = str.begin(), end = str.end(); + return (spirit::qi::parse(it, end, expr) && it == end); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SUPPORT_SPIRIT_QI_HPP_INCLUDED_ diff --git a/boost/log/support/std_regex.hpp b/boost/log/support/std_regex.hpp new file mode 100644 index 0000000000..92395352ac --- /dev/null +++ b/boost/log/support/std_regex.hpp @@ -0,0 +1,86 @@ +/* + * 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 support/std_regex.hpp + * \author Andrey Semashev + * \date 19.03.2014 + * + * This header enables \c std::regex support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_STD_REGEX_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_STD_REGEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_NO_CXX11_HDR_REGEX) + +#if defined(__GNUC__) +#pragma message "Boost.Log: This header requires support for std::regex in the standard library." +#elif defined(_MSC_VER) +#pragma message("Boost.Log: This header requires support for std::regex in the standard library.") +#endif + +#else // defined(BOOST_NO_CXX11_HDR_REGEX) + +#include <regex> +#include <string> +#include <boost/log/utility/functional/matches.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! This tag type is used if an expression is recognized as \c std::regex +struct std_regex_expression_tag; + +//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits +template< typename CharT, typename ReTraitsT > +struct matching_expression_kind< std::basic_regex< CharT, ReTraitsT > > +{ + typedef std_regex_expression_tag type; +}; + +//! The matching function implementation +template< typename ExpressionT > +struct match_traits< ExpressionT, std_regex_expression_tag > +{ + typedef ExpressionT compiled_type; + static compiled_type compile(ExpressionT const& expr) { return expr; } + + template< typename StringT, typename CharT, typename ReTraitsT > + static bool matches(StringT const& str, std::basic_regex< CharT, ReTraitsT > const& expr, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) + { + return std::regex_match(str.begin(), str.end(), expr, flags); + } + + template< typename CharT, typename StringTraitsT, typename AllocatorT, typename ReTraitsT > + static bool matches(std::basic_string< CharT, StringTraitsT, AllocatorT > const& str, std::basic_regex< CharT, ReTraitsT > const& expr, std::regex_constants::match_flag_type flags = std::regex_constants::match_default) + { + const CharT* p = str.c_str(); + return std::regex_match(p, p + str.size(), expr, flags); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // defined(BOOST_NO_CXX11_HDR_REGEX) + +#endif // BOOST_LOG_SUPPORT_STD_REGEX_HPP_INCLUDED_ diff --git a/boost/log/support/xpressive.hpp b/boost/log/support/xpressive.hpp new file mode 100644 index 0000000000..5959716e57 --- /dev/null +++ b/boost/log/support/xpressive.hpp @@ -0,0 +1,75 @@ +/* + * 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 support/xpressive.hpp + * \author Andrey Semashev + * \date 18.07.2009 + * + * This header enables Boost.Xpressive support for Boost.Log. + */ + +#ifndef BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_ +#define BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_ + +#include <string> +#include <boost/xpressive/basic_regex.hpp> +#include <boost/xpressive/regex_constants.hpp> +#include <boost/xpressive/regex_algorithms.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/matches.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! This tag type is used if an expression is recognized as a Boost.Xpressive expression +struct boost_xpressive_expression_tag; + +//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits +template< typename T > +struct matching_expression_kind< xpressive::basic_regex< T > > +{ + typedef boost_xpressive_expression_tag type; +}; + +//! The matching function implementation +template< typename ExpressionT > +struct match_traits< ExpressionT, boost_xpressive_expression_tag > +{ + typedef ExpressionT compiled_type; + static compiled_type compile(ExpressionT const& expr) { return expr; } + + template< typename StringT, typename T > + static bool matches(StringT const& str, xpressive::basic_regex< T > const& expr, xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default) + { + return xpressive::regex_match(str, expr, flags); + } + + template< typename CharT, typename TraitsT, typename AllocatorT > + static bool matches(std::basic_string< CharT, TraitsT, AllocatorT > const& str, xpressive::basic_regex< const CharT* > const& expr, xpressive::regex_constants::match_flag_type flags = xpressive::regex_constants::match_default) + { + const CharT* p = str.c_str(); + return xpressive::regex_match(p, p + str.size(), expr, flags); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_SUPPORT_XPRESSIVE_HPP_INCLUDED_ diff --git a/boost/log/trivial.hpp b/boost/log/trivial.hpp new file mode 100644 index 0000000000..90de113b68 --- /dev/null +++ b/boost/log/trivial.hpp @@ -0,0 +1,127 @@ +/* + * 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 log/trivial.hpp + * \author Andrey Semashev + * \date 07.11.2009 + * + * This header defines tools for trivial logging support + */ + +#ifndef BOOST_LOG_TRIVIAL_HPP_INCLUDED_ +#define BOOST_LOG_TRIVIAL_HPP_INCLUDED_ + +#include <iosfwd> +#include <ostream> +#include <boost/log/detail/config.hpp> +#include <boost/log/keywords/severity.hpp> +#include <boost/log/sources/severity_logger.hpp> +#include <boost/log/sources/record_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_LOG_USE_CHAR) +#error Boost.Log: Trivial logging is available for narrow-character builds only. Use advanced initialization routines to setup wide-character logging. +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace trivial { + +//! Trivial severity levels +enum severity_level +{ + trace, + debug, + info, + warning, + error, + fatal +}; + +//! Returns stringized enumeration value or \c NULL, if the value is not valid +BOOST_LOG_API const char* to_string(severity_level lvl); + +//! Outputs stringized representation of the severity level to the stream +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< ( + std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl) +{ + const char* str = boost::log::trivial::to_string(lvl); + if (str) + strm << str; + else + strm << static_cast< int >(lvl); + return strm; +} + +//! Reads stringized representation of the severity level from the stream +template< typename CharT, typename TraitsT > +BOOST_LOG_API std::basic_istream< CharT, TraitsT >& operator>> ( + std::basic_istream< CharT, TraitsT >& strm, severity_level& lvl); + +//! Trivial logger type +#if !defined(BOOST_LOG_NO_THREADS) +typedef sources::severity_logger_mt< severity_level > logger_type; +#else +typedef sources::severity_logger< severity_level > logger_type; +#endif + +/*! + * \brief Trivial logger tag + * + * This tag can be used to acquire the logger that is used with lrivial logging macros. + * This may be useful when the logger is used with other macros which require a logger. + */ +struct logger +{ + //! Logger type + typedef trivial::logger_type logger_type; + + /*! + * Returns a reference to the trivial logger instance + */ + static BOOST_LOG_API logger_type& get(); + + // Implementation details - never use these +#if !defined(BOOST_LOG_DOXYGEN_PASS) + enum registration_line_t { registration_line = __LINE__ }; + static const char* registration_file() { return __FILE__; } + static BOOST_LOG_API logger_type construct_logger(); +#endif +}; + +/*! + * The macro is used to initiate logging. The \c lvl argument of the macro specifies one of the following + * severity levels: \c trace, \c debug, \c info, \c warning, \c error or \c fatal (see \c severity_level enum). + * Following the macro, there may be a streaming expression that composes the record message string. For example: + * + * \code + * BOOST_LOG_TRIVIAL(info) << "Hello, world!"; + * \endcode + */ +#define BOOST_LOG_TRIVIAL(lvl)\ + BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\ + (::boost::log::keywords::severity = ::boost::log::trivial::lvl)) + +} // namespace trivial + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> +#if defined(BOOST_LOG_EXPRESSIONS_KEYWORD_HPP_INCLUDED_) +#include <boost/log/detail/trivial_keyword.hpp> +#endif + +#endif // BOOST_LOG_TRIVIAL_HPP_INCLUDED_ diff --git a/boost/log/utility/empty_deleter.hpp b/boost/log/utility/empty_deleter.hpp new file mode 100644 index 0000000000..67e5abc97b --- /dev/null +++ b/boost/log/utility/empty_deleter.hpp @@ -0,0 +1,42 @@ +/* + * 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 empty_deleter.hpp + * \author Andrey Semashev + * \date 22.04.2007 + * + * This header is deprecated, use boost/utility/empty_deleter.hpp instead. The header is left for + * backward compatibility and will be removed in future versions. + */ + +#ifndef BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ + +#include <boost/core/null_deleter.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GNUC__) +#pragma message "Boost.Log: This header is deprecated, use boost/core/null_deleter.hpp instead." +#elif defined(_MSC_VER) +#pragma message("Boost.Log: This header is deprecated, use boost/core/null_deleter.hpp instead.") +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +typedef boost::null_deleter empty_deleter; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ diff --git a/boost/log/utility/exception_handler.hpp b/boost/log/utility/exception_handler.hpp new file mode 100644 index 0000000000..c5392be687 --- /dev/null +++ b/boost/log/utility/exception_handler.hpp @@ -0,0 +1,354 @@ +/* + * 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 exception_handler.hpp + * \author Andrey Semashev + * \date 12.07.2009 + * + * This header contains tools for exception handlers support in different parts of the library. + */ + +#ifndef BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_ + +#include <new> // std::nothrow_t +#include <boost/mpl/bind.hpp> +#include <boost/mpl/quote.hpp> +#include <boost/mpl/fold.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/nop.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_MAX_EXCEPTION_TYPES +//! Maximum number of exception types that can be specified for exception handlers +#define BOOST_LOG_MAX_EXCEPTION_TYPES 10 +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_exception_types, exception_types, false) + +//! Root class for the exception handler class hierarchy +template< typename HandlerT > +class eh_root +{ +public: + //! The exception handler type + typedef HandlerT handler_type; + //! The handler result type + typedef void result_type; + +protected: + //! Exception handler + handler_type m_Handler; + +public: + //! Initializing constructor + explicit eh_root(handler_type const& handler) : m_Handler(handler) + { + } + + //! Exception launcher + void operator()() const + { + throw; + } +}; + +//! A cons-list element of the exception handler class hierarchy +template< typename ExceptionT, typename BaseT > +class eh_cons : + public BaseT +{ + //! Base type + typedef BaseT base_type; + +public: + //! The exception handler type + typedef typename base_type::handler_type handler_type; + +public: + //! Initializing constructor + explicit eh_cons(handler_type const& handler) : base_type(handler) + { + } + + //! Exception launcher + void operator()() const + { + try + { + base_type::operator()(); + } + catch (ExceptionT& e) + { + this->m_Handler(e); + } + } +}; + +template< template< typename, typename > class EHT, typename HandlerT > +struct make_self_contained_exception_handler +{ + typedef EHT< typename HandlerT::exception_types, HandlerT > type; +}; + +} // namespace aux + +/*! + * An exception handler functional object. The handler aggregates a user-defined + * functional object that will be called when one of the specified exception types + * is caught. + */ +template< typename SequenceT, typename HandlerT > +class exception_handler : + public mpl::fold< + SequenceT, + aux::eh_root< HandlerT >, + mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 > + >::type +{ + //! Base type + typedef typename mpl::fold< + SequenceT, + aux::eh_root< HandlerT >, + mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 > + >::type base_type; + +public: +#ifndef BOOST_LOG_DOXYGEN_PASS + typedef typename base_type::handler_type handler_type; +#else + //! The exception handler type + typedef HandlerT handler_type; + //! The handler result type + typedef void result_type; +#endif + +public: + /*! + * Initializing constructor. Creates an exception handler with the specified + * function object that will receive the exception. + */ + explicit exception_handler(handler_type const& handler) : base_type(handler) + { + } + + /*! + * Exception launcher. Rethrows the current exception in order to detect its type + * and pass it to the aggregated function object. + * + * \note Must be called from within a \c catch statement. + */ + void operator()() const + { + base_type::operator()(); + } +}; + +/*! + * A no-throw exception handler functional object. Acts similar to \c exception_handler, + * but in case if the exception cannot be handled the exception is not propagated + * from the handler. Instead the user-defined functional object is called with + * no parameters. + */ +template< typename SequenceT, typename HandlerT > +class nothrow_exception_handler : + public exception_handler< SequenceT, HandlerT > +{ + //! Base type + typedef exception_handler< SequenceT, HandlerT > base_type; + +public: +#ifndef BOOST_LOG_DOXYGEN_PASS + typedef typename base_type::handler_type handler_type; +#else + //! The exception handler type + typedef HandlerT handler_type; + //! The handler result type + typedef void result_type; +#endif + +public: + /*! + * Initializing constructor. Creates an exception handler with the specified + * function object that will receive the exception. + */ + explicit nothrow_exception_handler(handler_type const& handler) : base_type(handler) + { + } + + /*! + * Exception launcher. Rethrows the current exception in order to detect its type + * and pass it to the aggregated function object. If the type of the exception + * could not be detected, the user-defined handler is called with no arguments. + * + * \note Must be called from within a \c catch statement. + */ + void operator()() const + { + try + { + base_type::operator()(); + } + catch (...) + { + this->m_Handler(); + } + } +}; + +/*! + * The function creates an empty exception handler that effectively suppresses any exception + */ +inline nop make_exception_suppressor() +{ + return nop(); +} + +#ifndef BOOST_LOG_DOXYGEN_PASS + +template< typename HandlerT > +inline typename lazy_enable_if< + aux::has_exception_types< HandlerT >, + aux::make_self_contained_exception_handler< exception_handler, HandlerT > +>::type make_exception_handler(HandlerT const& handler) +{ + typedef typename aux::make_self_contained_exception_handler< exception_handler, HandlerT >::type eh_t; + return eh_t(handler); +} + +template< typename HandlerT > +inline typename lazy_enable_if< + aux::has_exception_types< HandlerT >, + aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT > +>::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&) +{ + typedef typename aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >::type eh_t; + return eh_t(handler); +} + +#define BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL(z, n, data)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\ + inline exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ + HandlerT\ + > make_exception_handler(HandlerT const& handler)\ + {\ + typedef exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ + HandlerT\ + > eh_t;\ + return eh_t(handler);\ + }\ + template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\ + inline nothrow_exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ + HandlerT\ + > make_exception_handler(HandlerT const& handler, std::nothrow_t const&)\ + {\ + typedef nothrow_exception_handler<\ + BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\ + HandlerT\ + > eh_t;\ + return eh_t(handler);\ + } + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_EXCEPTION_TYPES, BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL, ~) + +#undef BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * The function creates an exception handler functional object. The handler will call to the + * user-specified functional object with an exception as its argument. + * + * \param handler User-defined functional object that will receive exceptions. + * \return A nullary functional object that should be called from within a \c catch statement. + * + * \note This form requires the user-defined functional object to have an \c exception_types + * nested type. This type should be an MPL sequence of all expected exception types. + */ +template< typename HandlerT > +exception_handler< typename HandlerT::exception_types, HandlerT > +make_exception_handler(HandlerT const& handler); + +/*! + * The function creates an exception handler functional object. The handler will call to the + * user-specified functional object with an exception as its argument. If the exception type + * cannot be identified, the handler will call the user-defined functor with no arguments, + * instead of propagating exception to the caller. + * + * \overload + * + * \param handler User-defined functional object that will receive exceptions. + * \return A nullary functional object that should be called from within a \c catch statement. + * + * \note This form requires the user-defined functional object to have an \c exception_types + * nested type. This type should be an MPL sequence of all expected exception types. + */ +template< typename HandlerT > +nothrow_exception_handler< typename HandlerT::exception_types, HandlerT > +make_exception_handler(HandlerT const& handler, std::nothrow_t const&); + +/*! + * The function creates an exception handler functional object. The handler will call to the + * user-specified functional object with an exception as its argument. All expected exception + * types should be specified as first template parameters explicitly, in the order they would + * be specified in a corresponding <tt>try/catch</tt> statement. + * + * \overload + * + * \param handler User-defined functional object that will receive exceptions. + * \return A nullary functional object that should be called from within a \c catch statement. + */ +template< typename... ExceptionsT, typename HandlerT > +exception_handler< MPL_sequence_of_ExceptionsT, HandlerT > +make_exception_handler(HandlerT const& handler); + +/*! + * The function creates an exception handler functional object. The handler will call to the + * user-specified functional object with an exception as its argument. If the exception type + * cannot be identified, the handler will call the user-defined functor with no arguments, + * instead of propagating exception to the caller. All expected exception types should be + * specified as first template parameters explicitly, in the order they would be specified in + * a corresponding <tt>try/catch</tt> statement. + * + * \overload + * + * \param handler User-defined functional object that will receive exceptions. + * \return A nullary functional object that should be called from within a \c catch statement. + */ +template< typename... ExceptionsT, typename HandlerT > +nothrow_exception_handler< MPL_sequence_of_ExceptionsT, HandlerT > +make_exception_handler(HandlerT const& handler, std::nothrow_t const&); + +#endif // BOOST_LOG_DOXYGEN_PASS + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_ diff --git a/boost/log/utility/explicit_operator_bool.hpp b/boost/log/utility/explicit_operator_bool.hpp new file mode 100644 index 0000000000..0d708288dc --- /dev/null +++ b/boost/log/utility/explicit_operator_bool.hpp @@ -0,0 +1,42 @@ +/* + * 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 explicit_operator_bool.hpp + * \author Andrey Semashev + * \date 08.03.2009 + * + * This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead. The header is left for + * backward compatibility and will be removed in future versions. + */ + +#ifndef BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ + +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GNUC__) +#pragma message "Boost.Log: This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead." +#elif defined(_MSC_VER) +#pragma message("Boost.Log: This header is deprecated, use boost/utility/explicit_operator_bool.hpp instead.") +#endif + +/*! + * \brief The macro defines an explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement <tt>operator!</tt>, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_LOG_EXPLICIT_OPERATOR_BOOL()\ + BOOST_EXPLICIT_OPERATOR_BOOL() + +#endif // BOOST_LOG_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ diff --git a/boost/log/utility/formatting_ostream.hpp b/boost/log/utility/formatting_ostream.hpp new file mode 100644 index 0000000000..a32df35c83 --- /dev/null +++ b/boost/log/utility/formatting_ostream.hpp @@ -0,0 +1,748 @@ +/* + * 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 formatting_ostream.hpp + * \author Andrey Semashev + * \date 11.07.2012 + * + * The header contains implementation of a string stream used for log record formatting. + */ + +#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_ + +#include <ostream> +#include <string> +#include <memory> +#include <locale> +#include <boost/utility/string_ref_fwd.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/attachable_sstream_buf.hpp> +#include <boost/log/detail/code_conversion.hpp> +#include <boost/log/utility/string_literal_fwd.hpp> +#include <boost/log/utility/formatting_ostream_fwd.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T, typename R > +struct enable_if_char_type {}; +template< typename R > +struct enable_if_char_type< char, R > { typedef R type; }; +template< typename R > +struct enable_if_char_type< wchar_t, R > { typedef R type; }; +#if !defined(BOOST_NO_CXX11_CHAR16_T) +template< typename R > +struct enable_if_char_type< char16_t, R > { typedef R type; }; +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) +template< typename R > +struct enable_if_char_type< char32_t, R > { typedef R type; }; +#endif + +} // namespace aux + +/*! + * \brief Stream wrapper for log records formatting. + * + * This stream wrapper is used by the library for log record formatting. It implements the standard string stream interface + * with a few differences: + * + * \li It does not derive from standard types <tt>std::basic_ostream</tt>, <tt>std::basic_ios</tt> and <tt>std::ios_base</tt>, + * although it tries to implement their interfaces closely. There are a few small differences, mostly regarding <tt>rdbuf</tt> + * and <tt>str</tt> signatures, as well as the supported insertion operator overloads. The actual wrapped stream can be accessed + * through the <tt>stream</tt> methods. + * \li By default, \c bool values are formatted using alphabetical representation rather than numeric. + * \li The stream supports writing strings of character types different from the stream character type. The stream will perform + * character code conversion as needed using the imbued locale. + * \li The stream operates on an external string object rather than on the embedded one. The string can be attached or detached + * from the stream dynamically. + * + * Although <tt>basic_formatting_ostream</tt> does not derive from <tt>std::basic_ostream</tt>, users are not required to add + * special overloads of \c operator<< for it since the stream will by default reuse the operators for <tt>std::basic_ostream</tt>. + * However, one can define special overloads of \c operator<< for <tt>basic_formatting_ostream</tt> if a certain type needs + * special formatting when output to log. + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +class basic_formatting_ostream +{ +public: + //! Character type + typedef CharT char_type; + //! Character traits + typedef TraitsT traits_type; + //! Memory allocator + typedef AllocatorT allocator_type; + //! Stream buffer type + typedef boost::log::aux::basic_ostringstreambuf< char_type, traits_type, allocator_type > streambuf_type; + //! Target string type + typedef typename streambuf_type::string_type string_type; + + //! Stream type + typedef std::basic_ostream< char_type, traits_type > ostream_type; + //! Stream position type + typedef typename ostream_type::pos_type pos_type; + //! Stream offset type + typedef typename ostream_type::off_type off_type; + //! Integer type for characters + typedef typename ostream_type::int_type int_type; + + typedef typename ostream_type::failure failure; + typedef typename ostream_type::fmtflags fmtflags; + typedef typename ostream_type::iostate iostate; + typedef typename ostream_type::openmode openmode; + typedef typename ostream_type::seekdir seekdir; + typedef typename ostream_type::Init Init; + + typedef typename ostream_type::event event; + typedef typename ostream_type::event_callback event_callback; + + class sentry : + public ostream_type::sentry + { + typedef typename ostream_type::sentry base_type; + + public: + explicit sentry(basic_formatting_ostream& strm) : base_type(strm.stream()) + { + } + + BOOST_DELETED_FUNCTION(sentry(sentry const&)) + BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&)) + }; + +private: + // Function types + typedef std::ios_base& (*ios_base_manip)(std::ios_base&); + typedef std::basic_ios< char_type, traits_type >& (*basic_ios_manip)(std::basic_ios< char_type, traits_type >&); + typedef ostream_type& (*stream_manip)(ostream_type&); + +public: + static BOOST_CONSTEXPR_OR_CONST fmtflags boolalpha = ostream_type::boolalpha; + static BOOST_CONSTEXPR_OR_CONST fmtflags dec = ostream_type::dec; + static BOOST_CONSTEXPR_OR_CONST fmtflags fixed = ostream_type::fixed; + static BOOST_CONSTEXPR_OR_CONST fmtflags hex = ostream_type::hex; + static BOOST_CONSTEXPR_OR_CONST fmtflags internal = ostream_type::internal; + static BOOST_CONSTEXPR_OR_CONST fmtflags left = ostream_type::left; + static BOOST_CONSTEXPR_OR_CONST fmtflags oct = ostream_type::oct; + static BOOST_CONSTEXPR_OR_CONST fmtflags right = ostream_type::right; + static BOOST_CONSTEXPR_OR_CONST fmtflags scientific = ostream_type::scientific; + static BOOST_CONSTEXPR_OR_CONST fmtflags showbase = ostream_type::showbase; + static BOOST_CONSTEXPR_OR_CONST fmtflags showpoint = ostream_type::showpoint; + static BOOST_CONSTEXPR_OR_CONST fmtflags skipws = ostream_type::skipws; + static BOOST_CONSTEXPR_OR_CONST fmtflags unitbuf = ostream_type::unitbuf; + static BOOST_CONSTEXPR_OR_CONST fmtflags uppercase = ostream_type::uppercase; + static BOOST_CONSTEXPR_OR_CONST fmtflags adjustfield = ostream_type::adjustfield; + static BOOST_CONSTEXPR_OR_CONST fmtflags basefield = ostream_type::basefield; + static BOOST_CONSTEXPR_OR_CONST fmtflags floatfield = ostream_type::floatfield; + + static BOOST_CONSTEXPR_OR_CONST iostate badbit = ostream_type::badbit; + static BOOST_CONSTEXPR_OR_CONST iostate eofbit = ostream_type::eofbit; + static BOOST_CONSTEXPR_OR_CONST iostate failbit = ostream_type::failbit; + static BOOST_CONSTEXPR_OR_CONST iostate goodbit = ostream_type::goodbit; + + static BOOST_CONSTEXPR_OR_CONST openmode app = ostream_type::app; + static BOOST_CONSTEXPR_OR_CONST openmode ate = ostream_type::ate; + static BOOST_CONSTEXPR_OR_CONST openmode binary = ostream_type::binary; + static BOOST_CONSTEXPR_OR_CONST openmode in = ostream_type::in; + static BOOST_CONSTEXPR_OR_CONST openmode out = ostream_type::out; + static BOOST_CONSTEXPR_OR_CONST openmode trunc = ostream_type::trunc; + + static BOOST_CONSTEXPR_OR_CONST seekdir beg = ostream_type::beg; + static BOOST_CONSTEXPR_OR_CONST seekdir cur = ostream_type::cur; + static BOOST_CONSTEXPR_OR_CONST seekdir end = ostream_type::end; + + static BOOST_CONSTEXPR_OR_CONST event erase_event = ostream_type::erase_event; + static BOOST_CONSTEXPR_OR_CONST event imbue_event = ostream_type::imbue_event; + static BOOST_CONSTEXPR_OR_CONST event copyfmt_event = ostream_type::copyfmt_event; + +private: + mutable streambuf_type m_streambuf; + ostream_type m_stream; + +public: + /*! + * Default constructor. Creates an empty record that is equivalent to the invalid record handle. + * The stream capability is not available after construction. + * + * \post <tt>!*this == true</tt> + */ + basic_formatting_ostream() : m_stream(&m_streambuf) + { + init_stream(); + } + + /*! + * Initializing constructor. Attaches the string to the constructed stream. + * The string will be used to store the formatted characters. + * + * \post <tt>!*this == false</tt> + * \param str The string buffer to attach. + */ + explicit basic_formatting_ostream(string_type& str) : + m_streambuf(str), + m_stream(&m_streambuf) + { + init_stream(); + } + + /*! + * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record. + */ + ~basic_formatting_ostream() + { + if (m_streambuf.storage()) + flush(); + } + + /*! + * Attaches the stream to the string. The string will be used to store the formatted characters. + * + * \param str The string buffer to attach. + */ + void attach(string_type& str) + { + m_streambuf.attach(str); + m_stream.clear(ostream_type::goodbit); + } + /*! + * Detaches the stream from the string. Any buffered data is flushed to the string. + */ + void detach() + { + m_streambuf.detach(); + m_stream.clear(ostream_type::badbit); + } + + /*! + * \returns Reference to the attached string. The string must be attached before calling this method. + */ + string_type const& str() const + { + string_type* storage = m_streambuf.storage(); + BOOST_ASSERT(storage != NULL); + + m_streambuf.pubsync(); + + return *storage; + } + + /*! + * \returns Reference to the wrapped stream + */ + ostream_type& stream() { return m_stream; } + + /*! + * \returns Reference to the wrapped stream + */ + ostream_type const& stream() const { return m_stream; } + + // std::ios_base method forwarders + fmtflags flags() const { return m_stream.flags(); } + fmtflags flags(fmtflags f) { return m_stream.flags(f); } + fmtflags setf(fmtflags f) { return m_stream.setf(f); } + fmtflags setf(fmtflags f, fmtflags mask) { return m_stream.setf(f, mask); } + void unsetf(fmtflags f) { m_stream.unsetf(f); } + + std::streamsize precision() const { return m_stream.precision(); } + std::streamsize precision(std::streamsize p) { return m_stream.precision(p); } + + std::streamsize width() const { return m_stream.width(); } + std::streamsize width(std::streamsize w) { return m_stream.width(w); } + + std::locale getloc() const { return m_stream.getloc(); } + std::locale imbue(std::locale const& loc) { return m_stream.imbue(loc); } + + static int xalloc() { return ostream_type::xalloc(); } + long& iword(int index) { return m_stream.iword(index); } + void*& pword(int index) { return m_stream.pword(index); } + + void register_callback(event_callback fn, int index) { m_stream.register_callback(fn, index); } + + static bool sync_with_stdio(bool sync = true) { return ostream_type::sync_with_stdio(sync); } + + // std::basic_ios method forwarders + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const { return !m_stream; } + + iostate rdstate() const { return m_stream.rdstate(); } + void clear(iostate state = goodbit) { m_stream.clear(state); } + void setstate(iostate state) { m_stream.setstate(state); } + bool good() const { return m_stream.good(); } + bool eof() const { return m_stream.eof(); } + bool fail() const { return m_stream.fail(); } + bool bad() const { return m_stream.bad(); } + + iostate exceptions() const { return m_stream.exceptions(); } + void exceptions(iostate s) { m_stream.exceptions(s); } + + ostream_type* tie() const { return m_stream.tie(); } + ostream_type* tie(ostream_type* strm) { return m_stream.tie(strm); } + + streambuf_type* rdbuf() const { return &m_streambuf; } + + basic_formatting_ostream& copyfmt(std::basic_ios< char_type, traits_type >& rhs) + { + m_stream.copyfmt(rhs); + return *this; + } + basic_formatting_ostream& copyfmt(basic_formatting_ostream& rhs) + { + m_stream.copyfmt(rhs.stream()); + return *this; + } + + char_type fill() const { return m_stream.fill(); } + char_type fill(char_type ch) { return m_stream.fill(ch); } + + char narrow(char_type ch, char def) const { return m_stream.narrow(ch, def); } + char_type widen(char ch) const { return m_stream.widen(ch); } + + // std::basic_ostream method forwarders + basic_formatting_ostream& flush() + { + m_stream.flush(); + return *this; + } + + pos_type tellp() { return m_stream.tellp(); } + basic_formatting_ostream& seekp(pos_type pos) + { + m_stream.seekp(pos); + return *this; + } + basic_formatting_ostream& seekp(off_type off, std::ios_base::seekdir dir) + { + m_stream.seekp(off, dir); + return *this; + } + + basic_formatting_ostream& put(char_type c) + { + m_stream.put(c); + return *this; + } + + template< typename OtherCharT > + typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + put(OtherCharT c) + { + write(&c, 1); + return *this; + } + + basic_formatting_ostream& write(const char_type* p, std::streamsize size) + { + m_stream.write(p, size); + return *this; + } + + template< typename OtherCharT > + typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + write(const OtherCharT* p, std::streamsize size) + { + sentry guard(*this); + if (guard) + { + m_stream.flush(); + + string_type* storage = m_streambuf.storage(); + aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc()); + } + + return *this; + } + + basic_formatting_ostream& operator<< (ios_base_manip manip) + { + m_stream << manip; + return *this; + } + basic_formatting_ostream& operator<< (basic_ios_manip manip) + { + m_stream << manip; + return *this; + } + basic_formatting_ostream& operator<< (stream_manip manip) + { + m_stream << manip; + return *this; + } + + basic_formatting_ostream& operator<< (char c) + { + return this->formatted_write(&c, 1); + } + basic_formatting_ostream& operator<< (const char* p) + { + return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p))); + } + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + basic_formatting_ostream& operator<< (wchar_t c) + { + return this->formatted_write(&c, 1); + } + basic_formatting_ostream& operator<< (const wchar_t* p) + { + return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p))); + } +#endif +#if !defined(BOOST_NO_CXX11_CHAR16_T) + basic_formatting_ostream& operator<< (char16_t c) + { + return this->formatted_write(&c, 1); + } + basic_formatting_ostream& operator<< (const char16_t* p) + { + return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p))); + } +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) + basic_formatting_ostream& operator<< (char32_t c) + { + return this->formatted_write(&c, 1); + } + basic_formatting_ostream& operator<< (const char32_t* p) + { + return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p))); + } +#endif + + basic_formatting_ostream& operator<< (bool value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (signed char value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (unsigned char value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (short value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (unsigned short value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (int value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (unsigned int value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (long value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (unsigned long value) + { + m_stream << value; + return *this; + } +#if !defined(BOOST_NO_LONG_LONG) + basic_formatting_ostream& operator<< (long long value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (unsigned long long value) + { + m_stream << value; + return *this; + } +#endif + + basic_formatting_ostream& operator<< (float value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (double value) + { + m_stream << value; + return *this; + } + basic_formatting_ostream& operator<< (long double value) + { + m_stream << value; + return *this; + } + + basic_formatting_ostream& operator<< (const void* value) + { + m_stream << value; + return *this; + } + + basic_formatting_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf) + { + m_stream << buf; + return *this; + } + + template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str) + { + return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size())); + } + + template< typename OtherCharT, typename OtherTraitsT > + friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type + operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str) + { + return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size())); + } + +private: + void init_stream() + { + m_stream.clear(m_streambuf.storage() ? ostream_type::goodbit : ostream_type::badbit); + m_stream.flags + ( + ostream_type::dec | + ostream_type::skipws | + ostream_type::boolalpha // this differs from the default stream flags but makes logs look better + ); + m_stream.width(0); + m_stream.precision(6); + m_stream.fill(static_cast< char_type >(' ')); + } + + basic_formatting_ostream& formatted_write(const char_type* p, std::streamsize size) + { + sentry guard(*this); + if (guard) + { + m_stream.flush(); + + if (m_stream.width() <= size) + m_streambuf.storage()->append(p, static_cast< std::size_t >(size)); + else + this->aligned_write(p, size); + + m_stream.width(0); + } + + return *this; + } + + template< typename OtherCharT > + basic_formatting_ostream& formatted_write(const OtherCharT* p, std::streamsize size) + { + sentry guard(*this); + if (guard) + { + m_stream.flush(); + + if (m_stream.width() <= size) + aux::code_convert(p, static_cast< std::size_t >(size), *m_streambuf.storage(), m_stream.getloc()); + else + this->aligned_write(p, size); + + m_stream.width(0); + } + + return *this; + } + + void aligned_write(const char_type* p, std::streamsize size); + + template< typename OtherCharT > + void aligned_write(const OtherCharT* p, std::streamsize size); + + //! Copy constructor (closed) + BOOST_DELETED_FUNCTION(basic_formatting_ostream(basic_formatting_ostream const& that)) + //! Assignment (closed) + BOOST_DELETED_FUNCTION(basic_formatting_ostream& operator= (basic_formatting_ostream const& that)) +}; + +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::boolalpha; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::dec; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fixed; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::hex; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::internal; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::left; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::oct; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::right; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::scientific; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showbase; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showpoint; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::skipws; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::unitbuf; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::uppercase; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::adjustfield; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::basefield; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::floatfield; + +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::badbit; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::eofbit; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::failbit; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::goodbit; + +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::app; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::ate; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::binary; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::in; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::out; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::trunc; + +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::beg; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::cur; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::end; + +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::erase_event; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::imbue_event; +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::copyfmt_event; + +template< typename CharT, typename TraitsT, typename AllocatorT > +void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const char_type* p, std::streamsize size) +{ + string_type* const storage = m_streambuf.storage(); + typename string_type::size_type const alignment_size = + static_cast< typename string_type::size_type >(m_stream.width() - size); + const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left; + if (align_left) + { + storage->append(p, static_cast< std::size_t >(size)); + storage->append(alignment_size, m_stream.fill()); + } + else + { + storage->append(alignment_size, m_stream.fill()); + storage->append(p, static_cast< std::size_t >(size)); + } +} + +template< typename CharT, typename TraitsT, typename AllocatorT > +template< typename OtherCharT > +void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const OtherCharT* p, std::streamsize size) +{ + string_type* const storage = m_streambuf.storage(); + typename string_type::size_type const alignment_size = + static_cast< typename string_type::size_type >(m_stream.width() - size); + const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left; + if (align_left) + { + aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc()); + storage->append(alignment_size, m_stream.fill()); + } + else + { + storage->append(alignment_size, m_stream.fill()); + aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc()); + } +} + +template< typename CharT, typename TraitsT, typename AllocatorT, typename T > +inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& +operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T const& value) +{ + strm.stream() << value; + return strm; +} + +template< typename CharT, typename TraitsT, typename AllocatorT, typename T > +inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& +operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T& value) +{ + strm.stream() << value; + return strm; +} + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename CharT, typename TraitsT, typename AllocatorT, typename T > +inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& +operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >&& strm, T const& value) +{ + static_cast< basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >(strm) << value; + return strm; +} + +template< typename CharT, typename TraitsT, typename AllocatorT, typename T > +inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& +operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >&& strm, T& value) +{ + static_cast< basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >(strm) << value; + return strm; +} + +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_ diff --git a/boost/log/utility/formatting_ostream_fwd.hpp b/boost/log/utility/formatting_ostream_fwd.hpp new file mode 100644 index 0000000000..ba9b6e18d5 --- /dev/null +++ b/boost/log/utility/formatting_ostream_fwd.hpp @@ -0,0 +1,51 @@ +/* + * 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 formatting_ostream_fwd.hpp + * \author Andrey Semashev + * \date 11.07.2012 + * + * The header contains forward declaration of a string stream used for log record formatting. + */ + +#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_ + +#include <string> +#include <memory> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief Stream for log records formatting + */ +template< + typename CharT, + typename TraitsT = std::char_traits< CharT >, + typename AllocatorT = std::allocator< CharT > +> +class basic_formatting_ostream; + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_formatting_ostream< char > formatting_ostream; +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_formatting_ostream< wchar_t > wformatting_ostream; +#endif + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_ diff --git a/boost/log/utility/functional.hpp b/boost/log/utility/functional.hpp new file mode 100644 index 0000000000..bc48619a01 --- /dev/null +++ b/boost/log/utility/functional.hpp @@ -0,0 +1,40 @@ +/* + * 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 functional.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header includes all functional helpers. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/utility/functional/logical.hpp> +#include <boost/log/utility/functional/in_range.hpp> +#include <boost/log/utility/functional/begins_with.hpp> +#include <boost/log/utility/functional/ends_with.hpp> +#include <boost/log/utility/functional/contains.hpp> +#include <boost/log/utility/functional/matches.hpp> + +#include <boost/log/utility/functional/nop.hpp> +#include <boost/log/utility/functional/bind_assign.hpp> +#include <boost/log/utility/functional/bind_output.hpp> +#include <boost/log/utility/functional/bind_to_log.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/utility/functional/fun_ref.hpp> +#include <boost/log/utility/functional/as_action.hpp> +#include <boost/log/utility/functional/save_result.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/as_action.hpp b/boost/log/utility/functional/as_action.hpp new file mode 100644 index 0000000000..a12cee250a --- /dev/null +++ b/boost/log/utility/functional/as_action.hpp @@ -0,0 +1,60 @@ +/* + * 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 as_action.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains function object adapter for compatibility with Boost.Spirit actions interface requirements. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Function object adapter for Boost.Spirit actions +template< typename FunT > +struct as_action_adapter +{ + typedef typename FunT::result_type result_type; + + BOOST_DEFAULTED_FUNCTION(as_action_adapter(), {}) + explicit as_action_adapter(FunT const& fun) : m_fun(fun) {} + + template< typename AttributeT, typename ContextT > + result_type operator() (AttributeT const& attr, ContextT const& ctx, bool& pass) const + { + return m_fun(attr); + } + +private: + FunT m_fun; +}; + +template< typename FunT > +BOOST_FORCEINLINE as_action_adapter< FunT > as_action(FunT const& fun) +{ + return as_action_adapter< FunT >(fun); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/begins_with.hpp b/boost/log/utility/functional/begins_with.hpp new file mode 100644 index 0000000000..b8e91baa7e --- /dev/null +++ b/boost/log/utility/functional/begins_with.hpp @@ -0,0 +1,57 @@ +/* + * 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 begins_with.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a predicate for checking if the provided string begins with a substring. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The \c begins_with functor +struct begins_with_fun +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + typedef typename T::const_iterator left_iterator; + typedef typename U::const_iterator right_iterator; + + left_iterator left_it = left.begin(), left_end = left.end(); + right_iterator right_it = right.begin(), right_end = right.end(); + for (; left_it != left_end && right_it != right_end; ++left_it, ++right_it) + { + if (*left_it != *right_it) + break; + } + return right_it == right_end; + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/bind.hpp b/boost/log/utility/functional/bind.hpp new file mode 100644 index 0000000000..cdc79cba57 --- /dev/null +++ b/boost/log/utility/functional/bind.hpp @@ -0,0 +1,237 @@ +/* + * 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 bind.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains function object adapters. + * This is a lightweight alternative to what Boost.Phoenix and Boost.Bind provides. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_ + +#include <boost/type_traits/remove_cv.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +struct make_arg_type +{ + typedef T const& type; +}; + +template< typename T > +struct make_arg_type< T& > +{ + typedef T& type; +}; + +} // namespace aux + +//! First argument binder +template< typename FunT, typename FirstArgT > +struct binder1st : + private FunT +{ + typedef typename FunT::result_type result_type; + + binder1st(FunT const& fun, typename aux::make_arg_type< FirstArgT >::type arg) : FunT(fun), m_arg(arg) {} + + result_type operator() () const + { + return FunT::operator()(m_arg); + } + + template< typename T0 > + result_type operator() (T0 const& arg0) const + { + return FunT::operator()(m_arg, arg0); + } + + template< typename T0, typename T1 > + result_type operator() (T0 const& arg0, T1 const& arg1) const + { + return FunT::operator()(m_arg, arg0, arg1); + } + +private: + FirstArgT m_arg; +}; + +//! First argument binder +template< typename FunT, typename FirstArgT > +struct binder1st< FunT&, FirstArgT > +{ + typedef typename remove_cv< FunT >::type::result_type result_type; + + binder1st(FunT& fun, typename aux::make_arg_type< FirstArgT >::type arg) : m_fun(fun), m_arg(arg) {} + + result_type operator() () const + { + return m_fun(m_arg); + } + + template< typename T0 > + result_type operator() (T0 const& arg0) const + { + return m_fun(m_arg, arg0); + } + + template< typename T0, typename T1 > + result_type operator() (T0 const& arg0, T1 const& arg1) const + { + return m_fun(m_arg, arg0, arg1); + } + +private: + FunT& m_fun; + FirstArgT m_arg; +}; + +template< typename FunT, typename FirstArgT > +BOOST_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT const& arg) +{ + return binder1st< FunT, FirstArgT >(fun, arg); +} + +template< typename FunT, typename FirstArgT > +BOOST_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT& arg) +{ + return binder1st< FunT, FirstArgT >(fun, arg); +} + +//! Second argument binder +template< typename FunT, typename SecondArgT > +struct binder2nd : + private FunT +{ + typedef typename FunT::result_type result_type; + + binder2nd(FunT const& fun, typename aux::make_arg_type< SecondArgT >::type arg) : FunT(fun), m_arg(arg) {} + + template< typename T > + result_type operator() (T const& arg) const + { + return FunT::operator()(arg, m_arg); + } + + template< typename T0, typename T1 > + result_type operator() (T0 const& arg0, T1 const& arg1) const + { + return FunT::operator()(arg0, m_arg, arg1); + } + +private: + SecondArgT m_arg; +}; + +//! Second argument binder +template< typename FunT, typename SecondArgT > +struct binder2nd< FunT&, SecondArgT > +{ + typedef typename remove_cv< FunT >::type::result_type result_type; + + binder2nd(FunT& fun, typename aux::make_arg_type< SecondArgT >::type arg) : m_fun(fun), m_arg(arg) {} + + template< typename T > + result_type operator() (T const& arg) const + { + return m_fun(arg, m_arg); + } + + template< typename T0, typename T1 > + result_type operator() (T0 const& arg0, T1 const& arg1) const + { + return m_fun(arg0, m_arg, arg1); + } + +private: + FunT& m_fun; + SecondArgT m_arg; +}; + +template< typename FunT, typename SecondArgT > +BOOST_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT const& arg) +{ + return binder2nd< FunT, SecondArgT >(fun, arg); +} + +template< typename FunT, typename SecondArgT > +BOOST_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT& arg) +{ + return binder2nd< FunT, SecondArgT >(fun, arg); +} + +//! Third argument binder +template< typename FunT, typename ThirdArgT > +struct binder3rd : + private FunT +{ + typedef typename FunT::result_type result_type; + + binder3rd(FunT const& fun, typename aux::make_arg_type< ThirdArgT >::type arg) : FunT(fun), m_arg(arg) {} + + template< typename T0, typename T1 > + result_type operator() (T0 const& arg0, T1 const& arg1) const + { + return FunT::operator()(arg0, arg1, m_arg); + } + +private: + ThirdArgT m_arg; +}; + +//! Third argument binder +template< typename FunT, typename ThirdArgT > +struct binder3rd< FunT&, ThirdArgT > +{ + typedef typename remove_cv< FunT >::type::result_type result_type; + + binder3rd(FunT& fun, typename aux::make_arg_type< ThirdArgT >::type arg) : m_fun(fun), m_arg(arg) {} + + template< typename T0, typename T1 > + result_type operator() (T0 const& arg0, T1 const& arg1) const + { + return m_fun(arg0, arg1, m_arg); + } + +private: + FunT& m_fun; + ThirdArgT m_arg; +}; + +template< typename FunT, typename ThirdArgT > +BOOST_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT const& arg) +{ + return binder3rd< FunT, ThirdArgT >(fun, arg); +} + +template< typename FunT, typename ThirdArgT > +BOOST_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT& arg) +{ + return binder3rd< FunT, ThirdArgT >(fun, arg); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/bind_assign.hpp b/boost/log/utility/functional/bind_assign.hpp new file mode 100644 index 0000000000..acfad9426e --- /dev/null +++ b/boost/log/utility/functional/bind_assign.hpp @@ -0,0 +1,55 @@ +/* + * 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 bind_assign.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a function object that assigns the received value to the bound object. + * This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The function object that assigns its second operand to the first one +struct assign_fun +{ + typedef void result_type; + + template< typename LeftT, typename RightT > + void operator() (LeftT& assignee, RightT const& val) const + { + assignee = val; + } +}; + +template< typename AssigneeT > +BOOST_FORCEINLINE binder1st< assign_fun, AssigneeT& > bind_assign(AssigneeT& assignee) +{ + return binder1st< assign_fun, AssigneeT& >(assign_fun(), assignee); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/bind_output.hpp b/boost/log/utility/functional/bind_output.hpp new file mode 100644 index 0000000000..19cd88b947 --- /dev/null +++ b/boost/log/utility/functional/bind_output.hpp @@ -0,0 +1,55 @@ +/* + * 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 bind_output.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a function object that puts the received value to the bound stream. + * This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The function object that outputs its second operand to the first one +struct output_fun +{ + typedef void result_type; + + template< typename StreamT, typename T > + void operator() (StreamT& strm, T const& val) const + { + strm << val; + } +}; + +template< typename StreamT > +BOOST_FORCEINLINE binder1st< output_fun, StreamT& > bind_output(StreamT& strm) +{ + return binder1st< output_fun, StreamT& >(output_fun(), strm); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/bind_to_log.hpp b/boost/log/utility/functional/bind_to_log.hpp new file mode 100644 index 0000000000..9131d6658f --- /dev/null +++ b/boost/log/utility/functional/bind_to_log.hpp @@ -0,0 +1,76 @@ +/* + * 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 bind_to_log.hpp + * \author Andrey Semashev + * \date 06.11.2012 + * + * This header contains a function object that puts the received value to the bound stream using the \c to_log manipulator. + * This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/utility/manipulators/to_log.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The function object that outputs its second operand to the first one +template< typename TagT = void > +struct to_log_fun +{ + typedef void result_type; + + template< typename StreamT, typename T > + void operator() (StreamT& strm, T const& val) const + { + strm << boost::log::to_log< TagT >(val); + } +}; + +//! The function object that outputs its second operand to the first one +template< > +struct to_log_fun< void > +{ + typedef void result_type; + + template< typename StreamT, typename T > + void operator() (StreamT& strm, T const& val) const + { + strm << boost::log::to_log(val); + } +}; + +template< typename StreamT > +BOOST_FORCEINLINE binder1st< to_log_fun< >, StreamT& > bind_to_log(StreamT& strm) +{ + return binder1st< to_log_fun< >, StreamT& >(to_log_fun< >(), strm); +} + +template< typename TagT, typename StreamT > +BOOST_FORCEINLINE binder1st< to_log_fun< TagT >, StreamT& > bind_to_log(StreamT& strm) +{ + return binder1st< to_log_fun< TagT >, StreamT& >(to_log_fun< TagT >(), strm); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/contains.hpp b/boost/log/utility/functional/contains.hpp new file mode 100644 index 0000000000..84b6cd3d53 --- /dev/null +++ b/boost/log/utility/functional/contains.hpp @@ -0,0 +1,69 @@ +/* + * 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 contains.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a predicate for checking if the provided string contains a substring. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The \c contains functor +struct contains_fun +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + typedef typename T::const_iterator left_iterator; + typedef typename U::const_iterator right_iterator; + + typename U::size_type const right_size = right.size(); + if (left.size() >= right_size) + { + const left_iterator search_end = left.end() - right_size + 1; + const right_iterator right_end = right.end(); + for (left_iterator it = left.begin(); it != search_end; ++it) + { + left_iterator left_it = it; + right_iterator right_it = right.begin(); + for (; right_it != right_end; ++left_it, ++right_it) + { + if (*left_it != *right_it) + break; + } + if (right_it == right_end) + return true; + } + } + + return false; + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/ends_with.hpp b/boost/log/utility/functional/ends_with.hpp new file mode 100644 index 0000000000..ddf6578a2e --- /dev/null +++ b/boost/log/utility/functional/ends_with.hpp @@ -0,0 +1,57 @@ +/* + * 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 ends_with.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a predicate for checking if the provided string ends with a substring. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The \c ends_with functor +struct ends_with_fun +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + typedef typename T::const_reverse_iterator left_iterator; + typedef typename U::const_reverse_iterator right_iterator; + + left_iterator left_it = left.rbegin(), left_end = left.rend(); + right_iterator right_it = right.rbegin(), right_end = right.rend(); + for (; left_it != left_end && right_it != right_end; ++left_it, ++right_it) + { + if (*left_it != *right_it) + break; + } + return right_it == right_end; + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/fun_ref.hpp b/boost/log/utility/functional/fun_ref.hpp new file mode 100644 index 0000000000..08e3c6ac95 --- /dev/null +++ b/boost/log/utility/functional/fun_ref.hpp @@ -0,0 +1,79 @@ +/* + * 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 fun_ref.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains function object reference adapter. The adapter stores a reference to external + * function object and forwards all calls to the referred function. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Reference wrapper for function objects +template< typename FunT > +struct function_reference_wrapper +{ + typedef typename FunT::result_type result_type; + + explicit function_reference_wrapper(FunT& fun) : m_Fun(fun) {} + + result_type operator() () const + { + return m_Fun(); + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename... ArgsT > + result_type operator() (ArgsT const&... args) const + { + return m_Fun(args...); + } +#else + template< typename T > + result_type operator() (T const& arg) const + { + return m_Fun(arg); + } + + template< typename T1, typename T2 > + result_type operator() (T1 const& arg1, T2 const& arg2) const + { + return m_Fun(arg1, arg2); + } +#endif + +private: + FunT& m_Fun; +}; + +template< typename FunT > +BOOST_FORCEINLINE function_reference_wrapper< FunT > fun_ref(FunT& fun) +{ + return function_reference_wrapper< FunT >(fun); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/in_range.hpp b/boost/log/utility/functional/in_range.hpp new file mode 100644 index 0000000000..3fe808a74a --- /dev/null +++ b/boost/log/utility/functional/in_range.hpp @@ -0,0 +1,63 @@ +/* + * 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 in_range.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a predicate for checking if the provided value is within a half-open range. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_ + +#include <utility> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/functional/logical.hpp> // make_common_integral_type +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The in_range functor +struct in_range_fun +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& value, std::pair< U, U > const& rng) const + { + return op(value, rng, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& value, std::pair< U, U > const& rng, mpl::false_ const&) + { + return (value >= rng.first && value < rng.second); + } + template< typename T, typename U > + static bool op(T const& value, std::pair< U, U > const& rng, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return (static_cast< common_integral_type >(value) >= static_cast< common_integral_type >(rng.first)) + && (static_cast< common_integral_type >(value) < static_cast< common_integral_type >(rng.second)); + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/logical.hpp b/boost/log/utility/functional/logical.hpp new file mode 100644 index 0000000000..92bd79705b --- /dev/null +++ b/boost/log/utility/functional/logical.hpp @@ -0,0 +1,225 @@ +/* + * 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 logical.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains logical predicates for value comparison, analogous to \c std::less, \c std::greater + * and others. The main difference from the standard equivalents is that the predicates defined in this + * header are not templates and therefore do not require a fixed argument type. Furthermore, both arguments + * may have different types, in which case the comparison is performed without type conversion. + * + * \note In case if arguments are integral, the conversion is performed according to the standard C++ rules + * in order to avoid warnings from the compiler. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_ + +#include <boost/mpl/if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/and.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_unsigned.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The trait creates a common integral type suitable for comparison. This is mostly to silence compiler warnings like 'signed/unsigned mismatch'. +template< typename T, typename U, unsigned int TSizeV = sizeof(T), unsigned int USizeV = sizeof(U), bool TSmallerThanU = (sizeof(T) < sizeof(U)) > +struct make_common_integral_type +{ + typedef T type; +}; + +//! Specialization for case when \c T is smaller than \c U +template< typename T, typename U, unsigned int TSizeV, unsigned int USizeV > +struct make_common_integral_type< T, U, TSizeV, USizeV, true > +{ + typedef U type; +}; + +//! Specialization for the case when both types have the same size +template< typename T, typename U, unsigned int SizeV > +struct make_common_integral_type< T, U, SizeV, SizeV, false > : + public mpl::if_< + is_unsigned< T >, + T, + U + > +{ +}; + +} // namespace aux + +//! Equality predicate +struct equal_to +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::false_ const&) + { + return (left == right); + } + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return static_cast< common_integral_type >(left) == static_cast< common_integral_type >(right); + } +}; + +//! Inequality predicate +struct not_equal_to +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::false_ const&) + { + return (left != right); + } + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return static_cast< common_integral_type >(left) != static_cast< common_integral_type >(right); + } +}; + +//! Less predicate +struct less +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::false_ const&) + { + return (left < right); + } + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return static_cast< common_integral_type >(left) < static_cast< common_integral_type >(right); + } +}; + +//! Greater predicate +struct greater +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::false_ const&) + { + return (left > right); + } + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return static_cast< common_integral_type >(left) > static_cast< common_integral_type >(right); + } +}; + +//! Less or equal predicate +struct less_equal +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::false_ const&) + { + return (left <= right); + } + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return static_cast< common_integral_type >(left) <= static_cast< common_integral_type >(right); + } +}; + +//! Greater or equal predicate +struct greater_equal +{ + typedef bool result_type; + + template< typename T, typename U > + bool operator() (T const& left, U const& right) const + { + return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type()); + } + +private: + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::false_ const&) + { + return (left >= right); + } + template< typename T, typename U > + static bool op(T const& left, U const& right, mpl::true_ const&) + { + typedef typename aux::make_common_integral_type< T, U >::type common_integral_type; + return static_cast< common_integral_type >(left) >= static_cast< common_integral_type >(right); + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/matches.hpp b/boost/log/utility/functional/matches.hpp new file mode 100644 index 0000000000..b530f1e964 --- /dev/null +++ b/boost/log/utility/functional/matches.hpp @@ -0,0 +1,66 @@ +/* + * 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 matches.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a predicate for checking if the provided string matches a regular expression. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits +template< typename ExpressionT, typename = void > +struct matching_expression_kind; + +//! The matching function implementation +template< typename ExpressionT, typename TagT = typename matching_expression_kind< ExpressionT >::type > +struct match_traits; + +} // namespace aux + +//! The regex matching functor +struct matches_fun +{ + typedef bool result_type; + + template< typename StringT, typename ExpressionT > + bool operator() (StringT const& str, ExpressionT const& expr) const + { + typedef aux::match_traits< ExpressionT > impl; + return impl::matches(str, expr); + } + template< typename StringT, typename ExpressionT, typename ArgT > + bool operator() (StringT const& str, ExpressionT const& expr, ArgT const& arg) const + { + typedef aux::match_traits< ExpressionT > impl; + return impl::matches(str, expr, arg); + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/nop.hpp b/boost/log/utility/functional/nop.hpp new file mode 100644 index 0000000000..0a6e310337 --- /dev/null +++ b/boost/log/utility/functional/nop.hpp @@ -0,0 +1,55 @@ +/* + * 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 nop.hpp + * \author Andrey Semashev + * \date 30.03.2008 + * + * This header contains a function object that does nothing. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! The function object that does nothing +struct nop +{ + typedef void result_type; + + void operator() () const BOOST_NOEXCEPT {} + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename... ArgsT > + void operator() (ArgsT const&...) const BOOST_NOEXCEPT {} +#else + template< typename T > + void operator() (T const&) const BOOST_NOEXCEPT {} + template< typename T1, typename T2 > + void operator() (T1 const&, T2 const&) const BOOST_NOEXCEPT {} + template< typename T1, typename T2, typename T3 > + void operator() (T1 const&, T2 const&, T3 const&) const BOOST_NOEXCEPT {} +#endif +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_ diff --git a/boost/log/utility/functional/save_result.hpp b/boost/log/utility/functional/save_result.hpp new file mode 100644 index 0000000000..d0b22fdff2 --- /dev/null +++ b/boost/log/utility/functional/save_result.hpp @@ -0,0 +1,60 @@ +/* + * 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 save_result.hpp + * \author Andrey Semashev + * \date 19.01.2013 + * + * This header contains function object adapter that saves the result of the adopted function to an external variable. + */ + +#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Function object wrapper for saving the adopted function object result +template< typename FunT, typename AssigneeT > +struct save_result_wrapper +{ + typedef void result_type; + + save_result_wrapper(FunT fun, AssigneeT& assignee) : m_fun(fun), m_assignee(assignee) {} + + template< typename ArgT > + result_type operator() (ArgT const& arg) const + { + m_assignee = m_fun(arg); + } + +private: + FunT m_fun; + AssigneeT& m_assignee; +}; + +template< typename FunT, typename AssigneeT > +BOOST_FORCEINLINE save_result_wrapper< FunT, AssigneeT > save_result(FunT const& fun, AssigneeT& assignee) +{ + return save_result_wrapper< FunT, AssigneeT >(fun, assignee); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_ diff --git a/boost/log/utility/intrusive_ref_counter.hpp b/boost/log/utility/intrusive_ref_counter.hpp new file mode 100644 index 0000000000..025c21ac81 --- /dev/null +++ b/boost/log/utility/intrusive_ref_counter.hpp @@ -0,0 +1,55 @@ +/* + * 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 intrusive_ref_counter.hpp + * \author Andrey Semashev + * \date 12.03.2009 + * + * This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead. The header is left for + * backward compatibility and will be removed in future versions. + */ + +#ifndef BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ + +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <boost/smart_ptr/intrusive_ref_counter.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GNUC__) +#pragma message "Boost.Log: This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead." +#elif defined(_MSC_VER) +#pragma message("Boost.Log: This header is deprecated, use boost/smart_ptr/intrusive_ref_counter.hpp instead.") +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +struct legacy_intrusive_ref_counter_root +{ + virtual ~legacy_intrusive_ref_counter_root() {} +}; + +} // namespace aux + +typedef boost::intrusive_ref_counter< aux::legacy_intrusive_ref_counter_root > intrusive_ref_counter; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ diff --git a/boost/log/utility/manipulators.hpp b/boost/log/utility/manipulators.hpp new file mode 100644 index 0000000000..cee1affd2a --- /dev/null +++ b/boost/log/utility/manipulators.hpp @@ -0,0 +1,28 @@ +/* + * 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 manipulators.hpp + * \author Andrey Semashev + * \date 06.11.2012 + * + * This header includes all manipulators. + */ + +#ifndef BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#include <boost/log/utility/manipulators/add_value.hpp> +#include <boost/log/utility/manipulators/to_log.hpp> +#include <boost/log/utility/manipulators/dump.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_ diff --git a/boost/log/utility/manipulators/add_value.hpp b/boost/log/utility/manipulators/add_value.hpp new file mode 100644 index 0000000000..8d4a7c610f --- /dev/null +++ b/boost/log/utility/manipulators/add_value.hpp @@ -0,0 +1,165 @@ +/* + * 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 add_value.hpp + * \author Andrey Semashev + * \date 26.11.2012 + * + * This header contains the \c add_value manipulator. + */ + +#ifndef BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_ + +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/embedded_string_type.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute_value_impl.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/sources/record_ostream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifdef _MSC_VER +#pragma warning(push) +// 'boost::log::v2s_mt_nt6::add_value_manip<RefT>::m_value' : reference member is initialized to a temporary that doesn't persist after the constructor exits +// This is intentional since the manipulator can be used with a temporary, which will be used before the streaming expression ends and it is destroyed. +#pragma warning(disable: 4413) +// returning address of local variable or temporary +// This warning refers to add_value_manip<RefT>::get_value() when RefT is an rvalue reference. We store the reference in the manipulator and we intend to return it as is. +#pragma warning(disable: 4172) +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Attribute value manipulator +template< typename RefT > +class add_value_manip +{ +public: + //! Stored reference type + typedef RefT reference_type; + //! Attribute value type + typedef typename remove_cv< typename remove_reference< reference_type >::type >::type value_type; + +private: + // The stored reference type is an lvalue reference since apparently different compilers (GCC and MSVC) have different quirks when rvalue references are stored as members. + // Additionally, MSVC (at least 11.0) has a bug which causes a dangling reference to be stored in the manipulator, if a scalar rvalue is passed to the add_value generator. + // To work around this problem we save the value inside the manipulator in this case. + typedef typename remove_reference< reference_type >::type& lvalue_reference_type; + + typedef typename mpl::if_< + is_scalar< value_type >, + value_type, + lvalue_reference_type + >::type stored_type; + + typedef typename mpl::if_< + is_scalar< value_type >, + value_type, + reference_type + >::type get_value_result_type; + +private: + //! Attribute value + stored_type m_value; + //! Attribute name + attribute_name m_name; + +public: + //! Initializing constructor + add_value_manip(attribute_name const& name, reference_type value) : m_value(static_cast< lvalue_reference_type >(value)), m_name(name) + { + } + + //! Returns attribute name + attribute_name get_name() const { return m_name; } + //! Returns attribute value + get_value_result_type get_value() const { return static_cast< get_value_result_type >(m_value); } +}; + +//! The operator attaches an attribute value to the log record +template< typename CharT, typename RefT > +inline basic_record_ostream< CharT >& operator<< (basic_record_ostream< CharT >& strm, add_value_manip< RefT > const& manip) +{ + typedef typename aux::make_embedded_string_type< typename add_value_manip< RefT >::value_type >::type value_type; + attribute_value value(new attributes::attribute_value_impl< value_type >(manip.get_value())); + strm.get_record().attribute_values().insert(manip.get_name(), value); + return strm; +} + +//! The function creates a manipulator that attaches an attribute value to a log record +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T > +inline add_value_manip< T&& > add_value(attribute_name const& name, T&& value) +{ + return add_value_manip< T&& >(name, static_cast< T&& >(value)); +} + +//! \overload +template< typename DescriptorT, template< typename > class ActorT > +inline add_value_manip< typename DescriptorT::value_type&& > +add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type&& value) +{ + typedef typename DescriptorT::value_type value_type; + return add_value_manip< value_type&& >(DescriptorT::get_name(), static_cast< value_type&& >(value)); +} + +//! \overload +template< typename DescriptorT, template< typename > class ActorT > +inline add_value_manip< typename DescriptorT::value_type& > +add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type& value) +{ + return add_value_manip< typename DescriptorT::value_type& >(DescriptorT::get_name(), value); +} + +//! \overload +template< typename DescriptorT, template< typename > class ActorT > +inline add_value_manip< typename DescriptorT::value_type const& > +add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value) +{ + return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value); +} + +#else // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T > +inline add_value_manip< T const& > add_value(attribute_name const& name, T const& value) +{ + return add_value_manip< T const& >(name, value); +} + +template< typename DescriptorT, template< typename > class ActorT > +inline add_value_manip< typename DescriptorT::value_type const& > +add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value) +{ + return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value); +} + +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_ diff --git a/boost/log/utility/manipulators/dump.hpp b/boost/log/utility/manipulators/dump.hpp new file mode 100644 index 0000000000..99b2fad749 --- /dev/null +++ b/boost/log/utility/manipulators/dump.hpp @@ -0,0 +1,231 @@ +/* + * 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 dump.hpp + * \author Andrey Semashev + * \date 03.05.2013 + * + * This header contains the \c dump output manipulator. + */ + +#ifndef BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_ + +#include <cstddef> +#include <iosfwd> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +typedef void dump_data_char_t(const void* data, std::size_t size, std::basic_ostream< char >& strm); +extern BOOST_LOG_API dump_data_char_t* dump_data_char; +BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char >& strm) +{ + (dump_data_char)(data, size, strm); +} + +typedef void dump_data_wchar_t(const void* data, std::size_t size, std::basic_ostream< wchar_t >& strm); +extern BOOST_LOG_API dump_data_wchar_t* dump_data_wchar; +BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< wchar_t >& strm) +{ + (dump_data_wchar)(data, size, strm); +} + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +typedef void dump_data_char16_t(const void* data, std::size_t size, std::basic_ostream< char16_t >& strm); +extern BOOST_LOG_API dump_data_char16_t* dump_data_char16; +BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char16_t >& strm) +{ + (dump_data_char16)(data, size, strm); +} +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +typedef void dump_data_char32_t(const void* data, std::size_t size, std::basic_ostream< char32_t >& strm); +extern BOOST_LOG_API dump_data_char32_t* dump_data_char32; +BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char32_t >& strm) +{ + (dump_data_char32)(data, size, strm); +} +#endif + +template< std::size_t SizeV, typename R > +struct enable_dump_size_based +{ +}; + +template< typename R > +struct enable_dump_size_based< 1u, R > +{ + typedef R type; +}; + +template< typename T, typename R > +struct enable_dump : + public enable_dump_size_based< sizeof(T), R > +{ +}; + +template< typename R > +struct enable_dump< void, R > +{ + typedef R type; +}; + +template< typename R > +struct enable_dump< const void, R > +{ + typedef R type; +}; + +template< typename R > +struct enable_dump< volatile void, R > +{ + typedef R type; +}; + +template< typename R > +struct enable_dump< const volatile void, R > +{ + typedef R type; +}; + +} // namespace aux + +/*! + * \brief Manipulator for printing binary representation of the data + */ +class dump_manip +{ +private: + //! Beginning of the data + const void* m_data; + //! Size of the data, in bytes + std::size_t m_size; + +public: + dump_manip(const void* data, std::size_t size) BOOST_NOEXCEPT : m_data(data), m_size(size) {} + dump_manip(dump_manip const& that) BOOST_NOEXCEPT : m_data(that.m_data), m_size(that.m_size) {} + + const void* get_data() const BOOST_NOEXCEPT { return m_data; } + std::size_t get_size() const BOOST_NOEXCEPT { return m_size; } +}; + +//! The operator outputs binary data to a stream +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, dump_manip const& manip) +{ + if (strm.good()) + aux::dump_data(manip.get_data(), manip.get_size(), strm); + + return strm; +} + +/*! + * \brief Manipulator for printing binary representation of the data with a size limit + */ +class bounded_dump_manip : + public dump_manip +{ +private: + //! Maximum size to output, in bytes + std::size_t m_max_size; + +public: + bounded_dump_manip(const void* data, std::size_t size, std::size_t max_size) BOOST_NOEXCEPT : dump_manip(data, size), m_max_size(max_size) {} + bounded_dump_manip(bounded_dump_manip const& that) BOOST_NOEXCEPT : dump_manip(static_cast< dump_manip const& >(that)), m_max_size(that.m_max_size) {} + + std::size_t get_max_size() const BOOST_NOEXCEPT { return m_max_size; } +}; + +//! The operator outputs binary data to a stream +template< typename CharT, typename TraitsT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, bounded_dump_manip const& manip) +{ + if (strm.good()) + { + const std::size_t size = manip.get_size(), max_size = manip.get_max_size(); + if (max_size >= size) + { + aux::dump_data(manip.get_data(), size, strm); + } + else + { + aux::dump_data(manip.get_data(), max_size, strm); + strm << " and " << (size - max_size) << " bytes more"; + } + } + + return strm; +} + +/*! + * \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form + * \param data The pointer to the beginning of the region + * \param size The size of the region, in bytes + * \return The manipulator that is to be put to a stream + */ +template< typename T > +inline typename aux::enable_dump< T, dump_manip >::type dump(T* data, std::size_t size) BOOST_NOEXCEPT +{ + return dump_manip((const void*)data, size); +} + +/*! + * \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form + * \param data The pointer to the beginning of the array + * \param count The size of the region, in number of \c T elements + * \return The manipulator that is to be put to a stream + */ +template< typename T > +inline dump_manip dump_elements(T* data, std::size_t count) BOOST_NOEXCEPT +{ + return dump_manip((const void*)data, count * sizeof(T)); +} + +/*! + * \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form + * \param data The pointer to the beginning of the region + * \param size The size of the region, in bytes + * \params max_size The maximum number of bytes of the region to output + * \return The manipulator that is to be put to a stream + */ +template< typename T > +inline typename aux::enable_dump< T, bounded_dump_manip >::type dump(T* data, std::size_t size, std::size_t max_size) BOOST_NOEXCEPT +{ + return bounded_dump_manip((const void*)data, size, max_size); +} + +/*! + * \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form + * \param data The pointer to the beginning of the array + * \param count The size of the region, in number of \c T elements + * \params max_count The maximum number of elements to output + * \return The manipulator that is to be put to a stream + */ +template< typename T > +inline bounded_dump_manip dump_elements(T* data, std::size_t count, std::size_t max_count) BOOST_NOEXCEPT +{ + return bounded_dump_manip((const void*)data, count * sizeof(T), max_count * sizeof(T)); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_ diff --git a/boost/log/utility/manipulators/to_log.hpp b/boost/log/utility/manipulators/to_log.hpp new file mode 100644 index 0000000000..51e96f5bc1 --- /dev/null +++ b/boost/log/utility/manipulators/to_log.hpp @@ -0,0 +1,87 @@ +/* + * 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 to_log.hpp + * \author Andrey Semashev + * \date 06.11.2012 + * + * This header contains the \c to_log output manipulator. + */ + +#ifndef BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/mpl/bool.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/formatting_ostream_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief Generic manipulator for customizing output to log + */ +template< typename T, typename TagT = void > +class to_log_manip +{ +public: + //! Output value type + typedef T value_type; + //! Value tag type + typedef TagT tag_type; + +private: + //! Reference to the value + value_type const& m_value; + +public: + explicit to_log_manip(value_type const& value) : m_value(value) {} + to_log_manip(to_log_manip const& that) : m_value(that.m_value) {} + + value_type const& get() const { return m_value; } +}; + +template< typename CharT, typename TraitsT, typename T, typename TagT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, to_log_manip< T, TagT > manip) +{ + strm << manip.get(); + return strm; +} + +template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT > +inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, to_log_manip< T, TagT > manip) +{ + strm << manip.get(); + return strm; +} + +template< typename T > +inline to_log_manip< T > to_log(T const& value) +{ + return to_log_manip< T >(value); +} + +template< typename TagT, typename T > +inline to_log_manip< T, TagT > to_log(T const& value) +{ + return to_log_manip< T, TagT >(value); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_ diff --git a/boost/log/utility/once_block.hpp b/boost/log/utility/once_block.hpp new file mode 100644 index 0000000000..e52f3d1738 --- /dev/null +++ b/boost/log/utility/once_block.hpp @@ -0,0 +1,196 @@ +/* + * 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 once_block.hpp + * \author Andrey Semashev + * \date 23.06.2010 + * + * \brief The header defines classes and macros for once-blocks. + */ + +#ifndef BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/unique_identifier_name.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief A flag to detect if a code block has already been executed. + * + * This structure should be used in conjunction with the \c BOOST_LOG_ONCE_BLOCK_FLAG + * macro. Usage example: + * + * <code> + * once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT; + * + * void foo() + * { + * BOOST_LOG_ONCE_BLOCK_FLAG(flag) + * { + * puts("Hello, world once!"); + * } + * } + * </code> + */ +struct once_block_flag +{ +#ifndef BOOST_LOG_DOXYGEN_PASS + // Do not use, implementation detail + enum + { + uninitialized = 0, // this must be zero, so that zero-initialized once_block_flag is equivalent to the one initialized with uninitialized + being_initialized, + initialized + }; + unsigned char status; +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +/*! + * \def BOOST_LOG_ONCE_BLOCK_INIT + * + * The static initializer for \c once_block_flag. + */ +#define BOOST_LOG_ONCE_BLOCK_INIT { boost::log::once_block_flag::uninitialized } + +namespace aux { + +class once_block_sentry +{ +private: + once_block_flag& m_flag; + +public: + explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f) + { + } + + ~once_block_sentry() BOOST_NOEXCEPT + { + if (m_flag.status != once_block_flag::initialized) + rollback(); + } + + bool executed() const BOOST_NOEXCEPT + { + return (m_flag.status == once_block_flag::initialized || enter_once_block()); + } + + BOOST_LOG_API void commit() BOOST_NOEXCEPT; + +private: + BOOST_LOG_API bool enter_once_block() const BOOST_NOEXCEPT; + BOOST_LOG_API void rollback() BOOST_NOEXCEPT; + + // Non-copyable, non-assignable + BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&)) + BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#else // BOOST_LOG_NO_THREADS + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +struct once_block_flag +{ + bool status; +}; + +#define BOOST_LOG_ONCE_BLOCK_INIT { false } + +namespace aux { + +class once_block_sentry +{ +private: + once_block_flag& m_flag; + +public: + explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f) + { + } + + bool executed() const BOOST_NOEXCEPT + { + return m_flag.status; + } + + void commit() BOOST_NOEXCEPT + { + m_flag.status = true; + } + + // Non-copyable, non-assignable + BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&)) + BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_NO_THREADS + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)\ + for (boost::log::aux::once_block_sentry sentry_var((flag_var));\ + BOOST_UNLIKELY(!sentry_var.executed()); sentry_var.commit()) + +// NOTE: flag_var deliberately doesn't have an initializer so that it is zero-initialized at the static initialization stage +#define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\ + static boost::log::once_block_flag flag_var;\ + BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var) + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \def BOOST_LOG_ONCE_BLOCK_FLAG(flag_var) + * + * Begins a code block to be executed only once, with protection against thread concurrency. + * User has to provide the flag variable that controls whether the block has already + * been executed. + */ +#define BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)\ + BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(\ + flag_var,\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_)) + +/*! + * \def BOOST_LOG_ONCE_BLOCK() + * + * Begins a code block to be executed only once, with protection against thread concurrency. + */ +#define BOOST_LOG_ONCE_BLOCK()\ + BOOST_LOG_ONCE_BLOCK_INTERNAL(\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_flag_),\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_)) + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_ diff --git a/boost/log/utility/record_ordering.hpp b/boost/log/utility/record_ordering.hpp new file mode 100644 index 0000000000..bed3b80280 --- /dev/null +++ b/boost/log/utility/record_ordering.hpp @@ -0,0 +1,229 @@ +/* + * 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 <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/function_traits.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/utility/functional/logical.hpp> +#include <boost/log/utility/functional/nop.hpp> +#include <boost/log/detail/header.hpp> + +#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 <tt>const void*</tt> 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 <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_ diff --git a/boost/log/utility/setup.hpp b/boost/log/utility/setup.hpp new file mode 100644 index 0000000000..135d7dc33c --- /dev/null +++ b/boost/log/utility/setup.hpp @@ -0,0 +1,37 @@ +/* + * 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 setup.hpp + * \author Andrey Semashev + * \date 16.02.2013 + * + * This header includes all library setup helpers. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_ + +#include <boost/log/detail/setup_config.hpp> + +#include <boost/log/utility/setup/common_attributes.hpp> + +#include <boost/log/utility/setup/console.hpp> +#include <boost/log/utility/setup/file.hpp> + +#include <boost/log/utility/setup/from_settings.hpp> +#include <boost/log/utility/setup/from_stream.hpp> + +#include <boost/log/utility/setup/settings.hpp> +#include <boost/log/utility/setup/settings_parser.hpp> +#include <boost/log/utility/setup/filter_parser.hpp> +#include <boost/log/utility/setup/formatter_parser.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/common_attributes.hpp b/boost/log/utility/setup/common_attributes.hpp new file mode 100644 index 0000000000..f2545e963c --- /dev/null +++ b/boost/log/utility/setup/common_attributes.hpp @@ -0,0 +1,76 @@ +/* + * 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 common_attributes.hpp + * \author Andrey Semashev + * \date 16.05.2008 + * + * The header contains implementation of convenience functions for registering commonly used attributes. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_ + +#include <iostream> +#include <boost/log/detail/config.hpp> +#include <boost/log/core/core.hpp> +#include <boost/log/attributes/clock.hpp> +#include <boost/log/attributes/counter.hpp> +#include <boost/log/attributes/current_process_id.hpp> +#if !defined(BOOST_LOG_NO_THREADS) +#include <boost/log/attributes/current_thread_id.hpp> +#endif +#include <boost/log/detail/default_attribute_names.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief Simple attribute initialization routine + * + * The function adds commonly used attributes to the logging system. Specifically, the following + * attributes are registered globally: + * + * \li LineID - logging records counter with value type <tt>unsigned int</tt> + * \li TimeStamp - local time generator with value type <tt>boost::posix_time::ptime</tt> + * \li ProcessID - current process identifier with value type + * <tt>attributes::current_process_id::value_type</tt> + * \li ThreadID - in multithreaded builds, current thread identifier with + * value type <tt>attributes::current_thread_id::value_type</tt> + */ +inline void add_common_attributes() +{ + shared_ptr< core > pCore = core::get(); + pCore->add_global_attribute( + aux::default_attribute_names::line_id(), + attributes::counter< unsigned int >(1)); + pCore->add_global_attribute( + aux::default_attribute_names::timestamp(), + attributes::local_clock()); + pCore->add_global_attribute( + aux::default_attribute_names::process_id(), + attributes::current_process_id()); +#if !defined(BOOST_LOG_NO_THREADS) + pCore->add_global_attribute( + aux::default_attribute_names::thread_id(), + attributes::current_thread_id()); +#endif +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/console.hpp b/boost/log/utility/setup/console.hpp new file mode 100644 index 0000000000..fadde4e9b6 --- /dev/null +++ b/boost/log/utility/setup/console.hpp @@ -0,0 +1,243 @@ +/* + * 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 console.hpp + * \author Andrey Semashev + * \date 16.05.2008 + * + * The header contains implementation of convenience functions for enabling logging to console. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_ + +#include <iostream> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/core/null_deleter.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/sink_init_helpers.hpp> +#ifndef BOOST_LOG_NO_THREADS +#include <boost/log/sinks/sync_frontend.hpp> +#else +#include <boost/log/sinks/unlocked_frontend.hpp> +#endif +#include <boost/log/sinks/text_ostream_backend.hpp> +#include <boost/log/keywords/format.hpp> +#include <boost/log/keywords/filter.hpp> +#include <boost/log/keywords/auto_flush.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + + +#ifndef BOOST_LOG_DOXYGEN_PASS +#ifndef BOOST_LOG_NO_THREADS +#define BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL sinks::synchronous_sink +#else +#define BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL sinks::unlocked_sink +#endif +#endif // BOOST_LOG_DOXYGEN_PASS + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +// The function creates and initializes the sink +template< typename CharT, typename ArgsT > +shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(std::basic_ostream< CharT >& strm, ArgsT const& args) +{ + shared_ptr< std::basic_ostream< CharT > > pStream(&strm, boost::null_deleter()); + + typedef sinks::basic_text_ostream_backend< CharT > backend_t; + shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >(); + + pBackend->add_stream(pStream); + pBackend->auto_flush(args[keywords::auto_flush | false]); + + typedef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< backend_t > sink_t; + shared_ptr< sink_t > pSink = boost::make_shared< sink_t >(pBackend); + + aux::setup_filter(*pSink, args, + typename is_void< typename parameter::binding< ArgsT, keywords::tag::filter, void >::type >::type()); + + aux::setup_formatter(*pSink, args, + typename is_void< typename parameter::binding< ArgsT, keywords::tag::format, void >::type >::type()); + + core::get()->add_sink(pSink); + + return pSink; +} + +template< typename CharT > +struct default_console_stream; + +#ifdef BOOST_LOG_USE_CHAR +template< > +struct default_console_stream< char > +{ + static std::ostream& get() { return std::clog; } +}; +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T +template< > +struct default_console_stream< wchar_t > +{ + static std::wostream& get() { return std::wclog; } +}; +#endif // BOOST_LOG_USE_WCHAR_T + +} // namespace aux + +#ifndef BOOST_LOG_DOXYGEN_PASS + +template< typename CharT > +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log() +{ + return aux::add_console_log( + aux::default_console_stream< CharT >::get(), keywords::auto_flush = false); +} + + +template< typename CharT > +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(std::basic_ostream< CharT >& strm) +{ + return aux::add_console_log(strm, keywords::auto_flush = false); +} + +template< typename CharT, typename ArgT1 > +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1) +{ + return aux::add_console_log(strm, arg1); +} + +template< typename CharT, typename ArgT1, typename ArgT2 > +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2) +{ + return aux::add_console_log(strm, (arg1, arg2)); +} + +template< typename CharT, typename ArgT1, typename ArgT2, typename ArgT3 > +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3) +{ + return aux::add_console_log(strm, (arg1, arg2, arg3)); +} + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * The function constructs sink for the specified console stream and adds it to the core + * + * \param strm One of the standard console streams: <tt>std::cout</tt>, <tt>std::cerr</tt> or <tt>std::clog</tt> + * (or the corresponding wide-character analogues). + * \param args Optional additional named arguments for the sink initialization. The following arguments are supported: + * \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter, + * or a filter lambda expression. + * \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter, + * or a formatter lambda expression (either streaming or Boost.Format-like notation). + * \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the stream + * after each written record. + * \return Pointer to the constructed sink. + */ +template< typename CharT, typename... ArgsT > +shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(std::basic_ostream< CharT >& strm, ArgsT... const& args); + +/*! + * Equivalent to: <tt>add_console_log(std::clog);</tt> or <tt>add_console_log(std::wclog);</tt>, + * depending on the \c CharT type. + * + * \overload + */ +template< typename CharT, typename... ArgsT > +shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::basic_text_ostream_backend< CharT > + > +> add_console_log(ArgsT... const& args); + +#endif // BOOST_LOG_DOXYGEN_PASS + +#ifdef BOOST_LOG_USE_CHAR + +/*! + * The function constructs sink for the <tt>std::clog</tt> stream and adds it to the core + * + * \overload + * + * \return Pointer to the constructed sink. + */ +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::text_ostream_backend + > +> add_console_log() +{ + return add_console_log(std::clog); +} + +#endif // BOOST_LOG_USE_CHAR + +#ifdef BOOST_LOG_USE_WCHAR_T + +/*! + * The function constructs sink for the <tt>std::wclog</tt> stream and adds it to the core + * + * \return Pointer to the constructed sink. + */ +inline shared_ptr< + BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< + sinks::wtext_ostream_backend + > +> wadd_console_log() +{ + return add_console_log(std::wclog); +} + +#endif // BOOST_LOG_USE_WCHAR_T + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#undef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/file.hpp b/boost/log/utility/setup/file.hpp new file mode 100644 index 0000000000..12e9f0bc30 --- /dev/null +++ b/boost/log/utility/setup/file.hpp @@ -0,0 +1,166 @@ +/* + * 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 file.hpp + * \author Andrey Semashev + * \date 16.05.2008 + * + * The header contains implementation of convenience functions for enabling logging to a file. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_ + +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/parameter/parameters.hpp> // for is_named_argument +#include <boost/preprocessor/comparison/greater.hpp> +#include <boost/preprocessor/punctuation/comma_if.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_shifted_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/sink_init_helpers.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/core/core.hpp> +#ifndef BOOST_LOG_NO_THREADS +#include <boost/log/sinks/sync_frontend.hpp> +#else +#include <boost/log/sinks/unlocked_frontend.hpp> +#endif +#include <boost/log/sinks/text_file_backend.hpp> +#include <boost/log/keywords/scan_method.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_DOXYGEN_PASS +#ifndef BOOST_LOG_NO_THREADS +#define BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL sinks::synchronous_sink +#else +#define BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL sinks::unlocked_sink +#endif +#endif // BOOST_LOG_DOXYGEN_PASS + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The function creates a file collector according to the specified arguments +template< typename ArgsT > +inline shared_ptr< sinks::file::collector > setup_file_collector(ArgsT const&, mpl::true_ const&) +{ + return shared_ptr< sinks::file::collector >(); +} +template< typename ArgsT > +inline shared_ptr< sinks::file::collector > setup_file_collector(ArgsT const& args, mpl::false_ const&) +{ + return sinks::file::make_collector(args); +} + +//! The function constructs the sink and adds it to the core +template< typename ArgsT > +shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT const& args) +{ + typedef sinks::text_file_backend backend_t; + shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >(args); + + shared_ptr< sinks::file::collector > pCollector = aux::setup_file_collector(args, + typename is_void< typename parameter::binding< ArgsT, keywords::tag::target, void >::type >::type()); + if (pCollector) + { + pBackend->set_file_collector(pCollector); + pBackend->scan_for_files(args[keywords::scan_method | sinks::file::scan_matching]); + } + + shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< backend_t > > pSink = + boost::make_shared< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< backend_t > >(pBackend); + + aux::setup_filter(*pSink, args, + typename is_void< typename parameter::binding< ArgsT, keywords::tag::filter, void >::type >::type()); + + aux::setup_formatter(*pSink, args, + typename is_void< typename parameter::binding< ArgsT, keywords::tag::format, void >::type >::type()); + + core::get()->add_sink(pSink); + + return pSink; +} + +//! The function wraps the argument into a file_name named argument, if needed +template< typename T > +inline T const& wrap_file_name(T const& arg, mpl::true_) +{ + return arg; +} +template< typename T > +inline typename parameter::aux::tag< keywords::tag::file_name, T const >::type +wrap_file_name(T const& arg, mpl::false_) +{ + return keywords::file_name = arg; +} + +} // namespace aux + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL(z, n, data)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + inline shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\ + {\ + return aux::add_file_log((\ + aux::wrap_file_name(arg0, typename parameter::aux::is_named_argument< T0 >::type())\ + BOOST_PP_COMMA_IF(BOOST_PP_GREATER(n, 1))\ + BOOST_PP_ENUM_SHIFTED_PARAMS(n, arg)\ + ));\ + } + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL, ~) + +#undef BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL + +#else // BOOST_LOG_DOXYGEN_PASS + +/*! + * The function initializes the logging library to write logs to a file stream. + * + * \param args A number of named arguments. The following parameters are supported: + * \li \c file_name The file name or its pattern. This parameter is mandatory. + * \li \c open_mode The mask that describes the open mode for the file. See <tt>std::ios_base::openmode</tt>. + * \li \c rotation_size The size of the file at which rotation should occur. See <tt>basic_text_file_backend</tt>. + * \li \c time_based_rotation The predicate for time-based file rotations. See <tt>basic_text_file_backend</tt>. + * \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the file + * after each written record. + * \li \c target The target directory to store rotated files in. See <tt>sinks::file::make_collector</tt>. + * \li \c max_size The maximum total size of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>. + * \li \c min_free_space Minimum free space in the target directory. See <tt>sinks::file::make_collector</tt>. + * \li \c scan_method The method of scanning the target directory for log files. See <tt>sinks::file::scan_method</tt>. + * \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter, + * or a filter lambda expression. + * \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter, + * or a formatter lambda expression (either streaming or Boost.Format-like notation). + * \return Pointer to the constructed sink. + */ +template< typename... ArgsT > +shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT... const& args); + +#endif // BOOST_LOG_DOXYGEN_PASS + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#undef BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/filter_parser.hpp b/boost/log/utility/setup/filter_parser.hpp new file mode 100644 index 0000000000..cdc0634fd1 --- /dev/null +++ b/boost/log/utility/setup/filter_parser.hpp @@ -0,0 +1,346 @@ +/* + * 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 filter_parser.hpp + * \author Andrey Semashev + * \date 31.03.2008 + * + * The header contains definition of a filter parser function. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_ + +#include <string> +#include <boost/lexical_cast.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/phoenix/operator/comparison.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/setup_config.hpp> +#include <boost/log/detail/code_conversion.hpp> +#include <boost/log/exceptions.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/attribute_value_set.hpp> +#include <boost/log/expressions/filter.hpp> +#include <boost/log/expressions/keyword_fwd.hpp> +#include <boost/log/expressions/attr.hpp> +#include <boost/log/expressions/predicates/has_attr.hpp> +#include <boost/log/core/core.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * The interface class for all filter factories. + */ +template< typename CharT > +struct filter_factory +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + + /*! + * Default constructor + */ + BOOST_DEFAULTED_FUNCTION(filter_factory(), {}) + + /*! + * Virtual destructor + */ + virtual ~filter_factory() {} + + /*! + * The callback for filter for the attribute existence test + */ + virtual filter on_exists_test(attribute_name const& name) + { + return filter(expressions::has_attr(name)); + } + + /*! + * The callback for equality relation filter + */ + virtual filter on_equality_relation(attribute_name const& name, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The equality attribute value relation is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + /*! + * The callback for inequality relation filter + */ + virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The inequality attribute value relation is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + /*! + * The callback for less relation filter + */ + virtual filter on_less_relation(attribute_name const& name, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less attribute value relation is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + /*! + * The callback for greater relation filter + */ + virtual filter on_greater_relation(attribute_name const& name, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater attribute value relation is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + /*! + * The callback for less or equal relation filter + */ + virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less-or-equal attribute value relation is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + /*! + * The callback for greater or equal relation filter + */ + virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater-or-equal attribute value relation is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + + /*! + * The callback for custom relation filter + */ + virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(arg) + "\" is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + + BOOST_DELETED_FUNCTION(filter_factory(filter_factory const&)) + BOOST_DELETED_FUNCTION(filter_factory& operator= (filter_factory const&)) +}; + +/*! + * The base class for filter factories. The class defines default implementations for most + * filter expressions. In order to be able to construct filters, the attribute value type must + * support reading from a stream. Also, the default filters will rely on relational operators for + * the type, so these operators must also be defined. + */ +template< typename CharT, typename AttributeValueT > +class basic_filter_factory : + public filter_factory< CharT > +{ + //! Base type + typedef filter_factory< CharT > base_type; + +public: + //! The type(s) of the attribute value expected + typedef AttributeValueT value_type; + // Type imports + typedef typename base_type::string_type string_type; + + /*! + * The callback for filter for the attribute existence test + */ + virtual filter on_exists_test(attribute_name const& name) + { + return filter(expressions::has_attr< value_type >(name)); + } + + /*! + * The callback for equality relation filter + */ + virtual filter on_equality_relation(attribute_name const& name, string_type const& arg) + { + return filter(expressions::attr< value_type >(name) == parse_argument(arg)); + } + /*! + * The callback for inequality relation filter + */ + virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg) + { + return filter(expressions::attr< value_type >(name) != parse_argument(arg)); + } + /*! + * The callback for less relation filter + */ + virtual filter on_less_relation(attribute_name const& name, string_type const& arg) + { + return filter(expressions::attr< value_type >(name) < parse_argument(arg)); + } + /*! + * The callback for greater relation filter + */ + virtual filter on_greater_relation(attribute_name const& name, string_type const& arg) + { + return filter(expressions::attr< value_type >(name) > parse_argument(arg)); + } + /*! + * The callback for less or equal relation filter + */ + virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg) + { + return filter(expressions::attr< value_type >(name) <= parse_argument(arg)); + } + /*! + * The callback for greater or equal relation filter + */ + virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg) + { + return filter(expressions::attr< value_type >(name) >= parse_argument(arg)); + } + + /*! + * The callback for custom relation filter + */ + virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg) + { + BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(arg) + "\" is not supported", (name)); + BOOST_LOG_UNREACHABLE_RETURN(filter()); + } + + /*! + * The function parses the argument value for a binary relation + */ + virtual value_type parse_argument(string_type const& arg) + { + return boost::lexical_cast< value_type >(arg); + } +}; + +/*! + * The function registers a filter factory object for the specified attribute name. The factory will be + * used to construct a filter during parsing the filter string. + * + * \pre <tt>name != NULL && factory != NULL</tt>, <tt>name</tt> points to a zero-terminated string + * \param name Attribute name to associate the factory with + * \param factory The filter factory + */ +template< typename CharT > +BOOST_LOG_SETUP_API void register_filter_factory( + attribute_name const& name, shared_ptr< filter_factory< CharT > > const& factory); + +/*! + * The function registers a filter factory object for the specified attribute name. The factory will be + * used to construct a filter during parsing the filter string. + * + * \pre <tt>name != NULL && factory != NULL</tt>, <tt>name</tt> points to a zero-terminated string + * \param name Attribute name to associate the factory with + * \param factory The filter factory + */ +template< typename FactoryT > +inline typename enable_if< + is_base_and_derived< filter_factory< typename FactoryT::char_type >, FactoryT > +>::type register_filter_factory(attribute_name const& name, shared_ptr< FactoryT > const& factory) +{ + typedef filter_factory< typename FactoryT::char_type > factory_base; + register_filter_factory(name, boost::static_pointer_cast< factory_base >(factory)); +} + +/*! + * The function registers a simple filter factory object for the specified attribute name. The factory will + * support attribute values of type \c AttributeValueT, which must support all relation operations, such as + * equality comparison and less/greater ordering, and also extraction from stream. + * + * \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string + * \param name Attribute name to associate the factory with + */ +template< typename AttributeValueT, typename CharT > +inline void register_simple_filter_factory(attribute_name const& name) +{ + shared_ptr< filter_factory< CharT > > factory = + boost::make_shared< basic_filter_factory< CharT, AttributeValueT > >(); + register_filter_factory(name, factory); +} + +/*! + * The function registers a simple filter factory object for the specified attribute name. The factory will + * support attribute values of type \c AttributeValueT, which must support all relation operations, such as + * equality comparison and less/greater ordering, and also extraction from stream. + * + * \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string + * \param name Attribute name to associate the factory with + */ +template< typename AttributeValueT > +inline void register_simple_filter_factory(attribute_name const& name) +{ + register_simple_filter_factory< AttributeValueT, char >(name); +} + +/*! + * The function registers a simple filter factory object for the specified attribute keyword. The factory will + * support attribute values described by the keyword. The values must support all relation operations, such as + * equality comparison and less/greater ordering, and also extraction from stream. + * + * \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string + * \param keyword Attribute keyword to associate the factory with + */ +template< typename CharT, typename DescriptorT, template< typename > class ActorT > +inline void register_simple_filter_factory(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword) +{ + register_simple_filter_factory< typename DescriptorT::value_type, CharT >(keyword.get_name()); +} + +/*! + * The function parses a filter from the sequence of characters + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \return A function object that can be used as a filter. + * + * \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence. + */ +template< typename CharT > +BOOST_LOG_SETUP_API filter parse_filter(const CharT* begin, const CharT* end); + +/*! + * The function parses a filter from the string + * + * \param str A string that contains filter description + * \return A function object that can be used as a filter. + * + * \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence. + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline filter parse_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& str) +{ + const CharT* p = str.c_str(); + return parse_filter(p, p + str.size()); +} + +/*! + * The function parses a filter from the string + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str A string that contains filter description. + * \return A function object that can be used as a filter. + * + * \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence. + */ +template< typename CharT > +inline filter parse_filter(const CharT* str) +{ + return parse_filter(str, str + std::char_traits< CharT >::length(str)); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/formatter_parser.hpp b/boost/log/utility/setup/formatter_parser.hpp new file mode 100644 index 0000000000..df78d2ae7e --- /dev/null +++ b/boost/log/utility/setup/formatter_parser.hpp @@ -0,0 +1,216 @@ +/* + * 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 formatter_parser.hpp + * \author Andrey Semashev + * \date 07.04.2008 + * + * The header contains definition of a formatter parser function, along with facilities to + * add support for custom formatters. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_ + +#include <iosfwd> +#include <map> +#include <string> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/log/detail/setup_config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/core/record.hpp> +#include <boost/log/expressions/formatter.hpp> +#include <boost/log/expressions/attr.hpp> +#include <boost/log/expressions/formatters/stream.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * Formatter factory base interface. + */ +template< typename CharT > +struct formatter_factory +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! The formatter function object + typedef basic_formatter< char_type > formatter_type; + /*! + * Type of the map of formatter factory arguments [argument name -> argument value]. + * This type of maps will be passed to formatter factories on attempt to create a formatter. + */ + typedef std::map< string_type, string_type > args_map; + + /*! + * Default constructor + */ + BOOST_DEFAULTED_FUNCTION(formatter_factory(), {}) + + /*! + * Virtual destructor + */ + virtual ~formatter_factory() {} + + /*! + * The function creates a formatter for the specified attribute. + * + * \param name Attribute name + * \param args Formatter arguments + */ + virtual formatter_type create_formatter(attribute_name const& name, args_map const& args) = 0; + + BOOST_DELETED_FUNCTION(formatter_factory(formatter_factory const&)) + BOOST_DELETED_FUNCTION(formatter_factory& operator= (formatter_factory const&)) +}; + +/*! + * Base class for formatter factories. This class provides default implementation of formatter expressions for + * types supporting stream output. The factory does not take into account any additional parameters that may be specified. + */ +template< typename CharT, typename AttributeValueT > +class basic_formatter_factory : + public formatter_factory< CharT > +{ +private: + typedef formatter_factory< CharT > base_type; + +public: + //! Attribute value type + typedef AttributeValueT value_type; + // Type imports from the base class + typedef typename base_type::formatter_type formatter_type; + typedef typename base_type::args_map args_map; + + /*! + * The function creates a formatter for the specified attribute. + * + * \param name Attribute name + * \param args Formatter arguments + */ + formatter_type create_formatter(attribute_name const& name, args_map const& args) + { + return formatter_type(expressions::stream << expressions::attr< value_type >(name)); + } +}; + +/*! + * \brief The function registers a user-defined formatter factory + * + * The function registers a user-defined formatter factory. The registered factory function will be + * called when the formatter parser detects the specified attribute name in the formatter string. + * + * \pre <tt>!!attr_name && !!factory</tt>. + * + * \param attr_name Attribute name + * \param factory Pointer to the formatter factory + */ +template< typename CharT > +BOOST_LOG_SETUP_API void register_formatter_factory( + attribute_name const& attr_name, shared_ptr< formatter_factory< CharT > > const& factory); + +/*! + * \brief The function registers a user-defined formatter factory + * + * The function registers a user-defined formatter factory. The registered factory function will be + * called when the formatter parser detects the specified attribute name in the formatter string. + * + * \pre <tt>!!attr_name && !!factory</tt>. + * + * \param attr_name Attribute name + * \param factory Pointer to the formatter factory + */ +template< typename FactoryT > +inline typename enable_if< + is_base_and_derived< formatter_factory< typename FactoryT::char_type >, FactoryT > +>::type register_formatter_factory(attribute_name const& attr_name, shared_ptr< FactoryT > const& factory) +{ + typedef formatter_factory< typename FactoryT::char_type > factory_base; + register_formatter_factory(attr_name, boost::static_pointer_cast< factory_base >(factory)); +} + +/*! + * \brief The function registers a simple formatter factory + * + * The function registers a simple formatter factory. The registered factory will generate formatters + * that will be equivalent to the <tt>log::expressions::attr</tt> formatter (i.e. that will use the + * native \c operator<< to format the attribute value). The factory does not use any arguments from the format string, + * if specified. + * + * \pre <tt>!!attr_name</tt>. + * + * \param attr_name Attribute name + */ +template< typename AttributeValueT, typename CharT > +inline void register_simple_formatter_factory(attribute_name const& attr_name) +{ + shared_ptr< formatter_factory< CharT > > factory = + boost::make_shared< basic_formatter_factory< CharT, AttributeValueT > >(); + register_formatter_factory(attr_name, factory); +} + +/*! + * The function parses a formatter from the sequence of characters + * + * \pre <tt>begin <= end</tt>, both pointers must not be NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \return The parsed formatter. + * + * \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence. + */ +template< typename CharT > +BOOST_LOG_SETUP_API basic_formatter< CharT > parse_formatter(const CharT* begin, const CharT* end); + +/*! + * The function parses a formatter from the string + * + * \param str A string that contains format description + * \return The parsed formatter. + * + * \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence. + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline basic_formatter< CharT > parse_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& str) +{ + const CharT* p = str.c_str(); + return parse_formatter(p, p + str.size()); +} + +/*! + * The function parses a formatter from the string + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string + * \param str A string that contains format description. + * \return The parsed formatter. + * + * \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence. + */ +template< typename CharT > +inline basic_formatter< CharT > parse_formatter(const CharT* str) +{ + return parse_formatter(str, str + std::char_traits< CharT >::length(str)); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/from_settings.hpp b/boost/log/utility/setup/from_settings.hpp new file mode 100644 index 0000000000..50c36f524c --- /dev/null +++ b/boost/log/utility/setup/from_settings.hpp @@ -0,0 +1,164 @@ +/* + * 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 from_settings.hpp + * \author Andrey Semashev + * \date 11.10.2009 + * + * The header contains definition of facilities that allows to initialize the library from + * settings. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_ + +#include <string> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/log/detail/setup_config.hpp> +#include <boost/log/sinks/sink.hpp> +#include <boost/log/utility/setup/settings.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * The function initializes the logging library from a settings container + * + * \param setts Library settings container + * + * \b Throws: An <tt>std::exception</tt>-based exception if the provided settings are not valid. + */ +template< typename CharT > +BOOST_LOG_SETUP_API void init_from_settings(basic_settings_section< CharT > const& setts); + + +/*! + * Sink factory base interface + */ +template< typename CharT > +struct sink_factory +{ + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Settings section type + typedef basic_settings_section< char_type > settings_section; + + /*! + * Default constructor + */ + BOOST_DEFAULTED_FUNCTION(sink_factory(), {}) + + /*! + * Virtual destructor + */ + virtual ~sink_factory() {} + + /*! + * The function creates a formatter for the specified attribute. + * + * \param settings Sink parameters + */ + virtual shared_ptr< sinks::sink > create_sink(settings_section const& settings) = 0; + + BOOST_DELETED_FUNCTION(sink_factory(sink_factory const&)) + BOOST_DELETED_FUNCTION(sink_factory& operator= (sink_factory const&)) +}; + +/*! + * \brief The function registers a factory for a custom sink + * + * The function registers a factory for a sink. The factory will be called to create sink + * instance when the parser discovers the specified sink type in the settings file. The + * factory must accept a map of parameters [parameter name -> parameter value] that it + * may use to initialize the sink. The factory must return a non-NULL pointer to the + * constructed sink instance. + * + * \param sink_name The custom sink name. Must point to a zero-terminated sequence of characters, + * must not be NULL. + * \param factory Pointer to the custom sink factory. Must not be NULL. + */ +template< typename CharT > +BOOST_LOG_SETUP_API void register_sink_factory(const char* sink_name, shared_ptr< sink_factory< CharT > > const& factory); + +/*! + * \brief The function registers a factory for a custom sink + * + * The function registers a factory for a sink. The factory will be called to create sink + * instance when the parser discovers the specified sink type in the settings file. The + * factory must accept a map of parameters [parameter name -> parameter value] that it + * may use to initialize the sink. The factory must return a non-NULL pointer to the + * constructed sink instance. + * + * \param sink_name The custom sink name + * \param factory Pointer to the custom sink factory. Must not be NULL. + */ +template< typename CharT > +inline void register_sink_factory(std::string const& sink_name, shared_ptr< sink_factory< CharT > > const& factory) +{ + register_sink_factory(sink_name.c_str(), factory); +} + +/*! + * \brief The function registers a factory for a custom sink + * + * The function registers a factory for a sink. The factory will be called to create sink + * instance when the parser discovers the specified sink type in the settings file. The + * factory must accept a map of parameters [parameter name -> parameter value] that it + * may use to initialize the sink. The factory must return a non-NULL pointer to the + * constructed sink instance. + * + * \param sink_name The custom sink name. Must point to a zero-terminated sequence of characters, + * must not be NULL. + * \param factory Pointer to the custom sink factory. Must not be NULL. + */ +template< typename FactoryT > +inline typename enable_if< + is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT > +>::type register_sink_factory(const char* sink_name, shared_ptr< FactoryT > const& factory) +{ + typedef sink_factory< typename FactoryT::char_type > factory_base; + register_sink_factory(sink_name, boost::static_pointer_cast< factory_base >(factory)); +} + +/*! + * \brief The function registers a factory for a custom sink + * + * The function registers a factory for a sink. The factory will be called to create sink + * instance when the parser discovers the specified sink type in the settings file. The + * factory must accept a map of parameters [parameter name -> parameter value] that it + * may use to initialize the sink. The factory must return a non-NULL pointer to the + * constructed sink instance. + * + * \param sink_name The custom sink name + * \param factory Pointer to the custom sink factory. Must not be NULL. + */ +template< typename FactoryT > +inline typename enable_if< + is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT > +>::type register_sink_factory(std::string const& sink_name, shared_ptr< FactoryT > const& factory) +{ + typedef sink_factory< typename FactoryT::char_type > factory_base; + register_sink_factory(sink_name.c_str(), boost::static_pointer_cast< factory_base >(factory)); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/from_stream.hpp b/boost/log/utility/setup/from_stream.hpp new file mode 100644 index 0000000000..0b87459e7c --- /dev/null +++ b/boost/log/utility/setup/from_stream.hpp @@ -0,0 +1,47 @@ +/* + * 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 from_stream.hpp + * \author Andrey Semashev + * \date 22.03.2008 + * + * The header contains definition of facilities that allows to initialize the library from a + * settings file. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/log/detail/setup_config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * The function initializes the logging library from a stream containing logging settings + * + * \param strm Stream, that provides library settings + * + * \b Throws: An <tt>std::exception</tt>-based exception if the read data cannot be interpreted as the library settings + */ +template< typename CharT > +BOOST_LOG_SETUP_API void init_from_stream(std::basic_istream< CharT >& strm); + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/settings.hpp b/boost/log/utility/setup/settings.hpp new file mode 100644 index 0000000000..bf8a608dea --- /dev/null +++ b/boost/log/utility/setup/settings.hpp @@ -0,0 +1,643 @@ +/* + * 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 settings.hpp + * \author Andrey Semashev + * \date 11.10.2009 + * + * The header contains definition of the library settings container. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ + +#include <cstddef> +#include <string> +#include <iterator> +#include <boost/assert.hpp> +#include <boost/move/core.hpp> +#include <boost/mpl/if.hpp> +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/optional/optional.hpp> +#include <boost/property_tree/ptree.hpp> +#include <boost/log/detail/setup_config.hpp> +#include <boost/log/detail/native_typeof.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#if !defined(BOOST_LOG_TYPEOF) +#include <boost/utility/enable_if.hpp> +#endif +#if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) +#include <boost/utility/declval.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +// This workaround is needed for MSVC 10 to work around ICE caused by stack overflow +template< typename SectionT, bool IsConstV > +struct basic_settings_section_iterator_base; + +template< typename SectionT > +struct basic_settings_section_iterator_base< SectionT, true > +{ + typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type; + typedef typename SectionT::property_tree_type::const_iterator base_iterator_type; + typedef iterator_adaptor< + iterator_type, + base_iterator_type, + SectionT, + use_default, + const SectionT + > type; +}; + +template< typename SectionT > +struct basic_settings_section_iterator_base< SectionT, false > +{ + typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type; + typedef typename SectionT::property_tree_type::iterator base_iterator_type; + typedef iterator_adaptor< + iterator_type, + base_iterator_type, + SectionT, + use_default, + SectionT + > type; +}; + +} // namespace aux + +/*! + * \brief The class represents a reference to the settings container section + * + * The section refers to a sub-tree of the library settings container. It does not + * own the referred sub-tree but allows for convenient access to parameters within the subsection. + */ +template< typename CharT > +class basic_settings_section +{ + template< typename SectionT, bool IsConstV > + friend struct aux::basic_settings_section_iterator_base; + +public: + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Property tree type + typedef property_tree::basic_ptree< std::string, string_type > property_tree_type; + //! Property tree path type + typedef typename property_tree_type::path_type path_type; + +private: +#if !defined(BOOST_LOG_DOXYGEN_PASS) + + //! A reference proxy object +#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS + template< bool IsConstV > + class ref; + template< bool IsConstV > + friend class ref; +#endif + template< bool IsConstV > + class ref + { + private: + typedef typename mpl::if_c< + IsConstV, + basic_settings_section< char_type > const, + basic_settings_section< char_type > + >::type section_type; + + private: + section_type& m_section; + path_type m_path; + + public: + ref(section_type& section, std::string const& section_name) : + m_section(section), + m_path(section_name) + { + } + ref(section_type& section, const char* section_name) : + m_section(section), + m_path(section_name) + { + } + + ref& operator[] (std::string const& param_name) + { + m_path /= param_name; + return *this; + } + + ref& operator= (string_type const& value) + { + BOOST_ASSERT(m_section.m_ptree != NULL); + m_section.m_ptree->put(m_path, value); + return *this; + } + + template< bool V > + ref& operator= (ref< V > const& value) + { + BOOST_ASSERT(m_section.m_ptree != NULL); + optional< string_type > val = value.get(); + if (!!val) + { + m_section.m_ptree->put(m_path, val); + } + else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path)) + { + node.put_value(string_type()); + } + + return *this; + } + + template< typename T > + ref& operator= (T const& value) + { + BOOST_ASSERT(m_section.m_ptree != NULL); + m_section.m_ptree->put(m_path, value); + return *this; + } + + BOOST_EXPLICIT_OPERATOR_BOOL() + + bool operator! () const + { + return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path); + } + + std::string get_name() const + { + return m_path.dump(); + } + + operator optional< string_type > () const + { + return get(); + } + + optional< string_type > get() const + { + if (m_section.m_ptree) + return m_section.m_ptree->template get_optional< string_type >(m_path); + else + return optional< string_type >(); + } + + template< typename T > + optional< T > get() const + { + if (m_section.m_ptree) + return m_section.m_ptree->template get_optional< T >(m_path); + else + return optional< T >(); + } + + operator section_type () const + { + return get_section(); + } + + section_type get_section() const + { + if (m_section.m_ptree) + return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr()); + else + return section_type(); + } + +#if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)) +#if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) + template< typename T > + auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value)) + { + if (m_section.m_ptree) + return m_section.m_ptree->get(m_path, def_value); + else + return def_value; + } +#else + // GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled + template< typename T > + BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const + { + if (m_section.m_ptree) + return m_section.m_ptree->get(m_path, def_value); + else + return def_value; + } +#endif +#else + template< typename T > + T or_default(T const& def_value) const + { + if (m_section.m_ptree) + return m_section.m_ptree->get(m_path, def_value); + else + return def_value; + } + + template< typename T > + typename enable_if< boost::property_tree::detail::is_character< T >, std::basic_string< T > >::type + or_default(const T* def_value) const + { + if (m_section.m_ptree) + return m_section.m_ptree->get(m_path, def_value); + else + return def_value; + } +#endif + string_type or_default(string_type const& def_value) const + { + return get().get_value_or(def_value); + } + string_type or_default(typename string_type::value_type const* def_value) const + { + if (optional< string_type > val = get()) + return val.get(); + else + return def_value; + } + }; + + //! An iterator over subsections and parameters +#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS + template< bool IsConstV > + class iter; + template< bool IsConstV > + friend class iter; +#endif + template< bool IsConstV > + class iter : + public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type + { + friend class boost::iterator_core_access; + + typedef typename iter::iterator_adaptor_ iterator_adaptor_; + // NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE + typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type; + + public: + typedef typename iterator_adaptor_::reference reference; + + public: + BOOST_DEFAULTED_FUNCTION(iter(), {}) + template< bool OtherIsConstV > + iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {} + explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {} + + //! Returns the section name + std::string const& get_name() const + { + return this->base()->first; + } + + private: + reference dereference() const + { + return reference(const_cast< property_tree_type* >(&this->base()->second)); + } + }; + +public: + typedef ref< true > const_reference; + typedef ref< false > reference; + typedef iter< true > const_iterator; + typedef iter< false > iterator; + typedef std::reverse_iterator< const_iterator > const_reverse_iterator; + typedef std::reverse_iterator< iterator > reverse_iterator; + +#else + +public: + /*! + * Constant reference to the parameter value + */ + typedef implementation_defined const_reference; + /*! + * Mutable reference to the parameter value + */ + typedef implementation_defined reference; + + /*! + * Constant iterator over nested parameters and subsections + */ + typedef implementation_defined const_iterator; + /*! + * Mutable iterator over nested parameters and subsections + */ + typedef implementation_defined iterator; + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +protected: + //! Parameters + property_tree_type* m_ptree; + +public: + /*! + * Default constructor. Creates an empty settings container. + */ + basic_settings_section() : m_ptree(NULL) + { + } + + /*! + * Copy constructor. + */ + basic_settings_section(basic_settings_section const& that) : m_ptree(that.m_ptree) + { + } + + /*! + * Checks if the section refers to the container. + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * Checks if the section refers to the container. + */ + bool operator! () const BOOST_NOEXCEPT { return !m_ptree; } + + /*! + * Returns an iterator over the nested subsections and parameters. + */ + iterator begin() + { + if (m_ptree) + return iterator(m_ptree->begin()); + else + return iterator(); + } + + /*! + * Returns an iterator over the nested subsections and parameters. + */ + iterator end() + { + if (m_ptree) + return iterator(m_ptree->end()); + else + return iterator(); + } + + /*! + * Returns an iterator over the nested subsections and parameters. + */ + const_iterator begin() const + { + if (m_ptree) + return const_iterator(m_ptree->begin()); + else + return const_iterator(); + } + + /*! + * Returns an iterator over the nested subsections and parameters. + */ + const_iterator end() const + { + if (m_ptree) + return const_iterator(m_ptree->end()); + else + return const_iterator(); + } + + /*! + * Returns a reverse iterator over the nested subsections and parameters. + */ + reverse_iterator rbegin() { return reverse_iterator(begin()); } + + /*! + * Returns a reverse iterator over the nested subsections and parameters. + */ + reverse_iterator rend() { return reverse_iterator(end()); } + + /*! + * Returns a reverse iterator over the nested subsections and parameters. + */ + const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } + + /*! + * Returns a reverse iterator over the nested subsections and parameters. + */ + const_reverse_iterator rend() const { return const_reverse_iterator(end()); } + + /*! + * Checks if the container is empty (i.e. contains no sections and parameters). + */ + bool empty() const { return m_ptree == NULL || m_ptree->empty(); } + + /*! + * Accessor to a single parameter. This operator should be used in conjunction + * with the subsequent subscript operator that designates the parameter name. + * + * \param section_name The name of the section in which the parameter resides + * \return An unspecified reference type that can be used for parameter name specifying + */ + reference operator[] (std::string const& section_name) { return reference(*this, section_name); } + /*! + * Accessor to a single parameter. This operator should be used in conjunction + * with the subsequent subscript operator that designates the parameter name. + * + * \param section_name The name of the section in which the parameter resides + * \return An unspecified reference type that can be used for parameter name specifying + */ + const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); } + + /*! + * Accessor to a single parameter. This operator should be used in conjunction + * with the subsequent subscript operator that designates the parameter name. + * + * \param section_name The name of the section in which the parameter resides + * \return An unspecified reference type that can be used for parameter name specifying + */ + reference operator[] (const char* section_name) { return reference(*this, section_name); } + /*! + * Accessor to a single parameter. This operator should be used in conjunction + * with the subsequent subscript operator that designates the parameter name. + * + * \param section_name The name of the section in which the parameter resides + * \return An unspecified reference type that can be used for parameter name specifying + */ + const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); } + + /*! + * Accessor for the embedded property tree + */ + property_tree_type const& property_tree() const { return *m_ptree; } + /*! + * Accessor for the embedded property tree + */ + property_tree_type& property_tree() { return *m_ptree; } + + /*! + * Checks if the specified section is present in the container. + * + * \param section_name The name of the section + */ + bool has_section(string_type const& section_name) const + { + return m_ptree != NULL && !!m_ptree->get_child_optional(section_name); + } + /*! + * Checks if the specified parameter is present in the container. + * + * \param section_name The name of the section in which the parameter resides + * \param param_name The name of the parameter + */ + bool has_parameter(string_type const& section_name, string_type const& param_name) const + { + if (m_ptree) + { + optional< property_tree_type& > section = m_ptree->get_child_optional(section_name); + if (!!section) + return (section->find(param_name) != section->not_found()); + } + + return false; + } + + /*! + * Swaps two references to settings sections. + */ + void swap(basic_settings_section& that) + { + property_tree_type* const p = m_ptree; + m_ptree = that.m_ptree; + that.m_ptree = p; + } + +protected: + explicit basic_settings_section(property_tree_type* tree) : m_ptree(tree) + { + } +}; + +template< typename CharT > +inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right) +{ + left.swap(right); +} + + +/*! + * \brief The class represents settings container + * + * All settings are presented as a number of named parameters divided into named sections. + * The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this: + * + * <code><pre> + * optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1" + * // returns an empty value if no such parameter exists + * settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2" + * // to value "10" + * </pre></code> + * + * There are also other methods to work with parameters. + */ +template< typename CharT > +class basic_settings : + public basic_settings_section< CharT > +{ + typedef basic_settings this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + //! Section type + typedef basic_settings_section< CharT > section; + //! Property tree type + typedef typename section::property_tree_type property_tree_type; + +public: + /*! + * Default constructor. Creates an empty settings container. + */ + basic_settings() : section(new property_tree_type()) + { + } + + /*! + * Copy constructor. + */ + basic_settings(basic_settings const& that) : + section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL)) + { + } + + /*! + * Move constructor. + */ + basic_settings(BOOST_RV_REF(this_type) that) + { + this->swap(that); + } + /*! + * Initializing constructor. Creates a settings container with the copy of the specified property tree. + */ + explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree)) + { + } + + /*! + * Destructor + */ + ~basic_settings() + { + delete this->m_ptree; + } + + /*! + * Copy assignment operator. + */ + basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that) + { + if (this != &that) + { + basic_settings tmp = that; + this->swap(tmp); + } + return *this; + } + /*! + * Move assignment operator. + */ + basic_settings& operator= (BOOST_RV_REF(basic_settings) that) + { + this->swap(that); + return *this; + } +}; + +#ifdef BOOST_LOG_USE_CHAR +typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging +typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging +typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging +#endif + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ diff --git a/boost/log/utility/setup/settings_parser.hpp b/boost/log/utility/setup/settings_parser.hpp new file mode 100644 index 0000000000..cf1ea8ea1a --- /dev/null +++ b/boost/log/utility/setup/settings_parser.hpp @@ -0,0 +1,47 @@ +/* + * 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 settings_parser.hpp + * \author Andrey Semashev + * \date 20.07.2012 + * + * The header contains definition of a settings parser function. + */ + +#ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/log/detail/setup_config.hpp> +#include <boost/log/utility/setup/settings.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * The function parses library settings from an input stream + * + * \param strm Stream, that provides library settings + * + * \b Throws: An <tt>std::exception</tt>-based exception if the read data cannot be interpreted as the library settings + */ +template< typename CharT > +BOOST_LOG_SETUP_API basic_settings< CharT > parse_settings(std::basic_istream< CharT >& strm); + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_ diff --git a/boost/log/utility/strictest_lock.hpp b/boost/log/utility/strictest_lock.hpp new file mode 100644 index 0000000000..44733167a6 --- /dev/null +++ b/boost/log/utility/strictest_lock.hpp @@ -0,0 +1,214 @@ +/* + * 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 utility/strictest_lock.hpp + * \author Andrey Semashev + * \date 30.05.2010 + * + * The header contains definition of the \c strictest_lock metafunction that + * allows to select a lock with the strictest access requirements. + */ + +#ifndef BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_ + +#include <boost/mpl/integral_c.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/locks.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/arithmetic/sub.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/arithmetic/dec.hpp> +#include <boost/preprocessor/repetition/enum_trailing.hpp> +#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> +#include <boost/log/detail/pp_identity.hpp> +#endif +#if defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS) +#include <boost/mpl/less.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if !defined(BOOST_LOG_STRICTEST_LOCK_LIMIT) +/*! + * The macro defines the maximum number of template arguments that the \c strictest_lock + * metafunction accepts. Should not be less than 2. + */ +#define BOOST_LOG_STRICTEST_LOCK_LIMIT 10 +#endif // BOOST_LOG_STRICTEST_LOCK_LIMIT +#if BOOST_LOG_STRICTEST_LOCK_LIMIT < 2 +#error The BOOST_LOG_STRICTEST_LOCK_LIMIT macro should not be less than 2 +#endif +#endif // defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +//! Access modes for different types of locks +enum lock_access_mode +{ + unlocked_access, //!< A thread that owns this kind of lock doesn't restrict other threads in any way + shared_access, //!< A thread that owns this kind of lock requires that no other thread modify the locked data + exclusive_access //!< A thread that owns this kind of lock requires that no other thread has access to the locked data +}; + +//! The trait allows to select an access mode by the lock type +template< typename LockT > +struct thread_access_mode_of; + +template< typename MutexT > +struct thread_access_mode_of< no_lock< MutexT > > : mpl::integral_c< lock_access_mode, unlocked_access > +{ +}; + +#if !defined(BOOST_LOG_NO_THREADS) + +template< typename MutexT > +struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > +{ +}; + +template< typename MutexT > +struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > +{ +}; + +template< typename MutexT > +struct thread_access_mode_of< shared_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > +{ +}; + +template< typename MutexT > +struct thread_access_mode_of< upgrade_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > +{ +}; + +template< typename MutexT > +struct thread_access_mode_of< boost::log::aux::exclusive_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > +{ +}; + +template< typename MutexT > +struct thread_access_mode_of< boost::log::aux::shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > +{ +}; + +#endif // !defined(BOOST_LOG_NO_THREADS) + +namespace aux { + +//! The metafunction selects the most strict lock type of the two +template< + typename LeftLockT, + typename RightLockT, +#if !defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS) + bool CondV = (thread_access_mode_of< LeftLockT >::value < thread_access_mode_of< RightLockT >::value) +#else + bool CondV = mpl::less< thread_access_mode_of< LeftLockT >, thread_access_mode_of< RightLockT > >::value +#endif +> +struct strictest_lock_impl +{ + typedef RightLockT type; +}; +template< typename LeftLockT, typename RightLockT > +struct strictest_lock_impl< LeftLockT, RightLockT, false > +{ + typedef LeftLockT type; +}; + +} // namespace aux + +#if defined(BOOST_LOG_DOXYGEN_PASS) + +/*! + * \brief The metafunction selects the most strict lock type of the specified. + * + * The template supports all lock types provided by the Boost.Thread + * library (except for \c upgrade_to_unique_lock), plus additional + * pseudo-lock \c no_lock that indicates no locking at all. + * Exclusive locks are considered the strictest, shared locks are weaker, + * and \c no_lock is the weakest. + */ +template< typename... LocksT > +struct strictest_lock +{ + typedef implementation_defined type; +}; + +#else // defined(BOOST_LOG_DOXYGEN_PASS) + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template< typename LockT, typename... LocksT > +struct strictest_lock; + +template< typename LockT > +struct strictest_lock< LockT > +{ + typedef LockT type; +}; + +template< typename LeftLockT, typename RightLockT > +struct strictest_lock< LeftLockT, RightLockT > +{ + typedef typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type type; +}; + +template< typename LeftLockT, typename RightLockT, typename... LocksT > +struct strictest_lock< LeftLockT, RightLockT, LocksT... > +{ + typedef typename strictest_lock< + typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type, + LocksT... + >::type type; +}; + +#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +# define BOOST_LOG_TYPE_INTERNAL(z, i, data) BOOST_PP_CAT(T, BOOST_PP_INC(i)) + +template< + typename T, + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), typename T, void) +> +struct strictest_lock +{ + typedef typename strictest_lock< + typename boost::log::aux::strictest_lock_impl< T, T0 >::type + BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_LOG_STRICTEST_LOCK_LIMIT, 2), BOOST_LOG_TYPE_INTERNAL, ~) + >::type type; +}; + +template< typename T > +struct strictest_lock< + T + BOOST_PP_ENUM_TRAILING(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), BOOST_LOG_PP_IDENTITY, void) +> +{ + typedef T type; +}; + +# undef BOOST_LOG_TYPE_INTERNAL + +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#endif // defined(BOOST_LOG_DOXYGEN_PASS) + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_ diff --git a/boost/log/utility/string_literal.hpp b/boost/log/utility/string_literal.hpp new file mode 100644 index 0000000000..cb437fbc33 --- /dev/null +++ b/boost/log/utility/string_literal.hpp @@ -0,0 +1,617 @@ +/* + * 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 string_literal.hpp + * \author Andrey Semashev + * \date 24.06.2007 + * + * The header contains implementation of a constant string literal wrapper. + */ + +#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_ + +#include <cstddef> +#include <stdexcept> +#include <iosfwd> +#include <ios> // std::streamsize +#include <string> +#include <iterator> +#include <boost/operators.hpp> +#include <boost/throw_exception.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/string_literal_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief String literal wrapper + * + * The \c basic_string_literal is a thin wrapper around a constant string literal. + * It provides interface similar to STL strings, but because of read-only nature + * of string literals, lacks ability to modify string contents. However, + * \c basic_string_literal objects can be assigned to and cleared. + * + * The main advantage of this class comparing to other string classes is that + * it doesn't dynamically allocate memory and therefore is fast, thin and exception safe. + */ +template< typename CharT, typename TraitsT > +class basic_string_literal + //! \cond + : public totally_ordered1< basic_string_literal< CharT, TraitsT >, + totally_ordered2< basic_string_literal< CharT, TraitsT >, const CharT*, + totally_ordered2< + basic_string_literal< CharT, TraitsT >, + std::basic_string< CharT, TraitsT > + > + > + > + //! \endcond +{ + //! Self type + typedef basic_string_literal< CharT, TraitsT > this_type; + +public: + typedef CharT value_type; + typedef TraitsT traits_type; + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* const_pointer; + typedef value_type const& const_reference; + typedef const value_type* const_iterator; + typedef std::reverse_iterator< const_iterator > const_reverse_iterator; + + //! Corresponding STL string type + typedef std::basic_string< value_type, traits_type > string_type; + +private: + //! Pointer to the beginning of the literal + const_pointer m_pStart; + //! Length + size_type m_Len; + + //! Empty string literal to support clear + static const value_type g_EmptyString[1]; + +public: + /*! + * Constructor + * + * \post <tt>empty() == true</tt> + */ + basic_string_literal() BOOST_NOEXCEPT { clear(); } + + /*! + * Constructor from a string literal + * + * \post <tt>*this == p</tt> + * \param p A zero-terminated constant sequence of characters + */ + template< typename T, size_type LenV > + basic_string_literal(T(&p)[LenV] + //! \cond + , typename enable_if< is_same< T, const value_type >, int >::type = 0 + //! \endcond + ) BOOST_NOEXCEPT + : m_pStart(p), m_Len(LenV - 1) + { + } + + /*! + * Copy constructor + * + * \post <tt>*this == that</tt> + * \param that Source literal to copy string from + */ + basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {} + + /*! + * Assignment operator + * + * \post <tt>*this == that</tt> + * \param that Source literal to copy string from + */ + this_type& operator= (this_type const& that) BOOST_NOEXCEPT + { + return assign(that); + } + /*! + * Assignment from a string literal + * + * \post <tt>*this == p</tt> + * \param p A zero-terminated constant sequence of characters + */ + template< typename T, size_type LenV > +#ifndef BOOST_LOG_DOXYGEN_PASS + typename enable_if< + is_same< T, const value_type >, + this_type& + >::type +#else + this_type& +#endif // BOOST_LOG_DOXYGEN_PASS + operator= (T(&p)[LenV]) BOOST_NOEXCEPT + { + return assign(p); + } + + /*! + * Lexicographical comparison (equality) + * + * \param that Comparand + * \return \c true if the comparand string equals to this string, \c false otherwise + */ + bool operator== (this_type const& that) const BOOST_NOEXCEPT + { + return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) == 0); + } + /*! + * Lexicographical comparison (equality) + * + * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. + * \return \c true if the comparand string equals to this string, \c false otherwise + */ + bool operator== (const_pointer str) const BOOST_NOEXCEPT + { + return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) == 0); + } + /*! + * Lexicographical comparison (equality) + * + * \param that Comparand + * \return \c true if the comparand string equals to this string, \c false otherwise + */ + bool operator== (string_type const& that) const + { + return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) == 0); + } + + /*! + * Lexicographical comparison (less ordering) + * + * \param that Comparand + * \return \c true if this string is less than the comparand, \c false otherwise + */ + bool operator< (this_type const& that) const BOOST_NOEXCEPT + { + return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) < 0); + } + /*! + * Lexicographical comparison (less ordering) + * + * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. + * \return \c true if this string is less than the comparand, \c false otherwise + */ + bool operator< (const_pointer str) const BOOST_NOEXCEPT + { + return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) < 0); + } + /*! + * Lexicographical comparison (less ordering) + * + * \param that Comparand + * \return \c true if this string is less than the comparand, \c false otherwise + */ + bool operator< (string_type const& that) const + { + return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) < 0); + } + + /*! + * Lexicographical comparison (greater ordering) + * + * \param that Comparand + * \return \c true if this string is greater than the comparand, \c false otherwise + */ + bool operator> (this_type const& that) const BOOST_NOEXCEPT + { + return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) > 0); + } + /*! + * Lexicographical comparison (greater ordering) + * + * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. + * \return \c true if this string is greater than the comparand, \c false otherwise + */ + bool operator> (const_pointer str) const BOOST_NOEXCEPT + { + return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) > 0); + } + /*! + * Lexicographical comparison (greater ordering) + * + * \param that Comparand + * \return \c true if this string is greater than the comparand, \c false otherwise + */ + bool operator> (string_type const& that) const + { + return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) > 0); + } + + /*! + * Subscript operator + * + * \pre <tt>i < size()</tt> + * \param i Requested character index + * \return Constant reference to the requested character + */ + const_reference operator[] (size_type i) const BOOST_NOEXCEPT + { + return m_pStart[i]; + } + /*! + * Checked subscript + * + * \param i Requested character index + * \return Constant reference to the requested character + * + * \b Throws: An <tt>std::exception</tt>-based exception if index \a i is out of string boundaries + */ + const_reference at(size_type i) const + { + if (i >= m_Len) + BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::at: the index value is out of range")); + return m_pStart[i]; + } + + /*! + * \return Pointer to the beginning of the literal + */ + const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; } + /*! + * \return Pointer to the beginning of the literal + */ + const_pointer data() const BOOST_NOEXCEPT { return m_pStart; } + /*! + * \return Length of the literal + */ + size_type size() const BOOST_NOEXCEPT { return m_Len; } + /*! + * \return Length of the literal + */ + size_type length() const BOOST_NOEXCEPT { return m_Len; } + + /*! + * \return \c true if the literal is an empty string, \c false otherwise + */ + bool empty() const BOOST_NOEXCEPT + { + return (m_Len == 0); + } + + /*! + * \return Iterator that points to the first character of the literal + */ + const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; } + /*! + * \return Iterator that points after the last character of the literal + */ + const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; } + /*! + * \return Reverse iterator that points to the last character of the literal + */ + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } + /*! + * \return Reverse iterator that points before the first character of the literal + */ + const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } + + /*! + * \return STL string constructed from the literal + */ + string_type str() const + { + return string_type(m_pStart, m_Len); + } + + /*! + * The method clears the literal + * + * \post <tt>empty() == true</tt> + */ + void clear() BOOST_NOEXCEPT + { + m_pStart = g_EmptyString; + m_Len = 0; + } + /*! + * The method swaps two literals + */ + void swap(this_type& that) BOOST_NOEXCEPT + { + const_pointer p = m_pStart; + m_pStart = that.m_pStart; + that.m_pStart = p; + + size_type l = m_Len; + m_Len = that.m_Len; + that.m_Len = l; + } + + /*! + * Assignment from another literal + * + * \post <tt>*this == that</tt> + * \param that Source literal to copy string from + */ + this_type& assign(this_type const& that) BOOST_NOEXCEPT + { + m_pStart = that.m_pStart; + m_Len = that.m_Len; + return *this; + } + /*! + * Assignment from another literal + * + * \post <tt>*this == p</tt> + * \param p A zero-terminated constant sequence of characters + */ + template< typename T, size_type LenV > +#ifndef BOOST_LOG_DOXYGEN_PASS + typename enable_if< + is_same< T, const value_type >, + this_type& + >::type +#else + this_type& +#endif // BOOST_LOG_DOXYGEN_PASS + assign(T(&p)[LenV]) BOOST_NOEXCEPT + { + m_pStart = p; + m_Len = LenV - 1; + return *this; + } + + /*! + * The method copies the literal or its portion to an external buffer + * + * \pre <tt>pos <= size()</tt> + * \param str Pointer to the external buffer beginning. Must not be NULL. + * The buffer must have enough capacity to accommodate the requested number of characters. + * \param n Maximum number of characters to copy + * \param pos Starting position to start copying from + * \return Number of characters copied + * + * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. + */ + size_type copy(value_type* str, size_type n, size_type pos = 0) const + { + if (pos > m_Len) + BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::copy: the position is out of range")); + + size_type len = m_Len - pos; + if (len > n) + len = n; + traits_type::copy(str, m_pStart + pos, len); + return len; + } + + /*! + * Lexicographically compares the argument string to a part of this string + * + * \pre <tt>pos <= size()</tt> + * \param pos Starting position within this string to perform comparison to + * \param n Length of the substring of this string to perform comparison to + * \param str Comparand. Must point to a sequence of characters, must not be NULL. + * \param len Number of characters in the sequence \a str. + * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, + * a positive value if this string is greater than the comparand. + * + * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. + */ + int compare(size_type pos, size_type n, const_pointer str, size_type len) const + { + if (pos > m_Len) + BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::compare: the position is out of range")); + + size_type compare_size = m_Len - pos; + if (compare_size > len) + compare_size = len; + if (compare_size > n) + compare_size = n; + return compare_internal(m_pStart + pos, compare_size, str, compare_size); + } + /*! + * Lexicographically compares the argument string to a part of this string + * + * \pre <tt>pos <= size()</tt> + * \param pos Starting position within this string to perform comparison to + * \param n Length of the substring of this string to perform comparison to + * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. + * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, + * a positive value if this string is greater than the comparand. + * + * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. + */ + int compare(size_type pos, size_type n, const_pointer str) const BOOST_NOEXCEPT + { + return compare(pos, n, str, traits_type::length(str)); + } + /*! + * Lexicographically compares the argument string literal to a part of this string + * + * \pre <tt>pos <= size()</tt> + * \param pos Starting position within this string to perform comparison to + * \param n Length of the substring of this string to perform comparison to + * \param that Comparand + * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, + * a positive value if this string is greater than the comparand. + * + * \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range. + */ + int compare(size_type pos, size_type n, this_type const& that) const BOOST_NOEXCEPT + { + return compare(pos, n, that.c_str(), that.size()); + } + /*! + * Lexicographically compares the argument string to this string + * + * \param str Comparand. Must point to a sequence of characters, must not be NULL. + * \param len Number of characters in the sequence \a str. + * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, + * a positive value if this string is greater than the comparand. + */ + int compare(const_pointer str, size_type len) const BOOST_NOEXCEPT + { + return compare(0, m_Len, str, len); + } + /*! + * Lexicographically compares the argument string to this string + * + * \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL. + * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, + * a positive value if this string is greater than the comparand. + */ + int compare(const_pointer str) const BOOST_NOEXCEPT + { + return compare(0, m_Len, str, traits_type::length(str)); + } + /*! + * Lexicographically compares the argument string to this string + * + * \param that Comparand + * \return Zero if the comparand equals this string, a negative value if this string is less than the comparand, + * a positive value if this string is greater than the comparand. + */ + int compare(this_type const& that) const BOOST_NOEXCEPT + { + return compare(0, m_Len, that.c_str(), that.size()); + } + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! Internal comparison implementation + static int compare_internal(const_pointer pLeft, size_type LeftLen, const_pointer pRight, size_type RightLen) BOOST_NOEXCEPT + { + if (pLeft != pRight) + { + const int result = traits_type::compare(pLeft, pRight, (LeftLen < RightLen ? LeftLen : RightLen)); + if (result != 0) + return result; + } + return LeftLen < RightLen ? -1 : (LeftLen > RightLen ? 1 : 0); + } +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +template< typename CharT, typename TraitsT > +typename basic_string_literal< CharT, TraitsT >::value_type const +basic_string_literal< CharT, TraitsT >::g_EmptyString[1] = { 0 }; + +namespace aux { + +template< typename CharT, typename TraitsT > +inline void insert_fill_chars(std::basic_ostream< CharT, TraitsT >& strm, std::size_t n) +{ + enum { chunk_size = 8 }; + CharT fill_chars[chunk_size]; + const CharT filler = strm.fill(); + for (unsigned int i = 0; i < chunk_size; ++i) + fill_chars[i] = filler; + for (; n >= chunk_size && strm.good(); n -= chunk_size) + strm.write(fill_chars, static_cast< std::size_t >(chunk_size)); + if (n > 0 && strm.good()) + strm.write(fill_chars, n); +} + +template< typename CharT, typename TraitsT > +void insert_aligned(std::basic_ostream< CharT, TraitsT >& strm, const CharT* p, std::size_t size) +{ + const std::size_t alignment_size = static_cast< std::size_t >(strm.width()) - size; + const bool align_left = (strm.flags() & std::basic_ostream< CharT, TraitsT >::adjustfield) == std::basic_ostream< CharT, TraitsT >::left; + if (align_left) + { + strm.write(p, size); + if (strm.good()) + aux::insert_fill_chars(strm, alignment_size); + } + else + { + aux::insert_fill_chars(strm, alignment_size); + if (strm.good()) + strm.write(p, size); + } +} + +} // namespace aux + +//! Output operator +template< typename CharT, typename StrmTraitsT, typename LitTraitsT > +inline std::basic_ostream< CharT, StrmTraitsT >& operator<< ( + std::basic_ostream< CharT, StrmTraitsT >& strm, basic_string_literal< CharT, LitTraitsT > const& lit) +{ + if (strm.good()) + { + const std::size_t size = lit.size(); + const std::size_t w = static_cast< std::size_t >(strm.width()); + if (w <= size) + strm.write(lit.c_str(), static_cast< std::streamsize >(size)); + else + aux::insert_aligned(strm, lit.c_str(), lit.size()); + strm.width(0); + } + return strm; +} + +//! External swap +template< typename CharT, typename TraitsT > +inline void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +//! Creates a string literal wrapper from a constant string literal +#ifdef BOOST_LOG_USE_CHAR +template< typename T, std::size_t LenV > +inline +#ifndef BOOST_LOG_DOXYGEN_PASS +typename enable_if< + is_same< T, const char >, + string_literal +>::type +#else +basic_string_literal< T > +#endif // BOOST_LOG_DOXYGEN_PASS +str_literal(T(&p)[LenV]) +{ + return string_literal(p); +} +#endif + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#ifdef BOOST_LOG_USE_WCHAR_T +template< typename T, std::size_t LenV > +inline typename enable_if< + is_same< T, const wchar_t >, + wstring_literal +>::type +str_literal(T(&p)[LenV]) +{ + return wstring_literal(p); +} +#endif + +#endif // BOOST_LOG_DOXYGEN_PASS + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_ diff --git a/boost/log/utility/string_literal_fwd.hpp b/boost/log/utility/string_literal_fwd.hpp new file mode 100644 index 0000000000..69f48986f3 --- /dev/null +++ b/boost/log/utility/string_literal_fwd.hpp @@ -0,0 +1,55 @@ +/* + * 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 string_literal_fwd.hpp + * \author Andrey Semashev + * \date 24.06.2007 + * + * The header contains forward declaration of a constant string literal wrapper. + */ + +#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_ + +#include <string> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief String literal wrapper + * + * The \c basic_string_literal is a thin wrapper around a constant string literal. + * It provides interface similar to STL strings, but because of read-only nature + * of string literals, lacks ability to modify string contents. However, + * \c basic_string_literal objects can be assigned to and cleared. + * + * The main advantage of this class comparing to other string classes is that + * it doesn't dynamically allocate memory and therefore is fast, thin and exception safe. + */ +template< typename CharT, typename TraitsT = std::char_traits< CharT > > +class basic_string_literal; + +// Convenience typedefs +#ifdef BOOST_LOG_USE_CHAR +typedef basic_string_literal< char > string_literal; //!< String literal type for narrow characters +#endif +#ifdef BOOST_LOG_USE_WCHAR_T +typedef basic_string_literal< wchar_t > wstring_literal; //!< String literal type for wide characters +#endif + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_ diff --git a/boost/log/utility/type_dispatch/date_time_types.hpp b/boost/log/utility/type_dispatch/date_time_types.hpp new file mode 100644 index 0000000000..5d91ab40c0 --- /dev/null +++ b/boost/log/utility/type_dispatch/date_time_types.hpp @@ -0,0 +1,138 @@ +/* + * 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 date_time_types.hpp + * \author Andrey Semashev + * \date 13.03.2008 + * + * The header contains definition of date and time-related types supported by the library by default. + */ + +#ifndef BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_ +#define BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_ + +#include <ctime> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/copy.hpp> +#include <boost/mpl/back_inserter.hpp> +#include <boost/mpl/push_back.hpp> +#include <boost/date_time/gregorian/gregorian_types.hpp> +#include <boost/date_time/local_time/local_time_types.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * An MPL-sequence of natively supported date and time types of attributes + */ +typedef mpl::vector< + std::time_t, + std::tm +> native_date_time_types; + +/*! + * An MPL-sequence of Boost date and time types of attributes + */ +typedef mpl::vector< + posix_time::ptime, + local_time::local_date_time +> boost_date_time_types; + +/*! + * An MPL-sequence with the complete list of the supported date and time types + */ +typedef mpl::copy< + boost_date_time_types, + mpl::back_inserter< native_date_time_types > +>::type date_time_types; + +/*! + * An MPL-sequence of natively supported date types of attributes + */ +typedef native_date_time_types native_date_types; + +/*! + * An MPL-sequence of Boost date types of attributes + */ +typedef mpl::push_back< + boost_date_time_types, + gregorian::date +>::type boost_date_types; + +/*! + * An MPL-sequence with the complete list of the supported date types + */ +typedef mpl::copy< + boost_date_types, + mpl::back_inserter< native_date_types > +>::type date_types; + +/*! + * An MPL-sequence of natively supported time types + */ +typedef native_date_time_types native_time_types; + +//! An MPL-sequence of Boost time types +typedef boost_date_time_types boost_time_types; + +/*! + * An MPL-sequence with the complete list of the supported time types + */ +typedef date_time_types time_types; + +/*! + * An MPL-sequence of natively supported time duration types of attributes + */ +typedef mpl::vector< + double // result of difftime +> native_time_duration_types; + +/*! + * An MPL-sequence of Boost time duration types of attributes + */ +typedef mpl::vector< + posix_time::time_duration, + gregorian::date_duration +> boost_time_duration_types; + +/*! + * An MPL-sequence with the complete list of the supported time duration types + */ +typedef mpl::copy< + boost_time_duration_types, + mpl::back_inserter< native_time_duration_types > +>::type time_duration_types; + +/*! + * An MPL-sequence of Boost time duration types of attributes + */ +typedef mpl::vector< + posix_time::time_period, + local_time::local_time_period, + gregorian::date_period +> boost_time_period_types; + +/*! + * An MPL-sequence with the complete list of the supported time period types + */ +typedef boost_time_period_types time_period_types; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_ diff --git a/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp b/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp new file mode 100644 index 0000000000..8fa3c82d33 --- /dev/null +++ b/boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp @@ -0,0 +1,154 @@ +/* + * 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 dynamic_type_dispatcher.hpp + * \author Andrey Semashev + * \date 15.04.2007 + * + * The header contains implementation of the run-time type dispatcher. + */ + +#ifndef BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_ +#define BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_ + +#include <new> +#include <memory> +#include <map> +#include <boost/ref.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared_object.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/visible_type.hpp> +#include <boost/log/utility/type_info_wrapper.hpp> +#include <boost/log/utility/type_dispatch/type_dispatcher.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief A dynamic type dispatcher + * + * The type dispatcher can be used to pass objects of arbitrary types from one + * component to another. With regard to the library, the type dispatcher + * can be used to extract attribute values. + * + * The dynamic type dispatcher can be initialized in run time and, therefore, + * can support different types, depending on runtime conditions. Each + * supported type is associated with a functional object that will be called + * when an object of the type is dispatched. + */ +class dynamic_type_dispatcher : + public type_dispatcher +{ +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + template< typename T, typename VisitorT > + class callback_impl : + public callback_base + { + private: + VisitorT m_Visitor; + + public: + explicit callback_impl(VisitorT const& visitor) : m_Visitor(visitor) + { + this->m_pVisitor = (void*)boost::addressof(m_Visitor); + typedef void (*trampoline_t)(void*, T const&); + BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); + union + { + void* as_pvoid; + trampoline_t as_trampoline; + } + caster; + caster.as_trampoline = &callback_base::trampoline< VisitorT, T >; + this->m_pTrampoline = caster.as_pvoid; + } + }; +#endif // BOOST_LOG_DOXYGEN_PASS + + //! The dispatching map + typedef std::map< type_info_wrapper, shared_ptr< callback_base > > dispatching_map; + dispatching_map m_DispatchingMap; + +public: + /*! + * Default constructor + */ + dynamic_type_dispatcher() : type_dispatcher(&dynamic_type_dispatcher::get_callback) + { + } + + /*! + * Copy constructor + */ + dynamic_type_dispatcher(dynamic_type_dispatcher const& that) : + type_dispatcher(static_cast< type_dispatcher const& >(that)), + m_DispatchingMap(that.m_DispatchingMap) + { + } + + /*! + * Copy assignment + */ + dynamic_type_dispatcher& operator= (dynamic_type_dispatcher const& that) + { + m_DispatchingMap = that.m_DispatchingMap; + return *this; + } + + /*! + * The method registers a new type + * + * \param visitor Function object that will be associated with the type \c T + */ + template< typename T, typename VisitorT > + void register_type(VisitorT const& visitor) + { + boost::shared_ptr< callback_base > p( + boost::make_shared< callback_impl< T, VisitorT > >(boost::cref(visitor))); + + type_info_wrapper wrapper(typeid(aux::visible_type< T >)); + m_DispatchingMap[wrapper].swap(p); + } + + /*! + * The method returns the number of registered types + */ + dispatching_map::size_type registered_types_count() const + { + return m_DispatchingMap.size(); + } + +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + static callback_base get_callback(type_dispatcher* p, std::type_info const& type) + { + dynamic_type_dispatcher* const self = static_cast< dynamic_type_dispatcher* >(p); + type_info_wrapper wrapper(type); + dispatching_map::iterator it = self->m_DispatchingMap.find(wrapper); + if (it != self->m_DispatchingMap.end()) + return *it->second; + else + return callback_base(); + } +#endif // BOOST_LOG_DOXYGEN_PASS +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_ diff --git a/boost/log/utility/type_dispatch/standard_types.hpp b/boost/log/utility/type_dispatch/standard_types.hpp new file mode 100644 index 0000000000..0bf6a1db24 --- /dev/null +++ b/boost/log/utility/type_dispatch/standard_types.hpp @@ -0,0 +1,105 @@ +/* + * 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 standard_types.hpp + * \author Andrey Semashev + * \date 19.05.2007 + * + * The header contains definition of standard types supported by the library by default. + */ + +#ifndef BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_ +#define BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_ + +#include <string> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/copy.hpp> +#include <boost/mpl/back_inserter.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/string_literal_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * An MPL-sequence of integral types of attributes, supported by default + */ +typedef mpl::vector< + bool, + char, +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + wchar_t, +#endif + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long +#if defined(BOOST_HAS_LONG_LONG) + , long long + , unsigned long long +#endif // defined(BOOST_HAS_LONG_LONG) +> integral_types; + +/*! + * An MPL-sequence of FP types of attributes, supported by default + */ +typedef mpl::vector< + float, + double, + long double +> floating_point_types; + +/*! + * An MPL-sequence of all numeric types of attributes, supported by default + */ +typedef mpl::copy< + floating_point_types, + mpl::back_inserter< integral_types > +>::type numeric_types; + +/*! + * An MPL-sequence of string types of attributes, supported by default + */ +typedef mpl::vector< +#ifdef BOOST_LOG_USE_CHAR + std::string, + string_literal +#ifdef BOOST_LOG_USE_WCHAR_T + , +#endif +#endif +#ifdef BOOST_LOG_USE_WCHAR_T + std::wstring, + wstring_literal +#endif +> string_types; + +/*! + * An MPL-sequence of all attribute value types that are supported by the library by default. + */ +typedef mpl::copy< + string_types, + mpl::back_inserter< numeric_types > +>::type default_attribute_types; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_ diff --git a/boost/log/utility/type_dispatch/static_type_dispatcher.hpp b/boost/log/utility/type_dispatch/static_type_dispatcher.hpp new file mode 100644 index 0000000000..73cf21b243 --- /dev/null +++ b/boost/log/utility/type_dispatch/static_type_dispatcher.hpp @@ -0,0 +1,319 @@ +/* + * 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 static_type_dispatcher.hpp + * \author Andrey Semashev + * \date 15.04.2007 + * + * The header contains implementation of a compile-time type dispatcher. + */ + +#ifndef BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_ +#define BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_ + +#include <cstddef> +#include <utility> +#include <iterator> +#include <algorithm> +#include <boost/array.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/size.hpp> +#include <boost/mpl/begin.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/deref.hpp> +#include <boost/mpl/next.hpp> +#include <boost/mpl/is_sequence.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/visible_type.hpp> +#include <boost/log/utility/once_block.hpp> +#include <boost/log/utility/type_info_wrapper.hpp> +#include <boost/log/utility/type_dispatch/type_dispatcher.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Ordering predicate for type dispatching map +struct dispatching_map_order +{ + typedef bool result_type; + typedef std::pair< type_info_wrapper, void* > first_argument_type, second_argument_type; + result_type operator() (first_argument_type const& left, second_argument_type const& right) const + { + return (left.first < right.first); + } +}; + +//! Dispatching map filler +template< typename VisitorT > +struct dispatching_map_initializer +{ + template< typename IteratorT > + static BOOST_FORCEINLINE void init(IteratorT*, IteratorT*, std::pair< type_info_wrapper, void* >*) + { + } + + template< typename BeginIteratorT, typename EndIteratorT > + static BOOST_FORCEINLINE void init(BeginIteratorT*, EndIteratorT* end, std::pair< type_info_wrapper, void* >* p) + { + typedef typename mpl::deref< BeginIteratorT >::type type; + do_init(static_cast< visible_type< type >* >(0), p); + + typedef typename mpl::next< BeginIteratorT >::type next_iterator_type; + init(static_cast< next_iterator_type* >(0), end, p + 1); + } + +private: + template< typename T > + static BOOST_FORCEINLINE void do_init(visible_type< T >*, std::pair< type_info_wrapper, void* >* p) + { + p->first = typeid(visible_type< T >); + + typedef void (*trampoline_t)(void*, T const&); + BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); + union + { + void* as_pvoid; + trampoline_t as_trampoline; + } + caster; + caster.as_trampoline = &type_dispatcher::callback_base::trampoline< VisitorT, T >; + p->second = caster.as_pvoid; + } +}; + +//! A base class for a dispatcher that supports a sequence of types +class type_sequence_dispatcher_base : + public type_dispatcher +{ +private: + //! Dispatching map element type + typedef std::pair< type_info_wrapper, void* > dispatching_map_element_type; + +private: + //! Dispatching map + const dispatching_map_element_type* m_dispatching_map_begin; + //! Dispatching map size + std::size_t m_dispatching_map_size; + //! Pointer to the receiver function + void* m_visitor; + +protected: + //! Initializing constructor + type_sequence_dispatcher_base(const dispatching_map_element_type* disp_map, std::size_t disp_map_size, void* visitor) BOOST_NOEXCEPT : + type_dispatcher(&type_sequence_dispatcher_base::get_callback), + m_dispatching_map_begin(disp_map), + m_dispatching_map_size(disp_map_size), + m_visitor(visitor) + { + } + +private: + //! The get_callback method implementation + static callback_base get_callback(type_dispatcher* p, std::type_info const& type) + { + type_sequence_dispatcher_base* const self = static_cast< type_sequence_dispatcher_base* >(p); + type_info_wrapper wrapper(type); + const dispatching_map_element_type* begin = self->m_dispatching_map_begin; + const dispatching_map_element_type* end = begin + self->m_dispatching_map_size; + const dispatching_map_element_type* it = std::lower_bound + ( + begin, + end, + dispatching_map_element_type(wrapper, (void*)0), + dispatching_map_order() + ); + + if (it != end && it->first == wrapper) + return callback_base(self->m_visitor, it->second); + else + return callback_base(); + } + + // Copying and assignment closed + BOOST_DELETED_FUNCTION(type_sequence_dispatcher_base(type_sequence_dispatcher_base const&)) + BOOST_DELETED_FUNCTION(type_sequence_dispatcher_base& operator= (type_sequence_dispatcher_base const&)) +}; + +//! A dispatcher that supports a sequence of types +template< typename TypeSequenceT > +class type_sequence_dispatcher : + public type_sequence_dispatcher_base +{ +public: + //! Type sequence of the supported types + typedef TypeSequenceT supported_types; + +private: + //! The dispatching map + typedef array< + std::pair< type_info_wrapper, void* >, + mpl::size< supported_types >::value + > dispatching_map; + +public: + /*! + * Constructor. Initializes the dispatcher internals. + */ + template< typename VisitorT > + explicit type_sequence_dispatcher(VisitorT& visitor) : + type_sequence_dispatcher_base(get_dispatching_map< VisitorT >().data(), dispatching_map::static_size, (void*)boost::addressof(visitor)) + { + } + +private: + //! The method returns the dispatching map instance + template< typename VisitorT > + static dispatching_map const& get_dispatching_map() + { + static const dispatching_map* pinstance = NULL; + + BOOST_LOG_ONCE_BLOCK() + { + static dispatching_map instance; + typename dispatching_map::value_type* p = &*instance.begin(); + + typedef typename mpl::begin< supported_types >::type begin_iterator_type; + typedef typename mpl::end< supported_types >::type end_iterator_type; + typedef dispatching_map_initializer< VisitorT > initializer; + initializer::init(static_cast< begin_iterator_type* >(0), static_cast< end_iterator_type* >(0), p); + + std::sort(instance.begin(), instance.end(), dispatching_map_order()); + + pinstance = &instance; + } + + return *pinstance; + } + + // Copying and assignment closed + BOOST_DELETED_FUNCTION(type_sequence_dispatcher(type_sequence_dispatcher const&)) + BOOST_DELETED_FUNCTION(type_sequence_dispatcher& operator= (type_sequence_dispatcher const&)) +}; + +//! A base class for a single-type dispatcher +class single_type_dispatcher_base : + public type_dispatcher +{ +private: + //! The type to match against + std::type_info const& m_type; + //! A callback for the supported type + callback_base m_callback; + +protected: + //! Initializing constructor + single_type_dispatcher_base(std::type_info const& type, callback_base const& callback) BOOST_NOEXCEPT : + type_dispatcher(&single_type_dispatcher_base::get_callback), + m_type(type), + m_callback(callback) + { + } + +private: + //! The get_callback method implementation + static callback_base get_callback(type_dispatcher* p, std::type_info const& type) + { + single_type_dispatcher_base* const self = static_cast< single_type_dispatcher_base* >(p); + if (type == self->m_type) + return self->m_callback; + else + return callback_base(); + } + + // Copying and assignment closed + BOOST_DELETED_FUNCTION(single_type_dispatcher_base(single_type_dispatcher_base const&)) + BOOST_DELETED_FUNCTION(single_type_dispatcher_base& operator= (single_type_dispatcher_base const&)) +}; + +//! A simple dispatcher that only supports one type +template< typename T > +class single_type_dispatcher : + public single_type_dispatcher_base +{ +public: + //! Constructor + template< typename VisitorT > + explicit single_type_dispatcher(VisitorT& visitor) BOOST_NOEXCEPT : + single_type_dispatcher_base(typeid(visible_type< T >), callback_base((void*)boost::addressof(visitor), &callback_base::trampoline< VisitorT, T >)) + { + } + + // Copying and assignment closed + BOOST_DELETED_FUNCTION(single_type_dispatcher(single_type_dispatcher const&)) + BOOST_DELETED_FUNCTION(single_type_dispatcher& operator= (single_type_dispatcher const&)) +}; + +} // namespace aux + +/*! + * \brief A static type dispatcher class + * + * The type dispatcher can be used to pass objects of arbitrary types from one + * component to another. With regard to the library, the type dispatcher + * can be used to extract attribute values. + * + * Static type dispatchers allow to specify one or several supported types at compile + * time. + */ +template< typename T > +class static_type_dispatcher +#ifndef BOOST_LOG_DOXYGEN_PASS + : + public mpl::if_< + mpl::is_sequence< T >, + boost::log::aux::type_sequence_dispatcher< T >, + boost::log::aux::single_type_dispatcher< T > + >::type +#endif +{ +private: + //! Base type + typedef typename mpl::if_< + mpl::is_sequence< T >, + boost::log::aux::type_sequence_dispatcher< T >, + boost::log::aux::single_type_dispatcher< T > + >::type base_type; + +public: + /*! + * Constructor. Initializes the dispatcher internals. + * + * The \a receiver object is not copied inside the dispatcher, but references to + * it may be kept by the dispatcher after construction. The receiver object must remain + * valid until the dispatcher is destroyed. + * + * \param receiver Unary function object that will be called on a dispatched value. The receiver + * must be callable with an argument of any of the supported types of the dispatcher. + */ + template< typename ReceiverT > + explicit static_type_dispatcher(ReceiverT& receiver) : + base_type(receiver) + { + } + + // Copying and assignment prohibited + BOOST_DELETED_FUNCTION(static_type_dispatcher(static_type_dispatcher const&)) + BOOST_DELETED_FUNCTION(static_type_dispatcher& operator= (static_type_dispatcher const&)) +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_ diff --git a/boost/log/utility/type_dispatch/type_dispatcher.hpp b/boost/log/utility/type_dispatch/type_dispatcher.hpp new file mode 100644 index 0000000000..36e1ce8b05 --- /dev/null +++ b/boost/log/utility/type_dispatch/type_dispatcher.hpp @@ -0,0 +1,189 @@ +/* + * 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 type_dispatcher.hpp + * \author Andrey Semashev + * \date 15.04.2007 + * + * The header contains definition of generic type dispatcher interfaces. + */ + +#ifndef BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ +#define BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ + +#include <typeinfo> +#include <boost/static_assert.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/visible_type.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief A type dispatcher interface + * + * All type dispatchers support this interface. It is used to acquire the + * visitor interface for the requested type. + */ +class type_dispatcher +{ +public: + +#ifndef BOOST_LOG_DOXYGEN_PASS + + //! The base class for type dispatcher callbacks + class callback_base + { + protected: + void* m_pVisitor; + void* m_pTrampoline; + + public: + explicit callback_base(void* visitor = 0, void* tramp = 0) BOOST_NOEXCEPT : + m_pVisitor(visitor), + m_pTrampoline(tramp) + { + } + template< typename ValueT > + explicit callback_base(void* visitor, void (*tramp)(void*, ValueT const&)) BOOST_NOEXCEPT : + m_pVisitor(visitor) + { + typedef void (*trampoline_t)(void*, ValueT const&); + BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); + union + { + void* as_pvoid; + trampoline_t as_trampoline; + } + caster; + caster.as_trampoline = tramp; + m_pTrampoline = caster.as_pvoid; + } + + template< typename VisitorT, typename T > + static void trampoline(void* visitor, T const& value) + { + (*static_cast< VisitorT* >(visitor))(value); + } + }; + + //! An interface to the callback for the concrete type visitor + template< typename T > + class callback : + private callback_base + { + private: + //! Type of the trampoline method + typedef void (*trampoline_t)(void*, T const&); + + public: + //! The type, which the visitor is able to consume + typedef T supported_type; + + public: + callback() BOOST_NOEXCEPT : callback_base() + { + } + explicit callback(callback_base const& base) BOOST_NOEXCEPT : callback_base(base) + { + } + + void operator() (T const& value) const + { + BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); + union + { + void* as_pvoid; + trampoline_t as_trampoline; + } + caster; + caster.as_pvoid = this->m_pTrampoline; + (caster.as_trampoline)(this->m_pVisitor, value); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + bool operator! () const BOOST_NOEXCEPT { return (this->m_pVisitor == 0); } + }; + +#else // BOOST_LOG_DOXYGEN_PASS + + /*! + * This interface is used by type dispatchers to consume the dispatched value. + */ + template< typename T > + class callback + { + public: + /*! + * The operator invokes the visitor-specific logic with the given value + * + * \param value The dispatched value + */ + void operator() (T const& value) const; + + /*! + * The operator checks if the visitor is attached to a receiver + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * The operator checks if the visitor is not attached to a receiver + */ + bool operator! () const BOOST_NOEXCEPT; + }; + +#endif // BOOST_LOG_DOXYGEN_PASS + +protected: + //! Pointer to the callback acquisition method + typedef callback_base (*get_callback_impl_type)(type_dispatcher*, std::type_info const&); + +private: + //! Pointer to the callback acquisition method + get_callback_impl_type m_get_callback_impl; + +protected: + /*! + * Initializing constructor + */ + explicit type_dispatcher(get_callback_impl_type get_callback_impl) BOOST_NOEXCEPT : m_get_callback_impl(get_callback_impl) + { + } + + // Destructor and copying can only be called from the derived classes + BOOST_DEFAULTED_FUNCTION(~type_dispatcher(), {}) + BOOST_DEFAULTED_FUNCTION(type_dispatcher(type_dispatcher const& that), : m_get_callback_impl(that.m_get_callback_impl) {}) + BOOST_DEFAULTED_FUNCTION(type_dispatcher& operator= (type_dispatcher const& that), { m_get_callback_impl = that.m_get_callback_impl; return *this; }) + +public: + /*! + * The method requests a callback for the value of type \c T + * + * \return The type-specific callback or an empty value, if the type is not supported + */ + template< typename T > + callback< T > get_callback() + { + return callback< T >((this->m_get_callback_impl)(this, typeid(boost::log::aux::visible_type< T >))); + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ diff --git a/boost/log/utility/type_info_wrapper.hpp b/boost/log/utility/type_info_wrapper.hpp new file mode 100644 index 0000000000..8ce4ea2414 --- /dev/null +++ b/boost/log/utility/type_info_wrapper.hpp @@ -0,0 +1,188 @@ +/* + * 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 type_info_wrapper.hpp + * \author Andrey Semashev + * \date 15.04.2007 + * + * The header contains implementation of a type information wrapper. + */ + +#ifndef BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_ + +#include <typeinfo> +#include <string> +#include <boost/core/demangle.hpp> +#include <boost/core/explicit_operator_bool.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief A simple <tt>std::type_info</tt> wrapper that implements value semantic for type information objects + * + * The type info wrapper is very useful for storing type information objects in containers, + * as a key or value. It also provides a number of useful features, such as default construction + * and assignment support, an empty state and extended support for human-friendly type names. + */ +class type_info_wrapper +{ +private: +#ifndef BOOST_LOG_DOXYGEN_PASS + //! An inaccessible type to indicate an uninitialized state of the wrapper + struct BOOST_SYMBOL_VISIBLE uninitialized {}; +#endif // BOOST_LOG_DOXYGEN_PASS + +private: + //! A pointer to the actual type info + std::type_info const* info; + +public: + /*! + * Default constructor + * + * \post <tt>!*this == true</tt> + */ + type_info_wrapper() BOOST_NOEXCEPT : info(&typeid(uninitialized)) {} + /*! + * Copy constructor + * + * \post <tt>*this == that</tt> + * \param that Source type info wrapper to copy from + */ + type_info_wrapper(type_info_wrapper const& that) BOOST_NOEXCEPT : info(that.info) {} + /*! + * Conversion constructor + * + * \post <tt>*this == that && !!*this</tt> + * \param that Type info object to be wrapped + */ + type_info_wrapper(std::type_info const& that) BOOST_NOEXCEPT : info(&that) {} + + /*! + * \return \c true if the type info wrapper was initialized with a particular type, + * \c false if the wrapper was default-constructed and not yet initialized + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * Stored type info getter + * + * \pre <tt>!!*this</tt> + * \return Constant reference to the wrapped type info object + */ + std::type_info const& get() const BOOST_NOEXCEPT { return *info; } + + /*! + * Swaps two instances of the wrapper + */ + void swap(type_info_wrapper& that) BOOST_NOEXCEPT + { + std::type_info const* temp = info; + info = that.info; + that.info = temp; + } + + /*! + * The method returns the contained type name string in a possibly more readable format than <tt>get().name()</tt> + * + * \pre <tt>!!*this</tt> + * \return Type name string + */ + std::string pretty_name() const + { + if (!this->operator!()) + return boost::core::demangle(info->name()); + else + return "[uninitialized]"; + } + + /*! + * \return \c false if the type info wrapper was initialized with a particular type, + * \c true if the wrapper was default-constructed and not yet initialized + */ + bool operator! () const BOOST_NOEXCEPT { return (info == &typeid(uninitialized) || *info == typeid(uninitialized)); } + + /*! + * Equality comparison + * + * \param that Comparand + * \return If either this object or comparand is in empty state and the other is not, the result is \c false. + * If both arguments are empty, the result is \c true. If both arguments are not empty, the result + * is \c true if this object wraps the same type as the comparand and \c false otherwise. + */ + bool operator== (type_info_wrapper const& that) const BOOST_NOEXCEPT + { + return (info == that.info || *info == *that.info); + } + /*! + * Ordering operator + * + * \pre <tt>!!*this && !!that</tt> + * \param that Comparand + * \return \c true if this object wraps type info object that is ordered before + * the type info object in the comparand, \c false otherwise + * \note The results of this operator are only consistent within a single run of application. + * The result may change for the same types after rebuilding or even restarting the application. + */ + bool operator< (type_info_wrapper const& that) const BOOST_NOEXCEPT + { + return static_cast< bool >(info->before(*that.info)); + } +}; + +//! Inequality operator +inline bool operator!= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT +{ + return !left.operator==(right); +} + +//! Ordering operator +inline bool operator<= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT +{ + return (left.operator==(right) || left.operator<(right)); +} + +//! Ordering operator +inline bool operator> (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT +{ + return !(left.operator==(right) || left.operator<(right)); +} + +//! Ordering operator +inline bool operator>= (type_info_wrapper const& left, type_info_wrapper const& right) BOOST_NOEXCEPT +{ + return !left.operator<(right); +} + +//! Free swap for type info wrapper +inline void swap(type_info_wrapper& left, type_info_wrapper& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +//! The function for exception serialization to string +inline std::string to_string(type_info_wrapper const& ti) +{ + return ti.pretty_name(); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_TYPE_INFO_WRAPPER_HPP_INCLUDED_ diff --git a/boost/log/utility/unique_identifier_name.hpp b/boost/log/utility/unique_identifier_name.hpp new file mode 100644 index 0000000000..ad25296e55 --- /dev/null +++ b/boost/log/utility/unique_identifier_name.hpp @@ -0,0 +1,51 @@ +/* + * 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 unique_identifier_name.hpp + * \author Andrey Semashev + * \date 30.04.2008 + * + * The header contains \c BOOST_LOG_UNIQUE_IDENTIFIER_NAME macro definition. + */ + +#ifndef BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_ + +#include <boost/preprocessor/cat.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_DOXYGEN_PASS + +#define BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL_(prefix, postfix)\ + BOOST_PP_CAT(prefix, postfix) +#define BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, postfix)\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL_(prefix, postfix) + +#endif // BOOST_LOG_DOXYGEN_PASS + +/*! + * \def BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix) + * + * Constructs a unique (in the current file scope) token that can be used as a variable name. + * The name will contain a prefix passed in the \a prefix argument. This allows to use the + * macro multiple times on a single line. + */ + +// In VC 7.0 and later when compiling with /ZI option __LINE__ macro is corrupted +#ifdef BOOST_MSVC +# define BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, __COUNTER__) +#else +# define BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)\ + BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, __LINE__) +#endif // BOOST_MSVC + +#endif // BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_ diff --git a/boost/log/utility/unused_variable.hpp b/boost/log/utility/unused_variable.hpp new file mode 100644 index 0000000000..816e102533 --- /dev/null +++ b/boost/log/utility/unused_variable.hpp @@ -0,0 +1,51 @@ +/* + * 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 unused_variable.hpp + * \author Andrey Semashev + * \date 10.05.2008 + * + * The header contains definition of a macro to suppress compiler warnings about unused variables. + */ + +#ifndef BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GNUC__) + +//! The macro suppresses compiler warnings for \c var being unused +#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) __attribute__((unused)) type var initializer + +#else + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +BOOST_FORCEINLINE void no_unused_warnings(T const&) BOOST_NOEXCEPT {} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +//! The macro suppresses compiler warnings for \c var being unused +#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) type var initializer; ::boost::log::aux::no_unused_warnings(var) + +#endif + +#endif // BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_ diff --git a/boost/log/utility/value_ref.hpp b/boost/log/utility/value_ref.hpp new file mode 100644 index 0000000000..08fda4c553 --- /dev/null +++ b/boost/log/utility/value_ref.hpp @@ -0,0 +1,630 @@ +/* + * 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 value_ref.hpp + * \author Andrey Semashev + * \date 27.07.2012 + * + * The header contains implementation of a value reference wrapper. + */ + +#ifndef BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_ + +#include <cstddef> +#include <iosfwd> +#include <boost/assert.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/is_sequence.hpp> +#include <boost/mpl/front.hpp> +#include <boost/mpl/size.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/and.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/equal_to.hpp> +#include <boost/mpl/contains.hpp> +#include <boost/mpl/index_of.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/optional/optional_fwd.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/parameter_tools.hpp> +#include <boost/log/detail/value_ref_visitation.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/utility/formatting_ostream_fwd.hpp> +#include <boost/log/utility/functional/logical.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/utility/functional/bind_output.hpp> +#include <boost/log/utility/functional/bind_to_log.hpp> +#include <boost/log/utility/manipulators/to_log.hpp> +#include <boost/log/utility/value_ref_fwd.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The function object applies the function object to the bound visitable object and argument +template< typename VisitableT, typename FunT > +struct vistation_invoker +{ + typedef typename FunT::result_type result_type; + + vistation_invoker(VisitableT& visitable, result_type const& def_val) : m_visitable(visitable), m_def_val(def_val) + { + } + + template< typename ArgT > + result_type operator() (ArgT const& arg) const + { + return m_visitable.apply_visitor_or_default(binder1st< FunT, ArgT const& >(FunT(), arg), m_def_val); + } + +private: + VisitableT& m_visitable; + result_type m_def_val; +}; + +//! Attribute value reference implementation for a single type case +template< typename T, typename TagT > +class singular_ref +{ +public: + //! Referenced value type + typedef T value_type; + //! Tag type + typedef TagT tag_type; + +protected: + //! The metafunction tests if the type is compatible with the reference wrapper +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template< typename U > + using is_compatible = is_same< U, value_type >; +#else + template< typename U > + struct is_compatible : + public is_same< U, value_type > + { + }; +#endif + +protected: + //! Pointer to the value + const value_type* m_ptr; + +protected: + //! Default constructor + singular_ref() BOOST_NOEXCEPT : m_ptr(NULL) + { + } + + //! Initializing constructor + explicit singular_ref(const value_type* p) BOOST_NOEXCEPT : m_ptr(p) + { + } + +public: + //! Returns a pointer to the referred value + const value_type* operator-> () const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_ptr != NULL); + return m_ptr; + } + + //! Returns a pointer to the referred value + const value_type* get_ptr() const BOOST_NOEXCEPT + { + return m_ptr; + } + + //! Returns a pointer to the referred value + template< typename U > + typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT + { + return m_ptr; + } + + //! Returns a reference to the value + value_type const& operator* () const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_ptr != NULL); + return *m_ptr; + } + + //! Returns a reference to the value + value_type const& get() const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_ptr != NULL); + return *m_ptr; + } + + //! Returns a reference to the value + template< typename U > + typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT + { + BOOST_ASSERT(m_ptr != NULL); + return *m_ptr; + } + + + //! Resets the reference + void reset() BOOST_NOEXCEPT + { + m_ptr = NULL; + } + + //! Returns the stored type index + static BOOST_CONSTEXPR unsigned int which() + { + return 0u; + } + + //! Swaps two reference wrappers + void swap(singular_ref& that) BOOST_NOEXCEPT + { + const void* p = m_ptr; + m_ptr = that.m_ptr; + that.m_ptr = p; + } + + //! Applies a visitor function object to the referred value + template< typename VisitorT > + typename VisitorT::result_type apply_visitor(VisitorT visitor) const + { + BOOST_ASSERT(m_ptr != NULL); + return visitor(*m_ptr); + } + + //! Applies a visitor function object to the referred value + template< typename VisitorT > + typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const + { + if (m_ptr) + { + visitor(*m_ptr); + return true; + } + else + return false; + } + + //! Applies a visitor function object to the referred value + template< typename VisitorT > + typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const + { + typedef optional< typename VisitorT::result_type > result_type; + if (m_ptr) + return result_type(visitor(*m_ptr)); + else + return result_type(); + } + + //! Applies a visitor function object to the referred value or returns a default value + template< typename VisitorT, typename DefaultT > + typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const + { + if (m_ptr) + return visitor(*m_ptr); + else + return def_val; + } + + //! Applies a visitor function object to the referred value or returns a default value + template< typename VisitorT, typename DefaultT > + typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const + { + if (m_ptr) + return visitor(*m_ptr); + else + return def_val; + } +}; + +//! Attribute value reference implementation for multiple types case +template< typename T, typename TagT > +class variant_ref +{ +public: + //! Referenced value type + typedef T value_type; + //! Tag type + typedef TagT tag_type; + +protected: + //! The metafunction tests if the type is compatible with the reference wrapper +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template< typename U > + using is_compatible = mpl::contains< value_type, U >; +#else + template< typename U > + struct is_compatible : + public mpl::contains< value_type, U > + { + }; +#endif + +protected: + //! Pointer to the value + const void* m_ptr; + //! Type index + unsigned int m_type_idx; + +protected: + //! Default constructor + variant_ref() BOOST_NOEXCEPT : m_ptr(NULL), m_type_idx(0) + { + } + + //! Initializing constructor + template< typename U > + explicit variant_ref(const U* p) BOOST_NOEXCEPT : m_ptr(p), m_type_idx(mpl::index_of< value_type, U >::type::value) + { + } + +public: + //! Resets the reference + void reset() BOOST_NOEXCEPT + { + m_ptr = NULL; + m_type_idx = 0; + } + + //! Returns a pointer to the referred value + template< typename U > + typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT + { + if (m_type_idx == static_cast< unsigned int >(mpl::index_of< value_type, U >::type::value)) + return static_cast< const U* >(m_ptr); + else + return NULL; + } + + //! Returns a reference to the value + template< typename U > + typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT + { + const U* const p = get_ptr< U >(); + BOOST_ASSERT(p != NULL); + return *p; + } + + //! Returns the stored type index + unsigned int which() const BOOST_NOEXCEPT + { + return m_type_idx; + } + + //! Swaps two reference wrappers + void swap(variant_ref& that) BOOST_NOEXCEPT + { + const void* p = m_ptr; + m_ptr = that.m_ptr; + that.m_ptr = p; + unsigned int type_idx = m_type_idx; + m_type_idx = that.m_type_idx; + that.m_type_idx = type_idx; + } + + //! Applies a visitor function object to the referred value + template< typename VisitorT > + typename VisitorT::result_type apply_visitor(VisitorT visitor) const + { + BOOST_ASSERT(m_ptr != NULL); + return do_apply_visitor(visitor); + } + + //! Applies a visitor function object to the referred value + template< typename VisitorT > + typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const + { + if (m_ptr) + { + do_apply_visitor(visitor); + return true; + } + else + return false; + } + + //! Applies a visitor function object to the referred value + template< typename VisitorT > + typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const + { + typedef optional< typename VisitorT::result_type > result_type; + if (m_ptr) + return result_type(do_apply_visitor(visitor)); + else + return result_type(); + } + + //! Applies a visitor function object to the referred value or returns a default value + template< typename VisitorT, typename DefaultT > + typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const + { + if (m_ptr) + return do_apply_visitor(visitor); + else + return def_val; + } + + //! Applies a visitor function object to the referred value or returns a default value + template< typename VisitorT, typename DefaultT > + typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const + { + if (m_ptr) + return do_apply_visitor(visitor); + else + return def_val; + } + +private: + template< typename VisitorT > + typename VisitorT::result_type do_apply_visitor(VisitorT& visitor) const + { + BOOST_ASSERT(m_type_idx < static_cast< unsigned int >(mpl::size< value_type >::value)); + return apply_visitor_dispatch< value_type, VisitorT >::call(m_ptr, m_type_idx, visitor); + } +}; + +template< typename T, typename TagT > +struct value_ref_base +{ + typedef typename mpl::eval_if< + mpl::and_< mpl::is_sequence< T >, mpl::equal_to< mpl::size< T >, mpl::int_< 1 > > >, + mpl::front< T >, + mpl::identity< T > + >::type value_type; + + typedef typename mpl::if_< + mpl::is_sequence< value_type >, + variant_ref< value_type, TagT >, + singular_ref< value_type, TagT > + >::type type; +}; + +} // namespace aux + +/*! + * \brief Reference wrapper for a stored attribute value. + * + * The \c value_ref class template provides access to the stored attribute value. It is not a traditional reference wrapper + * since it may be empty (i.e. refer to no value at all) and it can also refer to values of different types. Therefore its + * interface and behavior combines features of Boost.Ref, Boost.Optional and Boost.Variant, depending on the use case. + * + * The template parameter \c T can be a single type or an MPL sequence of possible types being referred. The reference wrapper + * will act as either an optional reference or an optional variant of references to the specified types. In any case, the + * referred values will not be modifiable (i.e. \c value_ref always models a const reference). + * + * Template parameter \c TagT is optional. It can be used for customizing the operations on this reference wrapper, such as + * putting the referred value to log. + */ +template< typename T, typename TagT > +class value_ref : + public aux::value_ref_base< T, TagT >::type +{ +#ifndef BOOST_LOG_DOXYGEN_PASS +public: + typedef void _has_basic_formatting_ostream_insert_operator; +#endif + +private: + //! Base implementation type + typedef typename aux::value_ref_base< T, TagT >::type base_type; + +public: + /*! + * Default constructor. Creates a reference wrapper that does not refer to a value. + */ + BOOST_DEFAULTED_FUNCTION(value_ref(), BOOST_NOEXCEPT {}) + + /*! + * Copy constructor. + */ + BOOST_DEFAULTED_FUNCTION(value_ref(value_ref const& that), BOOST_NOEXCEPT : base_type(static_cast< base_type const& >(that)) {}) + + /*! + * Initializing constructor. Creates a reference wrapper that refers to the specified value. + */ + template< typename U > + explicit value_ref(U const& val, typename enable_if< typename base_type::BOOST_NESTED_TEMPLATE is_compatible< U >, int >::type = 0) BOOST_NOEXCEPT : + base_type(boost::addressof(val)) + { + } + + /*! + * The operator verifies if the wrapper refers to a value. + */ + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /*! + * The operator verifies if the wrapper does not refer to a value. + */ + bool operator! () const BOOST_NOEXCEPT + { + return !this->m_ptr; + } + + /*! + * \return \c true if the wrapper does not refer to a value. + */ + bool empty() const BOOST_NOEXCEPT + { + return !this->m_ptr; + } + + /*! + * Swaps two reference wrappers + */ + void swap(value_ref& that) BOOST_NOEXCEPT + { + base_type::swap(that); + } +}; + +//! Free swap function +template< typename T, typename TagT > +inline void swap(value_ref< T, TagT >& left, value_ref< T, TagT >& right) +{ + left.swap(right); +} + +//! Stream output operator +template< typename CharT, typename TraitsT, typename T, typename TagT > +inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, value_ref< T, TagT > const& val) +{ + if (!!val) + val.apply_visitor(boost::log::bind_output(strm)); + return strm; +} + +//! Log formatting operator +template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT > +inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, value_ref< T, TagT > const& val) +{ + if (!!val) + val.apply_visitor(boost::log::bind_to_log< TagT >(strm)); + return strm; +} + +// Equality comparison +template< typename T, typename TagT, typename U > +inline bool operator== (value_ref< T, TagT > const& left, U const& right) +{ + return left.apply_visitor_or_default(binder2nd< equal_to, U const& >(equal_to(), right), false); +} + +template< typename U, typename T, typename TagT > +inline bool operator== (U const& left, value_ref< T, TagT > const& right) +{ + return right.apply_visitor_or_default(binder1st< equal_to, U const& >(equal_to(), left), false); +} + +template< typename T1, typename TagT1, typename T2, typename TagT2 > +inline bool operator== (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right) +{ + if (!left && !right) + return true; + return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, equal_to >(right, false), false); +} + +// Inequality comparison +template< typename T, typename TagT, typename U > +inline bool operator!= (value_ref< T, TagT > const& left, U const& right) +{ + return left.apply_visitor_or_default(binder2nd< not_equal_to, U const& >(not_equal_to(), right), false); +} + +template< typename U, typename T, typename TagT > +inline bool operator!= (U const& left, value_ref< T, TagT > const& right) +{ + return right.apply_visitor_or_default(binder1st< not_equal_to, U const& >(not_equal_to(), left), false); +} + +template< typename T1, typename TagT1, typename T2, typename TagT2 > +inline bool operator!= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right) +{ + if (!left && !right) + return false; + return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, not_equal_to >(right, false), false); +} + +// Less than ordering +template< typename T, typename TagT, typename U > +inline bool operator< (value_ref< T, TagT > const& left, U const& right) +{ + return left.apply_visitor_or_default(binder2nd< less, U const& >(less(), right), false); +} + +template< typename U, typename T, typename TagT > +inline bool operator< (U const& left, value_ref< T, TagT > const& right) +{ + return right.apply_visitor_or_default(binder1st< less, U const& >(less(), left), false); +} + +template< typename T1, typename TagT1, typename T2, typename TagT2 > +inline bool operator< (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right) +{ + return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less >(right, false), false); +} + +// Greater than ordering +template< typename T, typename TagT, typename U > +inline bool operator> (value_ref< T, TagT > const& left, U const& right) +{ + return left.apply_visitor_or_default(binder2nd< greater, U const& >(greater(), right), false); +} + +template< typename U, typename T, typename TagT > +inline bool operator> (U const& left, value_ref< T, TagT > const& right) +{ + return right.apply_visitor_or_default(binder1st< greater, U const& >(greater(), left), false); +} + +template< typename T1, typename TagT1, typename T2, typename TagT2 > +inline bool operator> (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right) +{ + return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater >(right, false), false); +} + +// Less or equal ordering +template< typename T, typename TagT, typename U > +inline bool operator<= (value_ref< T, TagT > const& left, U const& right) +{ + return left.apply_visitor_or_default(binder2nd< less_equal, U const& >(less_equal(), right), false); +} + +template< typename U, typename T, typename TagT > +inline bool operator<= (U const& left, value_ref< T, TagT > const& right) +{ + return right.apply_visitor_or_default(binder1st< less_equal, U const& >(less_equal(), left), false); +} + +template< typename T1, typename TagT1, typename T2, typename TagT2 > +inline bool operator<= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right) +{ + if (!left && !right) + return true; + return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less_equal >(right, false), false); +} + +// Greater or equal ordering +template< typename T, typename TagT, typename U > +inline bool operator>= (value_ref< T, TagT > const& left, U const& right) +{ + return left.apply_visitor_or_default(binder2nd< greater_equal, U const& >(greater_equal(), right), false); +} + +template< typename U, typename T, typename TagT > +inline bool operator>= (U const& left, value_ref< T, TagT > const& right) +{ + return right.apply_visitor_or_default(binder1st< greater_equal, U const& >(greater_equal(), left), false); +} + +template< typename T1, typename TagT1, typename T2, typename TagT2 > +inline bool operator>= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right) +{ + if (!left && !right) + return true; + return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater_equal >(right, false), false); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_ diff --git a/boost/log/utility/value_ref_fwd.hpp b/boost/log/utility/value_ref_fwd.hpp new file mode 100644 index 0000000000..aa4fa20225 --- /dev/null +++ b/boost/log/utility/value_ref_fwd.hpp @@ -0,0 +1,38 @@ +/* + * 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 value_ref_fwd.hpp + * \author Andrey Semashev + * \date 27.07.2012 + * + * The header contains forward declaration of a value reference wrapper. + */ + +#ifndef BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_ +#define BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +/*! + * \brief Reference wrapper for a stored attribute value. + */ +template< typename T, typename TagT = void > +class value_ref; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_ |