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,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_