stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,38 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,191 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute.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_
@@ -0,0 +1,74 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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_
@@ -0,0 +1,185 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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_
@@ -0,0 +1,514 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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)
BOOST_FORCEINLINE operator mapped_type() const BOOST_NOEXCEPT
{
return read_mapped_value();
}
//! Assignment operator (would be invoked in case of writing to the container)
mapped_type& operator= (mapped_type const& val) const;
private:
//! Reads the referenced mapped value from the container
mapped_type read_mapped_value() const BOOST_NOEXCEPT;
};
} // 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 {
//! Reads the referenced mapped value from the container
inline attribute_set_reference_proxy::mapped_type attribute_set_reference_proxy::read_mapped_value() 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_
@@ -0,0 +1,380 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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/type_index.hpp>
#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_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 typeindex::type_index get_type() const { return typeindex::type_index(); }
};
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.
*/
typeindex::type_index get_type() const
{
if (m_pImpl.get())
return m_pImpl->get_type();
else
return typeindex::type_index();
}
/*!
* 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_
@@ -0,0 +1,137 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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/type_index.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.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(boost::move(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
*/
typeindex::type_index get_type() const { return typeindex::type_id< 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_
@@ -0,0 +1,480 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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 \c true if there are no elements in the container, \c 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_
@@ -0,0 +1,95 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,122 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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_
@@ -0,0 +1,118 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/memory_order.hpp>
#include <boost/atomic/atomic.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 attribute acts as a counter - it returns a monotonously
* changing value each time requested. The attribute value type can be specified
* as a template parameter. The type must be an integral type.
*/
template< typename T >
class counter :
public attribute
{
BOOST_STATIC_ASSERT_MSG(is_integral< T >::value, "Boost.Log: Only integral types are supported by the counter attribute");
public:
//! A counter value type
typedef T value_type;
protected:
//! Factory implementation
class BOOST_SYMBOL_VISIBLE impl :
public attribute::impl
{
private:
#ifndef BOOST_LOG_NO_THREADS
boost::atomic< value_type > m_counter;
#else
value_type m_counter;
#endif
const value_type m_step;
public:
impl(value_type initial, value_type step) BOOST_NOEXCEPT :
m_counter(initial), m_step(step)
{
}
attribute_value get_value()
{
#ifndef BOOST_LOG_NO_THREADS
value_type value = m_counter.fetch_add(m_step, boost::memory_order_relaxed);
#else
value_type value = m_counter;
m_counter += m_step;
#endif
return make_attribute_value(value);
}
};
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 by this amount.
*/
explicit counter(value_type initial = (value_type)0, value_type step = (value_type)1) :
attribute(new impl(initial, step))
{
}
/*!
* Constructor for casting support
*/
explicit counter(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_COUNTER_HPP_INCLUDED_
@@ -0,0 +1,67 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,71 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,109 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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());
}
typeindex::type_index get_type() const { return typeindex::type_id< 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_
@@ -0,0 +1,186 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_index.hpp>
#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/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(typeindex::type_index 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(typeindex::type_index 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(typeindex::type_index 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_
@@ -0,0 +1,48 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,170 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,332 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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_
@@ -0,0 +1,474 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file
* \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_
@@ -0,0 +1,253 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.hpp>
#include <boost/core/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_
@@ -0,0 +1,81 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,83 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,816 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/core/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 boost::enable_if_c< mpl::is_sequence< T >::value, value_ref< T, TagT > >::type
unwrap_value_ref(value_ref< T, TagT > const& r)
{
return r;
}
template< typename T, typename TagT >
BOOST_FORCEINLINE typename boost::disable_if_c< mpl::is_sequence< T >::value, 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_
@@ -0,0 +1,62 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,372 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,45 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,41 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,28 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,329 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,211 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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;
private:
// A private constructor, accessible from core
BOOST_CONSTEXPR explicit record(public_data* impl) BOOST_NOEXCEPT : m_impl(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>
*/
BOOST_CONSTEXPR record() BOOST_NOEXCEPT : 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_
@@ -0,0 +1,266 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/move/utility_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 value set
explicit public_data(BOOST_RV_REF(attribute_value_set) values) BOOST_NOEXCEPT :
m_ref_counter(1),
m_attribute_values(boost::move(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) BOOST_NOEXCEPT { ++p->m_ref_counter; }
friend void intrusive_ptr_release(const public_data* p) BOOST_NOEXCEPT { 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) BOOST_NOEXCEPT : 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_CONSTEXPR record_view() BOOST_NOEXCEPT
#if !defined(BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS)
= default;
#else
{}
#endif
/*!
* 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_
@@ -0,0 +1,235 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file adaptive_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_ADAPTIVE_MUTEX_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_ADAPTIVE_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_ADAPTIVE_MUTEX_USE_PTHREAD
#elif defined(BOOST_WINDOWS)
#define BOOST_LOG_ADAPTIVE_MUTEX_USE_WINAPI
#elif defined(BOOST_HAS_PTHREADS)
#define BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD
#endif
#if defined(BOOST_LOG_ADAPTIVE_MUTEX_USE_WINAPI)
#include <boost/log/detail/pause.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/detail/winapi/thread.hpp>
#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
# if defined(__INTEL_COMPILER)
# define BOOST_LOG_COMPILER_BARRIER __memory_barrier()
# else
extern "C" void _ReadWriteBarrier(void);
# if defined(BOOST_MSVC)
# pragma intrinsic(_ReadWriteBarrier)
# endif
# define BOOST_LOG_COMPILER_BARRIER _ReadWriteBarrier()
# endif
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
# define BOOST_LOG_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
#endif
#include <boost/log/detail/header.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! A mutex that performs spinning or thread yielding in case of contention
class adaptive_mutex
{
private:
enum state
{
initial_pause = 2,
max_pause = 16
};
long m_State;
public:
adaptive_mutex() : m_State(0) {}
bool try_lock()
{
return (BOOST_INTERLOCKED_COMPARE_EXCHANGE(&m_State, 1L, 0L) == 0L);
}
void lock()
{
#if defined(BOOST_LOG_AUX_PAUSE)
unsigned int pause_count = initial_pause;
#endif
while (!try_lock())
{
#if defined(BOOST_LOG_AUX_PAUSE)
if (pause_count < max_pause)
{
for (unsigned int i = 0; i < pause_count; ++i)
{
BOOST_LOG_AUX_PAUSE;
}
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(adaptive_mutex(adaptive_mutex const&))
BOOST_DELETED_FUNCTION(adaptive_mutex& operator= (adaptive_mutex const&))
};
#undef BOOST_LOG_AUX_PAUSE
#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_ADAPTIVE_MUTEX_USE_PTHREAD)
#include <pthread.h>
#include <boost/assert.hpp>
#include <boost/log/detail/header.hpp>
#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
#define BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD_MUTEX_ADAPTIVE_NP
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! A mutex that performs spinning or thread yielding in case of contention
class adaptive_mutex
{
private:
pthread_mutex_t m_State;
public:
adaptive_mutex()
{
#if defined(BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD_MUTEX_ADAPTIVE_NP)
pthread_mutexattr_t attrs;
pthread_mutexattr_init(&attrs);
pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_ADAPTIVE_NP);
const int err = pthread_mutex_init(&m_State, &attrs);
pthread_mutexattr_destroy(&attrs);
#else
const int err = pthread_mutex_init(&m_State, NULL);
#endif
if (BOOST_UNLIKELY(err != 0))
throw_exception< thread_resource_error >(err, "Failed to initialize an adaptive mutex", "adaptive_mutex::adaptive_mutex()", __FILE__, __LINE__);
}
~adaptive_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 (BOOST_UNLIKELY(err != EBUSY))
throw_exception< lock_error >(err, "Failed to lock an adaptive mutex", "adaptive_mutex::try_lock()", __FILE__, __LINE__);
return false;
}
void lock()
{
const int err = pthread_mutex_lock(&m_State);
if (BOOST_UNLIKELY(err != 0))
throw_exception< lock_error >(err, "Failed to lock an adaptive mutex", "adaptive_mutex::lock()", __FILE__, __LINE__);
}
void unlock()
{
BOOST_VERIFY(pthread_mutex_unlock(&m_State) == 0);
}
// Non-copyable
BOOST_DELETED_FUNCTION(adaptive_mutex(adaptive_mutex const&))
BOOST_DELETED_FUNCTION(adaptive_mutex& operator= (adaptive_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
}
};
} // 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_ADAPTIVE_MUTEX_HPP_INCLUDED_
@@ -0,0 +1,43 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,330 @@
/*
* Copyright Andrey Semashev 2007 - 2016.
* 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 <cstddef>
#include <memory>
#include <locale>
#include <string>
#include <streambuf>
#include <boost/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/locale/utf.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;
//! Size type
typedef typename string_type::size_type size_type;
//! Int type
typedef typename base_type::int_type int_type;
struct storage_state
{
//! A reference to the string that will be filled
string_type* storage;
//! Max size of the storage, in characters
size_type max_size;
//! Indicates that storage overflow happened
bool overflow;
BOOST_CONSTEXPR storage_state() BOOST_NOEXCEPT : storage(NULL), max_size(0u), overflow(false)
{
}
};
private:
//! Buffer storage state
storage_state m_storage_state;
//! A buffer used to temporarily store output
char_type m_buffer[buffer_size];
public:
//! Constructor
basic_ostringstreambuf() BOOST_NOEXCEPT
{
base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
}
//! Constructor
explicit basic_ostringstreambuf(string_type& storage) BOOST_NOEXCEPT
{
base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
attach(storage);
}
storage_state const& get_storage_state() const BOOST_NOEXCEPT { return m_storage_state; }
void set_storage_state(storage_state const& st) BOOST_NOEXCEPT { m_storage_state = st; }
//! Detaches the buffer from the string
void detach()
{
if (m_storage_state.storage)
{
this_type::sync();
m_storage_state.storage = NULL;
m_storage_state.max_size = 0u;
m_storage_state.overflow = false;
}
}
//! Attaches the buffer to another string
void attach(string_type& storage)
{
attach(storage, storage.max_size());
}
//! Attaches the buffer to another string
void attach(string_type& storage, size_type max_size)
{
detach();
m_storage_state.storage = &storage;
this->max_size(max_size);
}
//! Returns a pointer to the attached string
string_type* storage() const BOOST_NOEXCEPT { return m_storage_state.storage; }
//! Returns the maximum size of the storage
size_type max_size() const BOOST_NOEXCEPT { return m_storage_state.max_size; }
//! Sets the maximum size of the storage
void max_size(size_type size)
{
if (m_storage_state.storage)
{
const size_type storage_max_size = m_storage_state.storage->max_size();
size = size > storage_max_size ? storage_max_size : size;
}
m_storage_state.max_size = size;
ensure_max_size();
}
//! Makes sure the storage does not exceed the max size limit. Should be called after the storage is modified externally.
void ensure_max_size()
{
if (m_storage_state.storage && m_storage_state.storage->size() > m_storage_state.max_size)
{
const size_type len = length_until_boundary(m_storage_state.storage->c_str(), m_storage_state.storage->size(), m_storage_state.max_size);
m_storage_state.storage->resize(len);
m_storage_state.overflow = true;
}
}
//! Returns true if the max size limit has been exceeded
bool storage_overflow() const BOOST_NOEXCEPT { return m_storage_state.overflow; }
//! Sets the overflow flag
void storage_overflow(bool f) BOOST_NOEXCEPT { m_storage_state.overflow = f; }
//! Returns the size left in the storage
size_type size_left() const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_storage_state.storage != NULL);
const size_type size = m_storage_state.storage->size();
return size < m_storage_state.max_size ? m_storage_state.max_size - size : static_cast< size_type >(0u);
}
//! Appends a string to the storage and returns the number of written characters
size_type append(const char_type* s, size_type n)
{
if (!m_storage_state.overflow)
{
BOOST_ASSERT(m_storage_state.storage != NULL);
size_type left = size_left();
BOOST_LOG_ASSUME(left <= m_storage_state.storage->max_size());
if (BOOST_LIKELY(n <= left))
{
m_storage_state.storage->append(s, n);
return n;
}
else
{
// We have to find out where the last character that fits before the limit ends
left = length_until_boundary(s, n, left);
m_storage_state.storage->append(s, left);
m_storage_state.overflow = true;
return left;
}
}
return 0u;
}
//! Appends the specified number of characters to the storage and returns the number of written characters
size_type append(size_type n, char_type c)
{
if (!m_storage_state.overflow)
{
BOOST_ASSERT(m_storage_state.storage != NULL);
const size_type left = size_left();
BOOST_LOG_ASSUME(left <= m_storage_state.storage->max_size());
if (BOOST_LIKELY(n <= left))
{
m_storage_state.storage->append(n, c);
return n;
}
else
{
m_storage_state.storage->append(left, c);
m_storage_state.overflow = true;
return left;
}
}
return 0u;
}
//! Appends a character to the storage and returns the number of written characters
size_type push_back(char_type c)
{
if (!m_storage_state.overflow)
{
BOOST_ASSERT(m_storage_state.storage != NULL);
BOOST_LOG_ASSUME(m_storage_state.max_size <= m_storage_state.storage->max_size());
if (BOOST_LIKELY(m_storage_state.storage->size() < m_storage_state.max_size))
{
m_storage_state.storage->push_back(c);
return 1u;
}
else
{
m_storage_state.overflow = true;
return 0u;
}
}
return 0u;
}
protected:
//! Puts all buffered data to the string
int sync()
{
char_type* pBase = this->pbase();
char_type* pPtr = this->pptr();
if (pBase != pPtr)
{
this->append(pBase, static_cast< size_type >(pPtr - pBase));
this->pbump(static_cast< int >(pBase - pPtr));
}
return 0;
}
//! Puts an unbuffered character to the string
int_type overflow(int_type c)
{
this_type::sync();
if (!traits_type::eq_int_type(c, traits_type::eof()))
{
this->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)
{
this_type::sync();
return static_cast< std::streamsize >(this->append(s, static_cast< size_type >(n)));
}
//! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
size_type length_until_boundary(const char_type* s, size_type n, size_type max_size) const
{
return length_until_boundary(s, n, max_size, mpl::bool_< sizeof(char_type) == 1u >());;
}
//! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, mpl::true_) const
{
std::locale loc = this->getloc();
std::codecvt< wchar_t, char, std::mbstate_t > const& fac = std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc);
std::mbstate_t mbs = std::mbstate_t();
return static_cast< size_type >(fac.length(mbs, s, s + max_size, ~static_cast< std::size_t >(0u)));
}
//! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
static size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, mpl::false_)
{
// Note: Although it's not required to be true for wchar_t, here we assume that the string has Unicode encoding.
// Compilers use some version of Unicode for wchar_t on all tested platforms, and std::locale doesn't offer a way
// to find the character boundary for character types other than char anyway.
typedef boost::locale::utf::utf_traits< CharT > utf_traits;
size_type pos = max_size;
while (pos > 0u)
{
--pos;
if (utf_traits::is_lead(s[pos]))
{
const char_type* p = s + pos;
boost::locale::utf::code_point cp = utf_traits::decode(p, s + n);
if (boost::locale::utf::is_valid_codepoint(cp) && p <= (s + max_size))
return static_cast< size_type >(p - s);
}
}
return 0u;
}
//! 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_
@@ -0,0 +1,111 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,162 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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_
@@ -0,0 +1,43 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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_
@@ -0,0 +1,116 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file attribute_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_
@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2016.
* 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 c_str.hpp
* \author Andrey Semashev
* \date 23.02.2016
*
* 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_C_STR_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_C_STR_HPP_INCLUDED_
#include <string>
#include <boost/core/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/is_character_type.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 >
inline typename boost::enable_if_c< is_character_type< T >::value, const T* >::type c_str(const T* str) BOOST_NOEXCEPT
{
return str;
}
template< typename T, typename TraitsT, typename AllocatorT >
inline typename boost::enable_if_c< is_character_type< T >::value, const T* >::type c_str(std::basic_string< T, TraitsT, AllocatorT > const& str) BOOST_NOEXCEPT
{
return str.c_str();
}
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_C_STR_HPP_INCLUDED_
@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,192 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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 <cstddef>
#include <locale>
#include <string>
#include <boost/core/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/is_character_type.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
// Implementation note: We have to implement char<->wchar_t conversions even in the absence of the native wchar_t
// type. These conversions are used in sinks, e.g. to convert multibyte strings to wide-character filesystem paths.
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const wchar_t* str1, std::size_t len, std::string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char* str1, std::size_t len, std::wstring& str2, std::size_t max_size, std::locale const& loc = std::locale());
#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char16_t* str1, std::size_t len, std::string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char* str1, std::size_t len, std::u16string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char16_t* str1, std::size_t len, std::wstring& str2, std::size_t max_size, 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 bool code_convert_impl(const char32_t* str1, std::size_t len, std::string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char* str1, std::size_t len, std::u32string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char32_t* str1, std::size_t len, std::wstring& str2, std::size_t max_size, std::locale const& loc = std::locale());
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_CHAR32_T)
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char16_t* str1, std::size_t len, std::u32string& str2, std::size_t max_size, std::locale const& loc = std::locale());
//! The function converts one string to the character type of another
BOOST_LOG_API bool code_convert_impl(const char32_t* str1, std::size_t len, std::u16string& str2, std::size_t max_size, std::locale const& loc = std::locale());
#endif
#endif // !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
//! The function converts one string to the character type of another
template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& = std::locale())
{
std::size_t size_left = str2.size() < max_size ? max_size - str2.size() : static_cast< std::size_t >(0u);
const bool overflow = len > size_left;
str2.append(reinterpret_cast< const TargetCharT* >(str1), overflow ? size_left : len);
return !overflow;
}
//! 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 typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& loc = std::locale())
{
return aux::code_convert(str1.data(), str1.size(), str2, max_size, loc);
}
//! 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 typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
return aux::code_convert(str1.data(), str1.size(), str2, str2.max_size(), loc);
}
//! The function converts one string to the character type of another
template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT), bool >::type
code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
return aux::code_convert(str1, len, str2, str2.max_size(), loc);
}
//! 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 typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
return aux::code_convert_impl(str1.c_str(), str1.size(), str2, str2.max_size(), loc);
}
//! The function converts one string to the character type of another
template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale())
{
return aux::code_convert_impl(str1, len, str2, str2.max_size(), loc);
}
//! 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 typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& loc = std::locale())
{
return aux::code_convert_impl(str1.c_str(), str1.size(), str2, max_size, loc);
}
//! The function converts one string to the character type of another
template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT >
inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT), bool >::type
code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::size_t max_size, std::locale const& loc = std::locale())
{
return aux::code_convert_impl(str1, len, str2, max_size, 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_impl(str.c_str(), str.size(), res, res.max_size(), loc);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_HAS_NRVO)
return static_cast< std::string&& >(res);
#else
return res;
#endif
}
//! 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_impl(str.c_str(), str.size(), res, res.max_size(), loc);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_HAS_NRVO)
return static_cast< std::wstring&& >(res);
#else
return res;
#endif
}
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_
@@ -0,0 +1,381 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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 <boost/predef/os.h>
// Try including WinAPI config as soon as possible so that any other headers don't include Windows SDK headers
#if defined(BOOST_OS_WINDOWS_AVAILABLE)
#include <boost/detail/winapi/config.hpp>
#endif
#include <limits.h> // To bring in libc macros
#include <boost/config.hpp>
// The library requires dynamic_cast in a few places
#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(BOOST_NO_CXX11_HDR_CODECVT)
// The compiler does not support std::codecvt<char16_t> and std::codecvt<char32_t> specializations.
// The BOOST_NO_CXX11_HDR_CODECVT means there's no usable <codecvt>, which is slightly different from this macro.
// But in order for <codecvt> to be implemented the std::codecvt specializations have to be implemented as well.
# define BOOST_LOG_NO_CXX11_CODECVT_FACETS
#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(BOOST_NO_CXX11_CONSTEXPR) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
// GCC 4.6 does not support in-class brace initializers for static constexpr array members
#define BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS
#endif
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
#define BOOST_LOG_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
#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
// The macro efficiently returns a local lvalue from a function.
// It employs NRVO, if supported by compiler, or uses a move constructor otherwise.
#if defined(BOOST_HAS_NRVO)
#define BOOST_LOG_NRVO_RESULT(x) x
#else
#define BOOST_LOG_NRVO_RESULT(x) boost::move(x)
#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
// GCC and compatible compilers may require marking types that may alias other types
#if defined(__GNUC__)
# define BOOST_LOG_MAY_ALIAS __attribute__ ((__may_alias__))
#else
# define BOOST_LOG_MAY_ALIAS
#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)
# define BOOST_LOG_API BOOST_SYMBOL_IMPORT
# else
# 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)
# define BOOST_LOG_API BOOST_SYMBOL_EXPORT
# else
# 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 BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt6
# else
# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt5
# endif
# 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 BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt6
# else
# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt5
# endif
# 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_
@@ -0,0 +1,64 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,70 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,44 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,486 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,439 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/detail/attachable_sstream_buf.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(boost::log::aux::basic_ostringstreambuf< CharT >& strbuf, 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;
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_),
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) BOOST_NOEXCEPT
{
this->swap(static_cast< date_time_formatter& >(that));
}
date_time_formatter& operator= (date_time_formatter that) BOOST_NOEXCEPT
{
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) BOOST_NOEXCEPT
{
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.strm.rdbuf(), ctx.value.year, 4, static_cast< char_type >('0'));
}
static void format_short_year(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), ctx.value.year % 100u, 2, static_cast< char_type >('0'));
}
static void format_numeric_month(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), ctx.value.month, 2, static_cast< char_type >('0'));
}
template< char_type FillCharV >
static void format_month_day(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), ctx.value.day, 2, static_cast< char_type >(FillCharV));
}
static void format_week_day(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), 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.strm.rdbuf(), ctx.value.hours, 2, static_cast< char_type >(FillCharV));
}
template< char_type FillCharV >
static void format_hours_12(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV));
}
static void format_minutes(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), ctx.value.minutes, 2, static_cast< char_type >('0'));
}
static void format_seconds(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), ctx.value.seconds, 2, static_cast< char_type >('0'));
}
static void format_fractional_seconds(context& ctx)
{
(put_integer)(*ctx.strm.rdbuf(), 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.strm.rdbuf()->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.strm.rdbuf()->push_back('-');
else if (DisplayPositiveV)
ctx.strm.rdbuf()->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.strm.rdbuf()->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_
@@ -0,0 +1,108 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,53 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,125 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,103 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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_
@@ -0,0 +1,170 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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)
# include <boost/atomic/capabilities.hpp>
# if (defined(linux) || defined(__linux) || defined(__linux__)) && BOOST_ATOMIC_INT_LOCK_FREE == 2
# include <boost/atomic/atomic.hpp>
# define BOOST_LOG_EVENT_USE_FUTEX
# elif defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES + 0) > 0 && BOOST_ATOMIC_FLAG_LOCK_FREE == 2
# include <semaphore.h>
# include <boost/cstdint.hpp>
# include <boost/atomic/atomic_flag.hpp>
# define BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE
# 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_FUTEX)
class futex_based_event
{
private:
boost::atomic< int > m_state;
public:
//! Default constructor
BOOST_LOG_API futex_based_event();
//! Destructor
BOOST_LOG_API ~futex_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(futex_based_event(futex_based_event const&))
BOOST_DELETED_FUNCTION(futex_based_event& operator= (futex_based_event const&))
};
typedef futex_based_event event;
#elif defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE)
class sem_based_event
{
private:
boost::atomic_flag 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_
@@ -0,0 +1,56 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,22 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#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>
@@ -0,0 +1,340 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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)
{
// Flush the stream beforehand so that the pump can safely switch the stream storage string
strm.flush();
return pump(*this, strm);
}
//! Composes the final string from the formatted pieces
string_type str() const
{
string_type result;
compose(result);
return BOOST_LOG_NRVO_RESULT(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());
}
}
}
//! Composes the final string from the formatted pieces
template< typename T >
void compose(T& 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
string_type const& target = m_formatting_params[it->arg_number].target;
str.append(target.data(), target.size());
}
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);
}
}
}
};
//! 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_state_backup(strm.rdbuf()->get_storage_state())
{
strm.attach(storage);
}
~scoped_storage()
{
m_stream.rdbuf()->set_storage_state(m_storage_state_backup);
}
private:
stream_type& m_stream;
typename stream_type::streambuf_type::storage_state m_storage_state_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());
}
}
}
/*!
* 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_
@@ -0,0 +1,236 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,30 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
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)
@@ -0,0 +1,66 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#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)
// 'X': This function or variable may be unsafe. Consider using Y instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
#pragma warning(disable: 4996)
#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)
@@ -0,0 +1,84 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,73 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file is_character_type.hpp
* \author Andrey Semashev
* \date 25.07.2015
*
* The header defines \c is_character_type trait which checks if the type is one of the character types
*/
#ifndef BOOST_LOG_DETAIL_IS_CHARACTER_TYPE_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_IS_CHARACTER_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 is_character_type
{
static BOOST_CONSTEXPR_OR_CONST bool value = false;
};
template< >
struct is_character_type< char >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
template< >
struct is_character_type< wchar_t >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
#if !defined(BOOST_NO_CXX11_CHAR16_T)
template< >
struct is_character_type< char16_t >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
template< >
struct is_character_type< char32_t >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
#endif
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_IS_CHARACTER_TYPE_HPP_INCLUDED_
@@ -0,0 +1,57 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file is_ostream.hpp
* \author Andrey Semashev
* \date 05.07.2015
*
* \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_IS_OSTREAM_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_IS_OSTREAM_HPP_INCLUDED_
#include <iosfwd>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/has_left_shift.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
namespace aux {
template< typename T >
struct is_ostream
{
static BOOST_CONSTEXPR_OR_CONST bool value = is_base_of< std::ios_base, T >::value && has_left_shift< T, int >::value;
};
template< typename CharT, typename TraitsT, typename AllocatorT >
struct is_ostream< basic_formatting_ostream< CharT, TraitsT, AllocatorT > >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_IS_OSTREAM_HPP_INCLUDED_
@@ -0,0 +1,521 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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/log/detail/sfinae_tools.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 boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
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 boost::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 boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
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 boost::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_
@@ -0,0 +1,424 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
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 boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
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 boost::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 boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
m_pImpl(new impl< FunT >(fun))
{
}
template< typename FunT >
light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
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 boost::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;
}
};
@@ -0,0 +1,175 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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) && (BOOST_USE_WINAPI_VERSION+0) >= (BOOST_WINAPI_VERSION_WIN6+0)
#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)
#include <boost/detail/winapi/srw_lock.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! A light read/write mutex that uses WinNT 6 and later APIs
class light_rw_mutex
{
boost::detail::winapi::SRWLOCK_ m_Mutex;
public:
light_rw_mutex()
{
boost::detail::winapi::InitializeSRWLock(&m_Mutex);
}
void lock_shared()
{
boost::detail::winapi::AcquireSRWLockShared(&m_Mutex);
}
void unlock_shared()
{
boost::detail::winapi::ReleaseSRWLockShared(&m_Mutex);
}
void lock()
{
boost::detail::winapi::AcquireSRWLockExclusive(&m_Mutex);
}
void unlock()
{
boost::detail::winapi::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 BOOST_LOG_MAY_ALIAS mutex_state { 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_
@@ -0,0 +1,148 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,199 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_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) };
};
//! A scope guard that automatically unlocks the mutex on destruction
template< typename MutexT >
struct exclusive_auto_unlocker
{
explicit exclusive_auto_unlocker(MutexT& m) BOOST_NOEXCEPT : m_Mutex(m)
{
}
~exclusive_auto_unlocker()
{
m_Mutex.unlock();
}
BOOST_DELETED_FUNCTION(exclusive_auto_unlocker(exclusive_auto_unlocker const&))
BOOST_DELETED_FUNCTION(exclusive_auto_unlocker& operator= (exclusive_auto_unlocker const&))
protected:
MutexT& m_Mutex;
};
//! 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();
}
BOOST_DELETED_FUNCTION(exclusive_lock_guard(exclusive_lock_guard const&))
BOOST_DELETED_FUNCTION(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();
}
BOOST_DELETED_FUNCTION(shared_lock_guard(shared_lock_guard const&))
BOOST_DELETED_FUNCTION(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_
@@ -0,0 +1,82 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
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)));
}
@@ -0,0 +1,63 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,153 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/control/if.hpp>
#include <boost/preprocessor/comparison/equal.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/sfinae_tools.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_1(n, types)\
template< typename T0 >\
explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))) {}
#define BOOST_LOG_CTOR_FORWARD_N(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))) {}
#define BOOST_LOG_CTOR_FORWARD(z, n, types)\
BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_CTOR_FORWARD_1, BOOST_LOG_CTOR_FORWARD_N)(n, types)
// 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_1(n, types)\
template< typename T0 >\
explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy())\
{ BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))); }
#define BOOST_LOG_CTOR_CALL_N(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))); }
#define BOOST_LOG_CTOR_CALL(z, n, types)\
BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_CTOR_CALL_1, BOOST_LOG_CTOR_CALL_N)(n, types)
// 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.
// https://svn.boost.org/trac/boost/ticket/7247
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
template< typename T, typename R >
struct enable_if_named_parameters {};
template< typename R >
struct enable_if_named_parameters< empty_arg_list, R >
{
typedef R type;
};
template< typename Keyword, typename Arg, typename R >
struct enable_if_named_parameters< boost::parameter::aux::tagged_argument< Keyword, Arg >, R >
{
typedef R type;
};
template< typename TaggedArg, typename Next, typename R >
struct enable_if_named_parameters< boost::parameter::aux::arg_list< TaggedArg, Next >, R >
{
typedef R type;
};
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_
@@ -0,0 +1,61 @@
/*
* Copyright Andrey Semashev 2016.
* 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 pause.hpp
* \author Andrey Semashev
* \date 06.01.2016
*
* \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_PAUSE_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_PAUSE_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
# if defined(_M_IX86)
# define BOOST_LOG_AUX_PAUSE __asm { pause }
# elif defined(_M_AMD64)
extern "C" void _mm_pause(void);
# if defined(BOOST_MSVC)
# pragma intrinsic(_mm_pause)
# endif
# define BOOST_LOG_AUX_PAUSE _mm_pause()
# endif
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
# define BOOST_LOG_AUX_PAUSE __asm__ __volatile__("pause;")
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
BOOST_FORCEINLINE void pause() BOOST_NOEXCEPT
{
#if defined(BOOST_LOG_AUX_PAUSE)
BOOST_LOG_AUX_PAUSE;
#endif
}
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_PAUSE_HPP_INCLUDED_
@@ -0,0 +1,27 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,60 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,60 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_LOG_SETUP_DLL)
# define BOOST_LOG_SETUP_API BOOST_SYMBOL_IMPORT
# else
# define BOOST_LOG_SETUP_API
# endif
//
// 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_LOG_SETUP_DLL)
# define BOOST_LOG_SETUP_API BOOST_SYMBOL_EXPORT
# else
# define BOOST_LOG_SETUP_API BOOST_SYMBOL_VISIBLE
# endif
#endif // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB)
#endif // BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_
@@ -0,0 +1,44 @@
/*
* Copyright Andrey Semashev 2016.
* 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 sfinae_tools.hpp
* \author Andrey Semashev
* \date 23.02.2016
*
* \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_SFINAE_TOOLS_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_SFINAE_TOOLS_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! A distinct type that can be used as a fake argument type in constructors filtered by SFINAE
struct sfinae_dummy {};
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_SFINAE_TOOLS_HPP_INCLUDED_
@@ -0,0 +1,89 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,118 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/core/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 boost::enable_if_c<
phoenix::is_actor< FilterT >::value,
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 boost::enable_if_c<
phoenix::is_actor< FormatterT >::value,
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_
@@ -0,0 +1,107 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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) || (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
// MSVC snprintfs are not conforming but they are good enough for our cases.
// MinGW32, at least the older versions up until gcc 4.7, also provide the non-conforming interface.
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
#else
// 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
#endif
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_
@@ -0,0 +1,147 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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
BOOST_CONSTEXPR operator integer_type() const BOOST_NOEXCEPT { return value; }
// Increment
tagged_integer& operator++ () BOOST_NOEXCEPT { ++value; return *this; }
tagged_integer operator++ (int) BOOST_NOEXCEPT { tagged_integer temp = *this; ++value; return temp; }
// Decrement
tagged_integer& operator-- () BOOST_NOEXCEPT { --value; return *this; }
tagged_integer operator-- (int) BOOST_NOEXCEPT { tagged_integer temp = *this; --value; return temp; }
#define BOOST_LOG_TAGGED_INTEGER_OP(op)\
tagged_integer& operator op (tagged_integer const& that) BOOST_NOEXCEPT { 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~ () BOOST_NOEXCEPT { ~value; return *this; }
// Shift operators
template< typename T >
tagged_integer& operator<<= (T const& that) BOOST_NOEXCEPT { value <<= that; return *this; }
template< typename T >
tagged_integer& operator>>= (T const& that) BOOST_NOEXCEPT { 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) BOOST_NOEXCEPT\
{\
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) BOOST_NOEXCEPT\
{\
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) BOOST_NOEXCEPT\
{\
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_
@@ -0,0 +1,65 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,116 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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:
#if defined(BOOST_THREAD_PLATFORM_WIN32)
typedef unsigned long key_storage;
#else
typedef void* key_storage;
#endif
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_
@@ -0,0 +1,272 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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 BOOST_LOG_MAY_ALIAS 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_
@@ -0,0 +1,102 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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>
#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include <boost/detail/winapi/basic_types.hpp>
#endif
#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 (WINAPI* 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_
@@ -0,0 +1,43 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,142 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,107 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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
@@ -0,0 +1,469 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file
* \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/type_index.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#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 {
// 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 memory allocation errors
*
* Exceptions derived from this class indicate problems with memory allocation.
*/
class BOOST_LOG_API bad_alloc :
public std::bad_alloc
{
private:
std::string m_message;
public:
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
explicit bad_alloc(const char* descr);
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
explicit bad_alloc(std::string const& descr);
/*!
* Destructor
*/
~bad_alloc() throw();
/*!
* Error message accessor.
*/
const char* what() const throw();
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
/*!
* \brief The exception is used to indicate reaching a storage capacity limit
*/
class BOOST_LOG_API capacity_limit_reached :
public bad_alloc
{
public:
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
explicit capacity_limit_reached(const char* descr);
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
explicit capacity_limit_reached(std::string const& descr);
/*!
* Destructor
*/
~capacity_limit_reached() throw();
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr);
#endif
};
/*!
* \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
{
public:
/*!
* 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, const char* descr);
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, const char* descr, attribute_name const& name);
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, const char* descr);
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, const char* descr, attribute_name const& name);
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, const char* descr, typeindex::type_index const& type);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, typeindex::type_index const& type);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr, attribute_name const& name, typeindex::type_index const& type);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, attribute_name const& name, typeindex::type_index 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, const char* descr);
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, const char* descr);
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, const char* descr, std::size_t content_line);
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, const char* descr, attribute_name const& name);
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, const char* descr);
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 boost::system::system_error
{
public:
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
system_error(boost::system::error_code code, 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, const char* descr, int system_error_code);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, int system_error_code);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr, boost::system::error_code code);
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, std::string const& descr, boost::system::error_code code);
#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
{
public:
/*!
* Initializing constructor. Creates an exception with the specified error message.
*/
explicit logic_error(std::string const& descr);
/*!
* Destructor
*/
~logic_error() throw();
#ifndef BOOST_LOG_DOXYGEN_PASS
static BOOST_LOG_NORETURN void throw_(const char* file, std::size_t line, const char* descr);
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 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, const char* descr);
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, const char* descr);
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, const char* descr);
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, const char* descr);
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_
@@ -0,0 +1,38 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,278 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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_
@@ -0,0 +1,69 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_
@@ -0,0 +1,187 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/sfinae_tools.hpp>
#endif
#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 >= 1600
template< typename FunT >
filter(FunT const& fun, typename boost::disable_if_c< move_detail::is_rv< FunT >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : m_Filter(fun)
{
}
#else
// MSVC 9 and older 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 boost::disable_if_c< is_same< typename remove_cv< FunT >::type, filter >::value, 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_
@@ -0,0 +1,484 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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 <locale>
#include <ostream>
#include <boost/ref.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/sfinae_tools.hpp>
#endif
#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:
typedef typename StreamT::char_type char_type;
typedef typename StreamT::traits_type traits_type;
typedef typename StreamT::allocator_type allocator_type;
typedef typename StreamT::streambuf_type streambuf_type;
typedef typename StreamT::string_type string_type;
typedef typename StreamT::ostream_type ostream_type;
typedef typename StreamT::pos_type pos_type;
typedef typename StreamT::off_type off_type;
typedef typename StreamT::int_type int_type;
typedef typename StreamT::failure failure;
typedef typename StreamT::fmtflags fmtflags;
typedef typename StreamT::iostate iostate;
typedef typename StreamT::openmode openmode;
typedef typename StreamT::seekdir seekdir;
typedef typename StreamT::Init Init;
typedef typename StreamT::event event;
typedef typename StreamT::event_callback event_callback;
typedef typename StreamT::sentry sentry;
static BOOST_CONSTEXPR_OR_CONST fmtflags boolalpha = StreamT::boolalpha;
static BOOST_CONSTEXPR_OR_CONST fmtflags dec = StreamT::dec;
static BOOST_CONSTEXPR_OR_CONST fmtflags fixed = StreamT::fixed;
static BOOST_CONSTEXPR_OR_CONST fmtflags hex = StreamT::hex;
static BOOST_CONSTEXPR_OR_CONST fmtflags internal = StreamT::internal;
static BOOST_CONSTEXPR_OR_CONST fmtflags left = StreamT::left;
static BOOST_CONSTEXPR_OR_CONST fmtflags oct = StreamT::oct;
static BOOST_CONSTEXPR_OR_CONST fmtflags right = StreamT::right;
static BOOST_CONSTEXPR_OR_CONST fmtflags scientific = StreamT::scientific;
static BOOST_CONSTEXPR_OR_CONST fmtflags showbase = StreamT::showbase;
static BOOST_CONSTEXPR_OR_CONST fmtflags showpoint = StreamT::showpoint;
static BOOST_CONSTEXPR_OR_CONST fmtflags skipws = StreamT::skipws;
static BOOST_CONSTEXPR_OR_CONST fmtflags unitbuf = StreamT::unitbuf;
static BOOST_CONSTEXPR_OR_CONST fmtflags uppercase = StreamT::uppercase;
static BOOST_CONSTEXPR_OR_CONST fmtflags adjustfield = StreamT::adjustfield;
static BOOST_CONSTEXPR_OR_CONST fmtflags basefield = StreamT::basefield;
static BOOST_CONSTEXPR_OR_CONST fmtflags floatfield = StreamT::floatfield;
static BOOST_CONSTEXPR_OR_CONST iostate badbit = StreamT::badbit;
static BOOST_CONSTEXPR_OR_CONST iostate eofbit = StreamT::eofbit;
static BOOST_CONSTEXPR_OR_CONST iostate failbit = StreamT::failbit;
static BOOST_CONSTEXPR_OR_CONST iostate goodbit = StreamT::goodbit;
static BOOST_CONSTEXPR_OR_CONST openmode app = StreamT::app;
static BOOST_CONSTEXPR_OR_CONST openmode ate = StreamT::ate;
static BOOST_CONSTEXPR_OR_CONST openmode binary = StreamT::binary;
static BOOST_CONSTEXPR_OR_CONST openmode in = StreamT::in;
static BOOST_CONSTEXPR_OR_CONST openmode out = StreamT::out;
static BOOST_CONSTEXPR_OR_CONST openmode trunc = StreamT::trunc;
static BOOST_CONSTEXPR_OR_CONST seekdir beg = StreamT::beg;
static BOOST_CONSTEXPR_OR_CONST seekdir cur = StreamT::cur;
static BOOST_CONSTEXPR_OR_CONST seekdir end = StreamT::end;
static BOOST_CONSTEXPR_OR_CONST event erase_event = StreamT::erase_event;
static BOOST_CONSTEXPR_OR_CONST event imbue_event = StreamT::imbue_event;
static BOOST_CONSTEXPR_OR_CONST event copyfmt_event = StreamT::copyfmt_event;
BOOST_FORCEINLINE explicit stream_ref(StreamT& strm) : reference_wrapper< StreamT >(strm)
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template< typename T >
BOOST_FORCEINLINE StreamT& operator<< (T&& val) const
{
StreamT& strm = this->get();
strm << static_cast< T&& >(val);
return strm;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1800
// MSVC 10 and 11 generate broken code for the perfect forwarding version above if T is an array type (e.g. a string literal)
template< typename T, unsigned int N >
BOOST_FORCEINLINE StreamT& operator<< (T (&val)[N]) const
{
StreamT& strm = this->get();
strm << val;
return strm;
}
#endif
#else
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;
}
#endif
BOOST_FORCEINLINE void attach(string_type& str) const { this->get().attach(str); }
BOOST_FORCEINLINE void detach() const { this->get().detach(); }
BOOST_FORCEINLINE string_type const& str() const { return this->get().str(); }
BOOST_FORCEINLINE ostream_type& stream() const { return this->get().stream(); }
BOOST_FORCEINLINE fmtflags flags() const { return this->get().flags(); }
BOOST_FORCEINLINE fmtflags flags(fmtflags f) const { return this->get().flags(f); }
BOOST_FORCEINLINE fmtflags setf(fmtflags f) const { return this->get().setf(f); }
BOOST_FORCEINLINE fmtflags setf(fmtflags f, fmtflags mask) const { return this->get().setf(f, mask); }
BOOST_FORCEINLINE void unsetf(fmtflags f) const { this->get().unsetf(f); }
BOOST_FORCEINLINE std::streamsize precision() const { return this->get().precision(); }
BOOST_FORCEINLINE std::streamsize precision(std::streamsize p) const { return this->get().precision(p); }
BOOST_FORCEINLINE std::streamsize width() const { return this->get().width(); }
BOOST_FORCEINLINE std::streamsize width(std::streamsize w) const { return this->get().width(w); }
BOOST_FORCEINLINE std::locale getloc() const { return this->get().getloc(); }
BOOST_FORCEINLINE std::locale imbue(std::locale const& loc) const { return this->get().imbue(loc); }
static BOOST_FORCEINLINE int xalloc() { return StreamT::xalloc(); }
BOOST_FORCEINLINE long& iword(int index) const { return this->get().iword(index); }
BOOST_FORCEINLINE void*& pword(int index) const { return this->get().pword(index); }
BOOST_FORCEINLINE void register_callback(event_callback fn, int index) const { this->get().register_callback(fn, index); }
static BOOST_FORCEINLINE bool sync_with_stdio(bool sync = true) { return StreamT::sync_with_stdio(sync); }
BOOST_EXPLICIT_OPERATOR_BOOL()
BOOST_FORCEINLINE bool operator! () const { return !this->get(); }
BOOST_FORCEINLINE iostate rdstate() const { return this->get().rdstate(); }
BOOST_FORCEINLINE void clear(iostate state = goodbit) const { this->get().clear(state); }
BOOST_FORCEINLINE void setstate(iostate state) const { this->get().setstate(state); }
BOOST_FORCEINLINE bool good() const { return this->get().good(); }
BOOST_FORCEINLINE bool eof() const { return this->get().eof(); }
BOOST_FORCEINLINE bool fail() const { return this->get().fail(); }
BOOST_FORCEINLINE bool bad() const { return this->get().bad(); }
BOOST_FORCEINLINE iostate exceptions() const { return this->get().exceptions(); }
BOOST_FORCEINLINE void exceptions(iostate s) const { this->get().exceptions(s); }
BOOST_FORCEINLINE ostream_type* tie() const { return this->get().tie(); }
BOOST_FORCEINLINE ostream_type* tie(ostream_type* strm) const { return this->get().tie(strm); }
BOOST_FORCEINLINE streambuf_type* rdbuf() const { return this->get().rdbuf(); }
BOOST_FORCEINLINE StreamT& copyfmt(std::basic_ios< char_type, traits_type >& rhs) const { return this->get().copyfmt(rhs); }
BOOST_FORCEINLINE StreamT& copyfmt(StreamT& rhs) const { return this->get().copyfmt(rhs); }
BOOST_FORCEINLINE char_type fill() const { return this->get().fill(); }
BOOST_FORCEINLINE char_type fill(char_type ch) const { return this->get().fill(ch); }
BOOST_FORCEINLINE char narrow(char_type ch, char def) const { return this->get().narrow(ch, def); }
BOOST_FORCEINLINE char_type widen(char ch) const { return this->get().widen(ch); }
BOOST_FORCEINLINE StreamT& flush() const { return this->get().flush(); }
BOOST_FORCEINLINE pos_type tellp() const { return this->get().tellp(); }
BOOST_FORCEINLINE StreamT& seekp(pos_type pos) const { return this->get().seekp(pos); }
BOOST_FORCEINLINE StreamT& seekp(off_type off, std::ios_base::seekdir dir) const { return this->get().seekp(off, dir); }
template< typename CharT >
BOOST_FORCEINLINE typename boost::log::aux::enable_if_streamable_char_type< CharT, StreamT& >::type
put(CharT c) const { return this->get().put(c); }
template< typename CharT >
BOOST_FORCEINLINE typename boost::log::aux::enable_if_streamable_char_type< CharT, StreamT& >::type
write(const CharT* p, std::streamsize size) const { return this->get().write(p, size); }
};
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::boolalpha;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::dec;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::fixed;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::hex;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::internal;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::left;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::oct;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::right;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::scientific;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::showbase;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::showpoint;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::skipws;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::unitbuf;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::uppercase;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::adjustfield;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::basefield;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::fmtflags stream_ref< StreamT >::floatfield;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::badbit;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::eofbit;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::failbit;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::iostate stream_ref< StreamT >::goodbit;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::app;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::ate;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::binary;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::in;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::out;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::openmode stream_ref< StreamT >::trunc;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::seekdir stream_ref< StreamT >::beg;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::seekdir stream_ref< StreamT >::cur;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::seekdir stream_ref< StreamT >::end;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::event stream_ref< StreamT >::erase_event;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::event stream_ref< StreamT >::imbue_event;
template< typename StreamT >
BOOST_CONSTEXPR_OR_CONST typename stream_ref< StreamT >::event stream_ref< StreamT >::copyfmt_event;
//! Default log record message formatter
struct message_formatter
{
typedef void result_type;
message_formatter() : m_MessageName(expressions::tag::message::get_name())
{
}
template< typename StreamT >
BOOST_FORCEINLINE 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 >= 1600
template< typename FunT >
basic_formatter(FunT const& fun, typename boost::disable_if_c< move_detail::is_rv< FunT >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : m_Formatter(fun)
{
}
#else
// MSVC 9 and older 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 boost::disable_if_c< is_same< typename remove_cv< FunT >::type, this_type >::value, 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_
@@ -0,0 +1,39 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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/max_size_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_
@@ -0,0 +1,280 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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%.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%.2X";
val = static_cast< uint8_t >(c);
}
else if (sizeof(wchar_t) == 2)
{
format = L"\\x%.4X";
val = static_cast< uint16_t >(c);
}
else
{
format = L"\\x%.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[ stream << 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_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[ stream << 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_
@@ -0,0 +1,645 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.hpp>
#include <boost/core/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/detail/sfinae_tools.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
#ifndef BOOST_LOG_DOXYGEN_PASS
// This is needed for a workaround against an MSVC-10 and older bug in constructor overload resolution
, typename boost::enable_if_has_type< typename range_const_iterator< RangeT >::type, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
#endif
)
{
typedef typename range_const_iterator< RangeT >::type iterator;
for (iterator it = boost::begin(decorations), end_ = boost::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 = boost::begin(from), end1 = boost::end(from);
iterator2 it2 = boost::begin(to), end2 = boost::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 boost::begin(r);
}
static char_type* string_end(char_type* p)
{
return p + std::char_traits< char_type >::length(p);
}
static const char_type* string_end(const char_type* p)
{
return p + std::char_traits< char_type >::length(p);
}
template< typename RangeT >
static typename range_const_iterator< RangeT >::type string_end(RangeT const& r)
{
return boost::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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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
phoenix::eval(m_subactor, ctx);
// Flush the buffered characters and apply decorations
strm.flush();
m_impl(*strm.rdbuf()->storage(), start_pos);
strm.rdbuf()->ensure_max_size();
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
phoenix::eval(m_subactor, ctx);
// Flush the buffered characters and apply decorations
strm.flush();
m_impl(*strm.rdbuf()->storage(), start_pos);
strm.rdbuf()->ensure_max_size();
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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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_LOG_NRVO_RESULT(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_LOG_NRVO_RESULT(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_
@@ -0,0 +1,140 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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[ stream << 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_
@@ -0,0 +1,345 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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_core.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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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_LOG_NRVO_RESULT(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_LOG_NRVO_RESULT(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_
@@ -0,0 +1,130 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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_
@@ -0,0 +1,319 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file 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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! 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_
@@ -0,0 +1,561 @@
/*
* Copyright Andrey Semashev 2016.
* 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/max_size_decorator.hpp
* \author Andrey Semashev
* \date 06.07.2016
*
* The header contains implementation of a string length limiting decorator.
*/
#ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_MAX_SIZE_DECORATOR_HPP_INCLUDED_
#define BOOST_LOG_EXPRESSIONS_FORMATTERS_MAX_SIZE_DECORATOR_HPP_INCLUDED_
#include <cstddef>
#include <string>
#include <boost/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/core/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/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/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 {
//! String size limiting decorator stream output terminal
template< typename LeftT, typename SubactorT, typename CharT >
class max_size_decorator_output_terminal
{
private:
//! Self type
typedef max_size_decorator_output_terminal< LeftT, SubactorT, CharT > this_type;
public:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
//! String size type
typedef std::size_t size_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;
//! Max size of the formatted string produced by the adopted formatter
size_type m_max_size;
//! Overflow marker
string_type m_overflow_marker;
public:
/*!
* Initializing constructor. Creates decorator of the \a fmt formatter with the specified \a decorations.
*/
max_size_decorator_output_terminal(LeftT const& left, subactor_type const& sub, size_type max_size, string_type const& overflow_marker = string_type()) :
m_left(left), m_subactor(sub), m_max_size(max_size), m_overflow_marker(overflow_marker)
{
BOOST_ASSERT(overflow_marker.size() <= max_size);
}
/*!
* Copy constructor
*/
max_size_decorator_output_terminal(max_size_decorator_output_terminal const& that) :
m_left(that.m_left), m_subactor(that.m_subactor), m_max_size(that.m_max_size), m_overflow_marker(that.m_overflow_marker)
{
}
/*!
* 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();
if (!strm.rdbuf()->storage_overflow())
{
const size_type old_max_size = strm.rdbuf()->max_size();
const size_type start_pos = strm.rdbuf()->storage()->size(), max_size_left = strm.rdbuf()->storage()->max_size() - start_pos;
strm.rdbuf()->max_size(start_pos + (m_max_size <= max_size_left ? m_max_size : max_size_left));
try
{
// Invoke the adopted formatter
phoenix::eval(m_subactor, ctx);
// Flush the buffered characters and apply decorations
strm.flush();
if (strm.rdbuf()->storage_overflow())
{
if (!m_overflow_marker.empty())
{
// Free up space for the overflow marker
strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
// Append the marker
strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size());
strm.rdbuf()->storage_overflow(false);
strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
}
else
{
strm.rdbuf()->storage_overflow(false);
}
}
// Restore the original size limit
strm.rdbuf()->max_size(old_max_size);
}
catch (...)
{
strm.rdbuf()->storage_overflow(false);
strm.rdbuf()->max_size(old_max_size);
throw;
}
}
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();
if (!strm.rdbuf()->storage_overflow())
{
const size_type old_max_size = strm.rdbuf()->max_size();
const size_type start_pos = strm.rdbuf()->storage()->size(), max_size_left = strm.rdbuf()->storage()->max_size() - start_pos;
strm.rdbuf()->max_size(start_pos + (m_max_size <= max_size_left ? m_max_size : max_size_left));
try
{
// Invoke the adopted formatter
phoenix::eval(m_subactor, ctx);
// Flush the buffered characters and apply decorations
strm.flush();
if (strm.rdbuf()->storage_overflow())
{
if (!m_overflow_marker.empty())
{
// Free up space for the overflow marker
strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
// Append the marker
strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size());
strm.rdbuf()->storage_overflow(false);
strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
}
else
{
strm.rdbuf()->storage_overflow(false);
}
}
// Restore the original size limit
strm.rdbuf()->max_size(old_max_size);
}
catch (...)
{
strm.rdbuf()->storage_overflow(false);
strm.rdbuf()->max_size(old_max_size);
throw;
}
}
return strm;
}
BOOST_DELETED_FUNCTION(max_size_decorator_output_terminal())
};
} // namespace aux
/*!
* String size limiting decorator terminal class. This formatter allows to limit the maximum total length
* of the strings generated by other formatters.
*
* The \c max_size_decorator_terminal class aggregates the formatter being decorated, the maximum string length
* it can produce and an optional truncation marker string, which will be put at the end of the output if the limit is exceeded. Note that
* the marker length is included in the limit and as such must not exceed it.
* The \c max_size_decorator_terminal class is a formatter itself, so it can be used to construct
* more complex formatters, including nesting decorators.
*/
template< typename SubactorT, typename CharT >
class max_size_decorator_terminal
{
private:
//! Self type
typedef max_size_decorator_terminal< SubactorT, CharT > this_type;
public:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal typedef for type categorization
typedef void _is_boost_log_terminal;
#endif
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
//! String size type
typedef std::size_t size_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;
//! Max size of the formatted string produced by the adopted formatter
size_type m_max_size;
//! Overflow marker
string_type m_overflow_marker;
public:
/*!
* Initializing constructor.
*/
max_size_decorator_terminal(subactor_type const& sub, size_type max_size, string_type const& overflow_marker = string_type()) :
m_subactor(sub), m_max_size(max_size), m_overflow_marker(overflow_marker)
{
BOOST_ASSERT(overflow_marker.size() <= max_size);
}
/*!
* Copy constructor
*/
max_size_decorator_terminal(max_size_decorator_terminal const& that) :
m_subactor(that.m_subactor), m_max_size(that.m_max_size), m_overflow_marker(that.m_overflow_marker)
{
}
/*!
* \returns Adopted subactor
*/
subactor_type const& get_subactor() const
{
return m_subactor;
}
/*!
* \returns Max string size limit
*/
size_type get_max_size() const
{
return m_max_size;
}
/*!
* \returns Max string size limit
*/
string_type const& get_overflow_marker() const
{
return m_overflow_marker;
}
/*!
* Invokation operator
*/
template< typename ContextT >
result_type operator() (ContextT const& ctx)
{
string_type str;
stream_type strm(str);
strm.rdbuf()->max_size(m_max_size);
// 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 see of overflow happened
strm.flush();
if (strm.rdbuf()->storage_overflow() && !m_overflow_marker.empty())
{
strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
strm.rdbuf()->max_size(str.max_size());
strm.rdbuf()->storage_overflow(false);
strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
strm.flush();
}
return BOOST_LOG_NRVO_RESULT(str);
}
/*!
* Invokation operator
*/
template< typename ContextT >
result_type operator() (ContextT const& ctx) const
{
string_type str;
stream_type strm(str);
strm.rdbuf()->max_size(m_max_size);
// 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 see of overflow happened
strm.flush();
if (strm.rdbuf()->storage_overflow())
{
strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size());
strm.rdbuf()->max_size(str.max_size());
strm.rdbuf()->storage_overflow(false);
strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size());
strm.flush();
}
return BOOST_LOG_NRVO_RESULT(str);
}
BOOST_DELETED_FUNCTION(max_size_decorator_terminal())
};
/*!
* Character decorator actor
*/
template< typename SubactorT, typename CharT, template< typename > class ActorT = phoenix::actor >
class max_size_decorator_actor :
public ActorT< max_size_decorator_terminal< SubactorT, CharT > >
{
public:
//! Base terminal type
typedef max_size_decorator_terminal< SubactorT, CharT > 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 max_size_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 CharT, template< typename > class ActorT >\
BOOST_FORCEINLINE phoenix::actor< aux::max_size_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, CharT > >\
operator<< (phoenix::actor< LeftExprT > left_ref left, max_size_decorator_actor< SubactorT, CharT, ActorT > right_ref right)\
{\
typedef aux::max_size_decorator_output_terminal< phoenix::actor< LeftExprT >, SubactorT, CharT > terminal_type;\
phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.get_terminal().get_subactor(), right.get_terminal().get_max_size(), right.get_terminal().get_overflow_marker()) }};\
return actor;\
}
#include <boost/log/detail/generate_overloads.hpp>
#undef BOOST_LOG_AUX_OVERLOAD
#endif // BOOST_LOG_DOXYGEN_PASS
namespace aux {
template< typename CharT >
class max_size_decorator_gen
{
private:
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::size_t size_type;
private:
size_type m_max_size;
string_type m_overflow_marker;
public:
explicit max_size_decorator_gen(size_type max_size, string_type const& overflow_marker = string_type()) :
m_max_size(max_size), m_overflow_marker(overflow_marker)
{
BOOST_ASSERT(overflow_marker.size() <= max_size);
}
template< typename SubactorT >
BOOST_FORCEINLINE max_size_decorator_actor< SubactorT, char_type > operator[] (SubactorT const& subactor) const
{
typedef max_size_decorator_actor< SubactorT, char_type > result_type;
typedef typename result_type::terminal_type terminal_type;
typename result_type::base_type act = {{ terminal_type(subactor, m_max_size, m_overflow_marker) }};
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 max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce.
*/
template< typename CharT >
BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size)
{
return aux::max_size_decorator_gen< CharT >(max_size);
}
/*!
* The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
* to construct the actual decorator.
*
* \param max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce.
* \param overflow_marker The marker string which is appended to the output if the \a max_size limit is exceeded. Must be
* a non-null pointer to a zero-terminated string.
*
* \pre The \a overflow_marker length must not exceed the \a max_size limit.
*/
template< typename CharT >
BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size, const CharT* overflow_marker)
{
return aux::max_size_decorator_gen< CharT >(max_size, overflow_marker);
}
/*!
* The function returns a decorator generator object. The generator provides <tt>operator[]</tt> that can be used
* to construct the actual decorator.
*
* \param max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce.
* \param overflow_marker The marker string which is appended to the output if the \a max_size limit is exceeded.
*
* \pre The \a overflow_marker length must not exceed the \a max_size limit.
*/
template< typename CharT >
BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size, std::basic_string< CharT > const& overflow_marker)
{
return aux::max_size_decorator_gen< CharT >(max_size, overflow_marker);
}
} // namespace expressions
BOOST_LOG_CLOSE_NAMESPACE // namespace log
#ifndef BOOST_LOG_DOXYGEN_PASS
namespace phoenix {
namespace result_of {
template< typename SubactorT, typename CharT >
struct is_nullary< custom_terminal< boost::log::expressions::max_size_decorator_terminal< SubactorT, CharT > > > :
public mpl::false_
{
};
template< typename LeftT, typename SubactorT, typename CharT >
struct is_nullary< custom_terminal< boost::log::expressions::aux::max_size_decorator_output_terminal< LeftT, SubactorT, CharT > > > :
public mpl::false_
{
};
} // namespace result_of
} // namespace phoenix
#endif
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_MAX_SIZE_DECORATOR_HPP_INCLUDED_

Some files were not shown because too many files have changed in this diff Show More