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,354 @@
/*
* 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 exception_handler.hpp
* \author Andrey Semashev
* \date 12.07.2009
*
* This header contains tools for exception handlers support in different parts of the library.
*/
#ifndef BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
#include <new> // std::nothrow_t
#include <boost/mpl/bind.hpp>
#include <boost/mpl/quote.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/nop.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_LOG_MAX_EXCEPTION_TYPES
//! Maximum number of exception types that can be specified for exception handlers
#define BOOST_LOG_MAX_EXCEPTION_TYPES 10
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_exception_types, exception_types, false)
//! Root class for the exception handler class hierarchy
template< typename HandlerT >
class eh_root
{
public:
//! The exception handler type
typedef HandlerT handler_type;
//! The handler result type
typedef void result_type;
protected:
//! Exception handler
handler_type m_Handler;
public:
//! Initializing constructor
explicit eh_root(handler_type const& handler) : m_Handler(handler)
{
}
//! Exception launcher
void operator()() const
{
throw;
}
};
//! A cons-list element of the exception handler class hierarchy
template< typename ExceptionT, typename BaseT >
class eh_cons :
public BaseT
{
//! Base type
typedef BaseT base_type;
public:
//! The exception handler type
typedef typename base_type::handler_type handler_type;
public:
//! Initializing constructor
explicit eh_cons(handler_type const& handler) : base_type(handler)
{
}
//! Exception launcher
void operator()() const
{
try
{
base_type::operator()();
}
catch (ExceptionT& e)
{
this->m_Handler(e);
}
}
};
template< template< typename, typename > class EHT, typename HandlerT >
struct make_self_contained_exception_handler
{
typedef EHT< typename HandlerT::exception_types, HandlerT > type;
};
} // namespace aux
/*!
* An exception handler functional object. The handler aggregates a user-defined
* functional object that will be called when one of the specified exception types
* is caught.
*/
template< typename SequenceT, typename HandlerT >
class exception_handler :
public mpl::fold<
SequenceT,
aux::eh_root< HandlerT >,
mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
>::type
{
//! Base type
typedef typename mpl::fold<
SequenceT,
aux::eh_root< HandlerT >,
mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
>::type base_type;
public:
#ifndef BOOST_LOG_DOXYGEN_PASS
typedef typename base_type::handler_type handler_type;
#else
//! The exception handler type
typedef HandlerT handler_type;
//! The handler result type
typedef void result_type;
#endif
public:
/*!
* Initializing constructor. Creates an exception handler with the specified
* function object that will receive the exception.
*/
explicit exception_handler(handler_type const& handler) : base_type(handler)
{
}
/*!
* Exception launcher. Rethrows the current exception in order to detect its type
* and pass it to the aggregated function object.
*
* \note Must be called from within a \c catch statement.
*/
void operator()() const
{
base_type::operator()();
}
};
/*!
* A no-throw exception handler functional object. Acts similar to \c exception_handler,
* but in case if the exception cannot be handled the exception is not propagated
* from the handler. Instead the user-defined functional object is called with
* no parameters.
*/
template< typename SequenceT, typename HandlerT >
class nothrow_exception_handler :
public exception_handler< SequenceT, HandlerT >
{
//! Base type
typedef exception_handler< SequenceT, HandlerT > base_type;
public:
#ifndef BOOST_LOG_DOXYGEN_PASS
typedef typename base_type::handler_type handler_type;
#else
//! The exception handler type
typedef HandlerT handler_type;
//! The handler result type
typedef void result_type;
#endif
public:
/*!
* Initializing constructor. Creates an exception handler with the specified
* function object that will receive the exception.
*/
explicit nothrow_exception_handler(handler_type const& handler) : base_type(handler)
{
}
/*!
* Exception launcher. Rethrows the current exception in order to detect its type
* and pass it to the aggregated function object. If the type of the exception
* could not be detected, the user-defined handler is called with no arguments.
*
* \note Must be called from within a \c catch statement.
*/
void operator()() const
{
try
{
base_type::operator()();
}
catch (...)
{
this->m_Handler();
}
}
};
/*!
* The function creates an empty exception handler that effectively suppresses any exception
*/
inline nop make_exception_suppressor()
{
return nop();
}
#ifndef BOOST_LOG_DOXYGEN_PASS
template< typename HandlerT >
inline typename boost::lazy_enable_if_c<
aux::has_exception_types< HandlerT >::value,
aux::make_self_contained_exception_handler< exception_handler, HandlerT >
>::type make_exception_handler(HandlerT const& handler)
{
typedef typename aux::make_self_contained_exception_handler< exception_handler, HandlerT >::type eh_t;
return eh_t(handler);
}
template< typename HandlerT >
inline typename boost::lazy_enable_if_c<
aux::has_exception_types< HandlerT >::value,
aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >
>::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&)
{
typedef typename aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >::type eh_t;
return eh_t(handler);
}
#define BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL(z, n, data)\
template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\
inline exception_handler<\
BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
HandlerT\
> make_exception_handler(HandlerT const& handler)\
{\
typedef exception_handler<\
BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
HandlerT\
> eh_t;\
return eh_t(handler);\
}\
template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\
inline nothrow_exception_handler<\
BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
HandlerT\
> make_exception_handler(HandlerT const& handler, std::nothrow_t const&)\
{\
typedef nothrow_exception_handler<\
BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
HandlerT\
> eh_t;\
return eh_t(handler);\
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_EXCEPTION_TYPES, BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL, ~)
#undef BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* The function creates an exception handler functional object. The handler will call to the
* user-specified functional object with an exception as its argument.
*
* \param handler User-defined functional object that will receive exceptions.
* \return A nullary functional object that should be called from within a \c catch statement.
*
* \note This form requires the user-defined functional object to have an \c exception_types
* nested type. This type should be an MPL sequence of all expected exception types.
*/
template< typename HandlerT >
exception_handler< typename HandlerT::exception_types, HandlerT >
make_exception_handler(HandlerT const& handler);
/*!
* The function creates an exception handler functional object. The handler will call to the
* user-specified functional object with an exception as its argument. If the exception type
* cannot be identified, the handler will call the user-defined functor with no arguments,
* instead of propagating exception to the caller.
*
* \overload
*
* \param handler User-defined functional object that will receive exceptions.
* \return A nullary functional object that should be called from within a \c catch statement.
*
* \note This form requires the user-defined functional object to have an \c exception_types
* nested type. This type should be an MPL sequence of all expected exception types.
*/
template< typename HandlerT >
nothrow_exception_handler< typename HandlerT::exception_types, HandlerT >
make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
/*!
* The function creates an exception handler functional object. The handler will call to the
* user-specified functional object with an exception as its argument. All expected exception
* types should be specified as first template parameters explicitly, in the order they would
* be specified in a corresponding <tt>try/catch</tt> statement.
*
* \overload
*
* \param handler User-defined functional object that will receive exceptions.
* \return A nullary functional object that should be called from within a \c catch statement.
*/
template< typename... ExceptionsT, typename HandlerT >
exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
make_exception_handler(HandlerT const& handler);
/*!
* The function creates an exception handler functional object. The handler will call to the
* user-specified functional object with an exception as its argument. If the exception type
* cannot be identified, the handler will call the user-defined functor with no arguments,
* instead of propagating exception to the caller. All expected exception types should be
* specified as first template parameters explicitly, in the order they would be specified in
* a corresponding <tt>try/catch</tt> statement.
*
* \overload
*
* \param handler User-defined functional object that will receive exceptions.
* \return A nullary functional object that should be called from within a \c catch statement.
*/
template< typename... ExceptionsT, typename HandlerT >
nothrow_exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
#endif // BOOST_LOG_DOXYGEN_PASS
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
@@ -0,0 +1,916 @@
/*
* 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 formatting_ostream.hpp
* \author Andrey Semashev
* \date 11.07.2012
*
* The header contains implementation of a string stream used for log record formatting.
*/
#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
#include <ostream>
#include <string>
#include <memory>
#include <locale>
#include <boost/core/enable_if.hpp>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/utility/string_ref_fwd.hpp>
#include <boost/utility/string_view_fwd.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/attachable_sstream_buf.hpp>
#include <boost/log/detail/code_conversion.hpp>
#include <boost/log/utility/string_literal_fwd.hpp>
#include <boost/log/utility/formatting_ostream_fwd.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
template< typename T, typename R >
struct enable_if_streamable_char_type {};
template< typename R >
struct enable_if_streamable_char_type< char, R > { typedef R type; };
template< typename R >
struct enable_if_streamable_char_type< wchar_t, R > { typedef R type; };
#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
template< typename R >
struct enable_if_streamable_char_type< char16_t, R > { typedef R type; };
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
template< typename R >
struct enable_if_streamable_char_type< char32_t, R > { typedef R type; };
#endif
#endif
template< typename StreamT, typename T, bool ByValueV, typename R >
struct enable_formatting_ostream_generic_operator {};
template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T, false, R > :
public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
{
};
template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T, true, R > :
public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
{
};
} // namespace aux
/*!
* \brief Stream wrapper for log records formatting.
*
* This stream wrapper is used by the library for log record formatting. It implements the standard string stream interface
* with a few differences:
*
* \li It does not derive from standard types <tt>std::basic_ostream</tt>, <tt>std::basic_ios</tt> and <tt>std::ios_base</tt>,
* although it tries to implement their interfaces closely. There are a few small differences, mostly regarding <tt>rdbuf</tt>
* and <tt>str</tt> signatures, as well as the supported insertion operator overloads. The actual wrapped stream can be accessed
* through the <tt>stream</tt> methods.
* \li By default, \c bool values are formatted using alphabetical representation rather than numeric.
* \li The stream supports writing strings of character types different from the stream character type. The stream will perform
* character code conversion as needed using the imbued locale.
* \li The stream operates on an external string object rather than on the embedded one. The string can be attached or detached
* from the stream dynamically.
*
* Although <tt>basic_formatting_ostream</tt> does not derive from <tt>std::basic_ostream</tt>, users are not required to add
* special overloads of \c operator<< for it since the stream will by default reuse the operators for <tt>std::basic_ostream</tt>.
* However, one can define special overloads of \c operator<< for <tt>basic_formatting_ostream</tt> if a certain type needs
* special formatting when output to log.
*/
template< typename CharT, typename TraitsT, typename AllocatorT >
class basic_formatting_ostream
{
public:
//! Character type
typedef CharT char_type;
//! Character traits
typedef TraitsT traits_type;
//! Memory allocator
typedef AllocatorT allocator_type;
//! Stream buffer type
typedef boost::log::aux::basic_ostringstreambuf< char_type, traits_type, allocator_type > streambuf_type;
//! Target string type
typedef typename streambuf_type::string_type string_type;
//! Stream type
typedef std::basic_ostream< char_type, traits_type > ostream_type;
//! Stream position type
typedef typename ostream_type::pos_type pos_type;
//! Stream offset type
typedef typename ostream_type::off_type off_type;
//! Integer type for characters
typedef typename ostream_type::int_type int_type;
typedef typename ostream_type::failure failure;
typedef typename ostream_type::fmtflags fmtflags;
typedef typename ostream_type::iostate iostate;
typedef typename ostream_type::openmode openmode;
typedef typename ostream_type::seekdir seekdir;
typedef typename ostream_type::Init Init;
typedef typename ostream_type::event event;
typedef typename ostream_type::event_callback event_callback;
class sentry :
public ostream_type::sentry
{
typedef typename ostream_type::sentry base_type;
public:
explicit sentry(basic_formatting_ostream& strm) : base_type(strm.stream())
{
}
// A workaround for Solaris Studio 12.4 compiler, see: https://svn.boost.org/trac/boost/ticket/11545
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const { return !static_cast< base_type const& >(*this); }
BOOST_DELETED_FUNCTION(sentry(sentry const&))
BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&))
};
protected:
// Function types
typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
typedef std::basic_ios< char_type, traits_type >& (*basic_ios_manip)(std::basic_ios< char_type, traits_type >&);
typedef ostream_type& (*stream_manip)(ostream_type&);
public:
static BOOST_CONSTEXPR_OR_CONST fmtflags boolalpha = ostream_type::boolalpha;
static BOOST_CONSTEXPR_OR_CONST fmtflags dec = ostream_type::dec;
static BOOST_CONSTEXPR_OR_CONST fmtflags fixed = ostream_type::fixed;
static BOOST_CONSTEXPR_OR_CONST fmtflags hex = ostream_type::hex;
static BOOST_CONSTEXPR_OR_CONST fmtflags internal = ostream_type::internal;
static BOOST_CONSTEXPR_OR_CONST fmtflags left = ostream_type::left;
static BOOST_CONSTEXPR_OR_CONST fmtflags oct = ostream_type::oct;
static BOOST_CONSTEXPR_OR_CONST fmtflags right = ostream_type::right;
static BOOST_CONSTEXPR_OR_CONST fmtflags scientific = ostream_type::scientific;
static BOOST_CONSTEXPR_OR_CONST fmtflags showbase = ostream_type::showbase;
static BOOST_CONSTEXPR_OR_CONST fmtflags showpoint = ostream_type::showpoint;
static BOOST_CONSTEXPR_OR_CONST fmtflags skipws = ostream_type::skipws;
static BOOST_CONSTEXPR_OR_CONST fmtflags unitbuf = ostream_type::unitbuf;
static BOOST_CONSTEXPR_OR_CONST fmtflags uppercase = ostream_type::uppercase;
static BOOST_CONSTEXPR_OR_CONST fmtflags adjustfield = ostream_type::adjustfield;
static BOOST_CONSTEXPR_OR_CONST fmtflags basefield = ostream_type::basefield;
static BOOST_CONSTEXPR_OR_CONST fmtflags floatfield = ostream_type::floatfield;
static BOOST_CONSTEXPR_OR_CONST iostate badbit = ostream_type::badbit;
static BOOST_CONSTEXPR_OR_CONST iostate eofbit = ostream_type::eofbit;
static BOOST_CONSTEXPR_OR_CONST iostate failbit = ostream_type::failbit;
static BOOST_CONSTEXPR_OR_CONST iostate goodbit = ostream_type::goodbit;
static BOOST_CONSTEXPR_OR_CONST openmode app = ostream_type::app;
static BOOST_CONSTEXPR_OR_CONST openmode ate = ostream_type::ate;
static BOOST_CONSTEXPR_OR_CONST openmode binary = ostream_type::binary;
static BOOST_CONSTEXPR_OR_CONST openmode in = ostream_type::in;
static BOOST_CONSTEXPR_OR_CONST openmode out = ostream_type::out;
static BOOST_CONSTEXPR_OR_CONST openmode trunc = ostream_type::trunc;
static BOOST_CONSTEXPR_OR_CONST seekdir beg = ostream_type::beg;
static BOOST_CONSTEXPR_OR_CONST seekdir cur = ostream_type::cur;
static BOOST_CONSTEXPR_OR_CONST seekdir end = ostream_type::end;
static BOOST_CONSTEXPR_OR_CONST event erase_event = ostream_type::erase_event;
static BOOST_CONSTEXPR_OR_CONST event imbue_event = ostream_type::imbue_event;
static BOOST_CONSTEXPR_OR_CONST event copyfmt_event = ostream_type::copyfmt_event;
private:
mutable streambuf_type m_streambuf;
ostream_type m_stream;
public:
/*!
* Default constructor. Creates an empty record that is equivalent to the invalid record handle.
* The stream capability is not available after construction.
*
* \post <tt>!*this == true</tt>
*/
basic_formatting_ostream() : m_stream(&m_streambuf)
{
init_stream();
}
/*!
* Initializing constructor. Attaches the string to the constructed stream.
* The string will be used to store the formatted characters.
*
* \post <tt>!*this == false</tt>
* \param str The string buffer to attach.
*/
explicit basic_formatting_ostream(string_type& str) :
m_streambuf(str),
m_stream(&m_streambuf)
{
init_stream();
}
/*!
* Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
*/
~basic_formatting_ostream()
{
if (m_streambuf.storage())
flush();
}
/*!
* Attaches the stream to the string. The string will be used to store the formatted characters.
*
* \param str The string buffer to attach.
*/
void attach(string_type& str)
{
m_streambuf.attach(str);
m_stream.clear(ostream_type::goodbit);
}
/*!
* Detaches the stream from the string. Any buffered data is flushed to the string.
*/
void detach()
{
m_streambuf.detach();
m_stream.clear(ostream_type::badbit);
}
/*!
* \returns Reference to the attached string. The string must be attached before calling this method.
*/
string_type const& str() const
{
string_type* const storage = m_streambuf.storage();
BOOST_ASSERT(storage != NULL);
m_streambuf.pubsync();
return *storage;
}
/*!
* \returns Reference to the wrapped stream
*/
ostream_type& stream() { return m_stream; }
/*!
* \returns Reference to the wrapped stream
*/
ostream_type const& stream() const { return m_stream; }
// std::ios_base method forwarders
fmtflags flags() const { return m_stream.flags(); }
fmtflags flags(fmtflags f) { return m_stream.flags(f); }
fmtflags setf(fmtflags f) { return m_stream.setf(f); }
fmtflags setf(fmtflags f, fmtflags mask) { return m_stream.setf(f, mask); }
void unsetf(fmtflags f) { m_stream.unsetf(f); }
std::streamsize precision() const { return m_stream.precision(); }
std::streamsize precision(std::streamsize p) { return m_stream.precision(p); }
std::streamsize width() const { return m_stream.width(); }
std::streamsize width(std::streamsize w) { return m_stream.width(w); }
std::locale getloc() const { return m_stream.getloc(); }
std::locale imbue(std::locale const& loc) { return m_stream.imbue(loc); }
static int xalloc() { return ostream_type::xalloc(); }
long& iword(int index) { return m_stream.iword(index); }
void*& pword(int index) { return m_stream.pword(index); }
void register_callback(event_callback fn, int index) { m_stream.register_callback(fn, index); }
static bool sync_with_stdio(bool sync = true) { return ostream_type::sync_with_stdio(sync); }
// std::basic_ios method forwarders
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const { return !m_stream; }
iostate rdstate() const { return m_stream.rdstate(); }
void clear(iostate state = goodbit) { m_stream.clear(state); }
void setstate(iostate state) { m_stream.setstate(state); }
bool good() const { return m_stream.good(); }
bool eof() const { return m_stream.eof(); }
bool fail() const { return m_stream.fail(); }
bool bad() const { return m_stream.bad(); }
iostate exceptions() const { return m_stream.exceptions(); }
void exceptions(iostate s) { m_stream.exceptions(s); }
ostream_type* tie() const { return m_stream.tie(); }
ostream_type* tie(ostream_type* strm) { return m_stream.tie(strm); }
streambuf_type* rdbuf() const { return &m_streambuf; }
basic_formatting_ostream& copyfmt(std::basic_ios< char_type, traits_type >& rhs)
{
m_stream.copyfmt(rhs);
return *this;
}
basic_formatting_ostream& copyfmt(basic_formatting_ostream& rhs)
{
m_stream.copyfmt(rhs.stream());
return *this;
}
char_type fill() const { return m_stream.fill(); }
char_type fill(char_type ch) { return m_stream.fill(ch); }
char narrow(char_type ch, char def) const { return m_stream.narrow(ch, def); }
char_type widen(char ch) const { return m_stream.widen(ch); }
// std::basic_ostream method forwarders
basic_formatting_ostream& flush()
{
m_stream.flush();
return *this;
}
pos_type tellp() { return m_stream.tellp(); }
basic_formatting_ostream& seekp(pos_type pos)
{
m_stream.seekp(pos);
return *this;
}
basic_formatting_ostream& seekp(off_type off, std::ios_base::seekdir dir)
{
m_stream.seekp(off, dir);
return *this;
}
basic_formatting_ostream& put(char_type c)
{
m_stream.put(c);
return *this;
}
template< typename OtherCharT >
typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
put(OtherCharT c)
{
write(&c, 1);
return *this;
}
basic_formatting_ostream& write(const char_type* p, std::streamsize size)
{
m_stream.write(p, size);
return *this;
}
template< typename OtherCharT >
typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
write(const OtherCharT* p, std::streamsize size)
{
sentry guard(*this);
if (!!guard)
{
m_stream.flush();
if (!m_streambuf.storage_overflow())
{
string_type* storage = m_streambuf.storage();
if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
m_streambuf.storage_overflow(true);
}
}
return *this;
}
basic_formatting_ostream& operator<< (ios_base_manip manip)
{
m_stream << manip;
return *this;
}
basic_formatting_ostream& operator<< (basic_ios_manip manip)
{
m_stream << manip;
return *this;
}
basic_formatting_ostream& operator<< (stream_manip manip)
{
m_stream << manip;
return *this;
}
basic_formatting_ostream& operator<< (char c)
{
return this->formatted_write(&c, 1);
}
basic_formatting_ostream& operator<< (const char* p)
{
return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p)));
}
// When no native character type is supported, the following overloads are disabled as they have ambiguous meaning.
// Use basic_string_view or basic_string to explicitly indicate that the data is a string.
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
basic_formatting_ostream& operator<< (wchar_t c)
{
return this->formatted_write(&c, 1);
}
basic_formatting_ostream& operator<< (const wchar_t* p)
{
return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p)));
}
#endif
#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
basic_formatting_ostream& operator<< (char16_t c)
{
return this->formatted_write(&c, 1);
}
basic_formatting_ostream& operator<< (const char16_t* p)
{
return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p)));
}
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
basic_formatting_ostream& operator<< (char32_t c)
{
return this->formatted_write(&c, 1);
}
basic_formatting_ostream& operator<< (const char32_t* p)
{
return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p)));
}
#endif
#endif
basic_formatting_ostream& operator<< (bool value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (signed char value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (unsigned char value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (short value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (unsigned short value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (int value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (unsigned int value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (long value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (unsigned long value)
{
m_stream << value;
return *this;
}
#if !defined(BOOST_NO_LONG_LONG)
basic_formatting_ostream& operator<< (long long value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (unsigned long long value)
{
m_stream << value;
return *this;
}
#endif
basic_formatting_ostream& operator<< (float value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (double value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (long double value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (const void* value)
{
m_stream << value;
return *this;
}
basic_formatting_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
{
m_stream << buf;
return *this;
}
template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_view< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
// Deprecated overload
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT >& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_view< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
// Deprecated overload
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_view< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
// Deprecated overload
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT >& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
}
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_view< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
// Deprecated overload
template< typename OtherCharT, typename OtherTraitsT >
friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
operator<< (basic_formatting_ostream&& strm, basic_string_ref< OtherCharT, OtherTraitsT >& str)
{
return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
}
#endif
protected:
void init_stream()
{
m_stream.exceptions(ostream_type::goodbit);
m_stream.clear(m_streambuf.storage() ? ostream_type::goodbit : ostream_type::badbit);
m_stream.flags
(
ostream_type::dec |
ostream_type::skipws |
ostream_type::boolalpha // this differs from the default stream flags but makes logs look better
);
m_stream.width(0);
m_stream.precision(6);
m_stream.fill(static_cast< char_type >(' '));
}
private:
basic_formatting_ostream& formatted_write(const char_type* p, std::streamsize size)
{
sentry guard(*this);
if (!!guard)
{
m_stream.flush();
if (m_stream.width() <= size)
m_streambuf.append(p, static_cast< std::size_t >(size));
else
this->aligned_write(p, size);
m_stream.width(0);
}
return *this;
}
template< typename OtherCharT >
basic_formatting_ostream& formatted_write(const OtherCharT* p, std::streamsize size)
{
sentry guard(*this);
if (!!guard)
{
m_stream.flush();
if (m_stream.width() <= size)
{
if (!m_streambuf.storage_overflow())
{
if (!aux::code_convert(p, static_cast< std::size_t >(size), *m_streambuf.storage(), m_streambuf.max_size(), m_stream.getloc()))
m_streambuf.storage_overflow(true);
}
}
else
this->aligned_write(p, size);
m_stream.width(0);
}
return *this;
}
void aligned_write(const char_type* p, std::streamsize size);
template< typename OtherCharT >
void aligned_write(const OtherCharT* p, std::streamsize size);
//! Copy constructor (closed)
BOOST_DELETED_FUNCTION(basic_formatting_ostream(basic_formatting_ostream const& that))
//! Assignment (closed)
BOOST_DELETED_FUNCTION(basic_formatting_ostream& operator= (basic_formatting_ostream const& that))
};
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::boolalpha;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::dec;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fixed;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::hex;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::internal;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::left;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::oct;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::right;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::scientific;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showbase;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showpoint;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::skipws;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::unitbuf;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::uppercase;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::adjustfield;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::basefield;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::floatfield;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::badbit;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::eofbit;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::failbit;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::goodbit;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::app;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::ate;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::binary;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::in;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::out;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::trunc;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::beg;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::cur;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::end;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::erase_event;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::imbue_event;
template< typename CharT, typename TraitsT, typename AllocatorT >
BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::copyfmt_event;
template< typename CharT, typename TraitsT, typename AllocatorT >
void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const char_type* p, std::streamsize size)
{
typename string_type::size_type const alignment_size =
static_cast< typename string_type::size_type >(m_stream.width() - size);
const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
if (align_left)
{
m_streambuf.append(p, static_cast< std::size_t >(size));
m_streambuf.append(alignment_size, m_stream.fill());
}
else
{
m_streambuf.append(alignment_size, m_stream.fill());
m_streambuf.append(p, static_cast< std::size_t >(size));
}
}
template< typename CharT, typename TraitsT, typename AllocatorT >
template< typename OtherCharT >
void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const OtherCharT* p, std::streamsize size)
{
string_type* const storage = m_streambuf.storage();
typename string_type::size_type const alignment_size =
static_cast< typename string_type::size_type >(m_stream.width() - size);
const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
if (align_left)
{
if (!m_streambuf.storage_overflow())
{
if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
m_streambuf.storage_overflow(true);
}
m_streambuf.append(alignment_size, m_stream.fill());
}
else
{
m_streambuf.append(alignment_size, m_stream.fill());
if (!m_streambuf.storage_overflow())
{
if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
m_streambuf.storage_overflow(true);
}
}
}
// Implementation note: these operators below should be the least attractive for the compiler
// so that user's overloads are chosen, when present. We use function template partial ordering for this purpose.
// We also don't use perfect forwarding for the right hand argument because in this case the generic overload
// would be more preferred than the typical one written by users:
//
// formatting_ostream& operator<< (formatting_ostream& strm, my_type const& arg);
//
// This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required
// if there is a perfect forwarding overload.
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, true, StreamT& >::type
operator<< (StreamT& strm, T value)
{
strm.stream() << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT& strm, T const& value)
{
strm.stream() << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT& strm, T& value)
{
strm.stream() << value;
return strm;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, true, StreamT& >::type
operator<< (StreamT&& strm, T value)
{
strm.stream() << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT&& strm, T const& value)
{
strm.stream() << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT&& strm, T& value)
{
strm.stream() << value;
return strm;
}
#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
@@ -0,0 +1,51 @@
/*
* 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 formatting_ostream_fwd.hpp
* \author Andrey Semashev
* \date 11.07.2012
*
* The header contains forward declaration of a string stream used for log record formatting.
*/
#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_
#include <string>
#include <memory>
#include <boost/log/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief Stream for log records formatting
*/
template<
typename CharT,
typename TraitsT = std::char_traits< CharT >,
typename AllocatorT = std::allocator< CharT >
>
class basic_formatting_ostream;
#ifdef BOOST_LOG_USE_CHAR
typedef basic_formatting_ostream< char > formatting_ostream;
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
typedef basic_formatting_ostream< wchar_t > wformatting_ostream;
#endif
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_FWD_HPP_INCLUDED_
@@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file functional.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header includes all functional helpers.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/logical.hpp>
#include <boost/log/utility/functional/in_range.hpp>
#include <boost/log/utility/functional/begins_with.hpp>
#include <boost/log/utility/functional/ends_with.hpp>
#include <boost/log/utility/functional/contains.hpp>
#include <boost/log/utility/functional/matches.hpp>
#include <boost/log/utility/functional/nop.hpp>
#include <boost/log/utility/functional/bind_assign.hpp>
#include <boost/log/utility/functional/bind_output.hpp>
#include <boost/log/utility/functional/bind_to_log.hpp>
#include <boost/log/utility/functional/bind.hpp>
#include <boost/log/utility/functional/fun_ref.hpp>
#include <boost/log/utility/functional/as_action.hpp>
#include <boost/log/utility/functional/save_result.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_HPP_INCLUDED_
@@ -0,0 +1,60 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file as_action.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains function object adapter for compatibility with Boost.Spirit actions interface requirements.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! Function object adapter for Boost.Spirit actions
template< typename FunT >
struct as_action_adapter
{
typedef typename FunT::result_type result_type;
BOOST_DEFAULTED_FUNCTION(as_action_adapter(), {})
explicit as_action_adapter(FunT const& fun) : m_fun(fun) {}
template< typename AttributeT, typename ContextT >
result_type operator() (AttributeT const& attr, ContextT const& ctx, bool& pass) const
{
return m_fun(attr);
}
private:
FunT m_fun;
};
template< typename FunT >
BOOST_FORCEINLINE as_action_adapter< FunT > as_action(FunT const& fun)
{
return as_action_adapter< FunT >(fun);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_AS_ACTION_HPP_INCLUDED_
@@ -0,0 +1,57 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file begins_with.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a predicate for checking if the provided string begins with a substring.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The \c begins_with functor
struct begins_with_fun
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
typedef typename T::const_iterator left_iterator;
typedef typename U::const_iterator right_iterator;
left_iterator left_it = left.begin(), left_end = left.end();
right_iterator right_it = right.begin(), right_end = right.end();
for (; left_it != left_end && right_it != right_end; ++left_it, ++right_it)
{
if (*left_it != *right_it)
break;
}
return right_it == right_end;
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BEGINS_WITH_HPP_INCLUDED_
@@ -0,0 +1,237 @@
/*
* 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 bind.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains function object adapters.
* This is a lightweight alternative to what Boost.Phoenix and Boost.Bind provides.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
template< typename T >
struct make_arg_type
{
typedef T const& type;
};
template< typename T >
struct make_arg_type< T& >
{
typedef T& type;
};
} // namespace aux
//! First argument binder
template< typename FunT, typename FirstArgT >
struct binder1st :
private FunT
{
typedef typename FunT::result_type result_type;
binder1st(FunT const& fun, typename aux::make_arg_type< FirstArgT >::type arg) : FunT(fun), m_arg(arg) {}
result_type operator() () const
{
return FunT::operator()(m_arg);
}
template< typename T0 >
result_type operator() (T0 const& arg0) const
{
return FunT::operator()(m_arg, arg0);
}
template< typename T0, typename T1 >
result_type operator() (T0 const& arg0, T1 const& arg1) const
{
return FunT::operator()(m_arg, arg0, arg1);
}
private:
FirstArgT m_arg;
};
//! First argument binder
template< typename FunT, typename FirstArgT >
struct binder1st< FunT&, FirstArgT >
{
typedef typename remove_cv< FunT >::type::result_type result_type;
binder1st(FunT& fun, typename aux::make_arg_type< FirstArgT >::type arg) : m_fun(fun), m_arg(arg) {}
result_type operator() () const
{
return m_fun(m_arg);
}
template< typename T0 >
result_type operator() (T0 const& arg0) const
{
return m_fun(m_arg, arg0);
}
template< typename T0, typename T1 >
result_type operator() (T0 const& arg0, T1 const& arg1) const
{
return m_fun(m_arg, arg0, arg1);
}
private:
FunT& m_fun;
FirstArgT m_arg;
};
template< typename FunT, typename FirstArgT >
BOOST_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT const& arg)
{
return binder1st< FunT, FirstArgT >(fun, arg);
}
template< typename FunT, typename FirstArgT >
BOOST_FORCEINLINE binder1st< FunT, FirstArgT > bind1st(FunT fun, FirstArgT& arg)
{
return binder1st< FunT, FirstArgT >(fun, arg);
}
//! Second argument binder
template< typename FunT, typename SecondArgT >
struct binder2nd :
private FunT
{
typedef typename FunT::result_type result_type;
binder2nd(FunT const& fun, typename aux::make_arg_type< SecondArgT >::type arg) : FunT(fun), m_arg(arg) {}
template< typename T >
result_type operator() (T const& arg) const
{
return FunT::operator()(arg, m_arg);
}
template< typename T0, typename T1 >
result_type operator() (T0 const& arg0, T1 const& arg1) const
{
return FunT::operator()(arg0, m_arg, arg1);
}
private:
SecondArgT m_arg;
};
//! Second argument binder
template< typename FunT, typename SecondArgT >
struct binder2nd< FunT&, SecondArgT >
{
typedef typename remove_cv< FunT >::type::result_type result_type;
binder2nd(FunT& fun, typename aux::make_arg_type< SecondArgT >::type arg) : m_fun(fun), m_arg(arg) {}
template< typename T >
result_type operator() (T const& arg) const
{
return m_fun(arg, m_arg);
}
template< typename T0, typename T1 >
result_type operator() (T0 const& arg0, T1 const& arg1) const
{
return m_fun(arg0, m_arg, arg1);
}
private:
FunT& m_fun;
SecondArgT m_arg;
};
template< typename FunT, typename SecondArgT >
BOOST_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT const& arg)
{
return binder2nd< FunT, SecondArgT >(fun, arg);
}
template< typename FunT, typename SecondArgT >
BOOST_FORCEINLINE binder2nd< FunT, SecondArgT > bind2nd(FunT fun, SecondArgT& arg)
{
return binder2nd< FunT, SecondArgT >(fun, arg);
}
//! Third argument binder
template< typename FunT, typename ThirdArgT >
struct binder3rd :
private FunT
{
typedef typename FunT::result_type result_type;
binder3rd(FunT const& fun, typename aux::make_arg_type< ThirdArgT >::type arg) : FunT(fun), m_arg(arg) {}
template< typename T0, typename T1 >
result_type operator() (T0 const& arg0, T1 const& arg1) const
{
return FunT::operator()(arg0, arg1, m_arg);
}
private:
ThirdArgT m_arg;
};
//! Third argument binder
template< typename FunT, typename ThirdArgT >
struct binder3rd< FunT&, ThirdArgT >
{
typedef typename remove_cv< FunT >::type::result_type result_type;
binder3rd(FunT& fun, typename aux::make_arg_type< ThirdArgT >::type arg) : m_fun(fun), m_arg(arg) {}
template< typename T0, typename T1 >
result_type operator() (T0 const& arg0, T1 const& arg1) const
{
return m_fun(arg0, arg1, m_arg);
}
private:
FunT& m_fun;
ThirdArgT m_arg;
};
template< typename FunT, typename ThirdArgT >
BOOST_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT const& arg)
{
return binder3rd< FunT, ThirdArgT >(fun, arg);
}
template< typename FunT, typename ThirdArgT >
BOOST_FORCEINLINE binder3rd< FunT, ThirdArgT > bind3rd(FunT fun, ThirdArgT& arg)
{
return binder3rd< FunT, ThirdArgT >(fun, arg);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_HPP_INCLUDED_
@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file bind_assign.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a function object that assigns the received value to the bound object.
* This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/bind.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The function object that assigns its second operand to the first one
struct assign_fun
{
typedef void result_type;
template< typename LeftT, typename RightT >
void operator() (LeftT& assignee, RightT const& val) const
{
assignee = val;
}
};
template< typename AssigneeT >
BOOST_FORCEINLINE binder1st< assign_fun, AssigneeT& > bind_assign(AssigneeT& assignee)
{
return binder1st< assign_fun, AssigneeT& >(assign_fun(), assignee);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_ASSIGN_HPP_INCLUDED_
@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file bind_output.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a function object that puts the received value to the bound stream.
* This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/bind.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The function object that outputs its second operand to the first one
struct output_fun
{
typedef void result_type;
template< typename StreamT, typename T >
void operator() (StreamT& strm, T const& val) const
{
strm << val;
}
};
template< typename StreamT >
BOOST_FORCEINLINE binder1st< output_fun, StreamT& > bind_output(StreamT& strm)
{
return binder1st< output_fun, StreamT& >(output_fun(), strm);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_OUTPUT_HPP_INCLUDED_
@@ -0,0 +1,76 @@
/*
* 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 bind_to_log.hpp
* \author Andrey Semashev
* \date 06.11.2012
*
* This header contains a function object that puts the received value to the bound stream using the \c to_log manipulator.
* This is a lightweight alternative to what Boost.Phoenix and Boost.Lambda provides.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/bind.hpp>
#include <boost/log/utility/manipulators/to_log.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The function object that outputs its second operand to the first one
template< typename TagT = void >
struct to_log_fun
{
typedef void result_type;
template< typename StreamT, typename T >
void operator() (StreamT& strm, T const& val) const
{
strm << boost::log::to_log< TagT >(val);
}
};
//! The function object that outputs its second operand to the first one
template< >
struct to_log_fun< void >
{
typedef void result_type;
template< typename StreamT, typename T >
void operator() (StreamT& strm, T const& val) const
{
strm << boost::log::to_log(val);
}
};
template< typename StreamT >
BOOST_FORCEINLINE binder1st< to_log_fun< >, StreamT& > bind_to_log(StreamT& strm)
{
return binder1st< to_log_fun< >, StreamT& >(to_log_fun< >(), strm);
}
template< typename TagT, typename StreamT >
BOOST_FORCEINLINE binder1st< to_log_fun< TagT >, StreamT& > bind_to_log(StreamT& strm)
{
return binder1st< to_log_fun< TagT >, StreamT& >(to_log_fun< TagT >(), strm);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_BIND_TO_LOG_HPP_INCLUDED_
@@ -0,0 +1,69 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file contains.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a predicate for checking if the provided string contains a substring.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The \c contains functor
struct contains_fun
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
typedef typename T::const_iterator left_iterator;
typedef typename U::const_iterator right_iterator;
typename U::size_type const right_size = right.size();
if (left.size() >= right_size)
{
const left_iterator search_end = left.end() - right_size + 1;
const right_iterator right_end = right.end();
for (left_iterator it = left.begin(); it != search_end; ++it)
{
left_iterator left_it = it;
right_iterator right_it = right.begin();
for (; right_it != right_end; ++left_it, ++right_it)
{
if (*left_it != *right_it)
break;
}
if (right_it == right_end)
return true;
}
}
return false;
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_CONTAINS_HPP_INCLUDED_
@@ -0,0 +1,57 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file ends_with.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a predicate for checking if the provided string ends with a substring.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The \c ends_with functor
struct ends_with_fun
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
typedef typename T::const_reverse_iterator left_iterator;
typedef typename U::const_reverse_iterator right_iterator;
left_iterator left_it = left.rbegin(), left_end = left.rend();
right_iterator right_it = right.rbegin(), right_end = right.rend();
for (; left_it != left_end && right_it != right_end; ++left_it, ++right_it)
{
if (*left_it != *right_it)
break;
}
return right_it == right_end;
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_ENDS_WITH_HPP_INCLUDED_
@@ -0,0 +1,79 @@
/*
* 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 fun_ref.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains function object reference adapter. The adapter stores a reference to external
* function object and forwards all calls to the referred function.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! Reference wrapper for function objects
template< typename FunT >
struct function_reference_wrapper
{
typedef typename FunT::result_type result_type;
explicit function_reference_wrapper(FunT& fun) : m_Fun(fun) {}
result_type operator() () const
{
return m_Fun();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template< typename... ArgsT >
result_type operator() (ArgsT const&... args) const
{
return m_Fun(args...);
}
#else
template< typename T >
result_type operator() (T const& arg) const
{
return m_Fun(arg);
}
template< typename T1, typename T2 >
result_type operator() (T1 const& arg1, T2 const& arg2) const
{
return m_Fun(arg1, arg2);
}
#endif
private:
FunT& m_Fun;
};
template< typename FunT >
BOOST_FORCEINLINE function_reference_wrapper< FunT > fun_ref(FunT& fun)
{
return function_reference_wrapper< FunT >(fun);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_FUN_REF_HPP_INCLUDED_
@@ -0,0 +1,63 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file in_range.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a predicate for checking if the provided value is within a half-open range.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_
#include <utility>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/functional/logical.hpp> // make_common_integral_type
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The in_range functor
struct in_range_fun
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& value, std::pair< U, U > const& rng) const
{
return op(value, rng, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& value, std::pair< U, U > const& rng, mpl::false_ const&)
{
return (value >= rng.first && value < rng.second);
}
template< typename T, typename U >
static bool op(T const& value, std::pair< U, U > const& rng, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return (static_cast< common_integral_type >(value) >= static_cast< common_integral_type >(rng.first))
&& (static_cast< common_integral_type >(value) < static_cast< common_integral_type >(rng.second));
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_IN_RANGE_HPP_INCLUDED_
@@ -0,0 +1,225 @@
/*
* 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 logical.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains logical predicates for value comparison, analogous to \c std::less, \c std::greater
* and others. The main difference from the standard equivalents is that the predicates defined in this
* header are not templates and therefore do not require a fixed argument type. Furthermore, both arguments
* may have different types, in which case the comparison is performed without type conversion.
*
* \note In case if arguments are integral, the conversion is performed according to the standard C++ rules
* in order to avoid warnings from the compiler.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! The trait creates a common integral type suitable for comparison. This is mostly to silence compiler warnings like 'signed/unsigned mismatch'.
template< typename T, typename U, unsigned int TSizeV = sizeof(T), unsigned int USizeV = sizeof(U), bool TSmallerThanU = (sizeof(T) < sizeof(U)) >
struct make_common_integral_type
{
typedef T type;
};
//! Specialization for case when \c T is smaller than \c U
template< typename T, typename U, unsigned int TSizeV, unsigned int USizeV >
struct make_common_integral_type< T, U, TSizeV, USizeV, true >
{
typedef U type;
};
//! Specialization for the case when both types have the same size
template< typename T, typename U, unsigned int SizeV >
struct make_common_integral_type< T, U, SizeV, SizeV, false > :
public mpl::if_<
is_unsigned< T >,
T,
U
>
{
};
} // namespace aux
//! Equality predicate
struct equal_to
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::false_ const&)
{
return (left == right);
}
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return static_cast< common_integral_type >(left) == static_cast< common_integral_type >(right);
}
};
//! Inequality predicate
struct not_equal_to
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::false_ const&)
{
return (left != right);
}
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return static_cast< common_integral_type >(left) != static_cast< common_integral_type >(right);
}
};
//! Less predicate
struct less
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::false_ const&)
{
return (left < right);
}
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return static_cast< common_integral_type >(left) < static_cast< common_integral_type >(right);
}
};
//! Greater predicate
struct greater
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::false_ const&)
{
return (left > right);
}
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return static_cast< common_integral_type >(left) > static_cast< common_integral_type >(right);
}
};
//! Less or equal predicate
struct less_equal
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::false_ const&)
{
return (left <= right);
}
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return static_cast< common_integral_type >(left) <= static_cast< common_integral_type >(right);
}
};
//! Greater or equal predicate
struct greater_equal
{
typedef bool result_type;
template< typename T, typename U >
bool operator() (T const& left, U const& right) const
{
return op(left, right, typename mpl::and_< is_integral< T >, is_integral< U > >::type());
}
private:
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::false_ const&)
{
return (left >= right);
}
template< typename T, typename U >
static bool op(T const& left, U const& right, mpl::true_ const&)
{
typedef typename aux::make_common_integral_type< T, U >::type common_integral_type;
return static_cast< common_integral_type >(left) >= static_cast< common_integral_type >(right);
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_LOGICAL_HPP_INCLUDED_
@@ -0,0 +1,66 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file matches.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a predicate for checking if the provided string matches a regular expression.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits
template< typename ExpressionT, typename = void >
struct matching_expression_kind;
//! The matching function implementation
template< typename ExpressionT, typename TagT = typename matching_expression_kind< ExpressionT >::type >
struct match_traits;
} // namespace aux
//! The regex matching functor
struct matches_fun
{
typedef bool result_type;
template< typename StringT, typename ExpressionT >
bool operator() (StringT const& str, ExpressionT const& expr) const
{
typedef aux::match_traits< ExpressionT > impl;
return impl::matches(str, expr);
}
template< typename StringT, typename ExpressionT, typename ArgT >
bool operator() (StringT const& str, ExpressionT const& expr, ArgT const& arg) const
{
typedef aux::match_traits< ExpressionT > impl;
return impl::matches(str, expr, arg);
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_MATCHES_HPP_INCLUDED_
@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file nop.hpp
* \author Andrey Semashev
* \date 30.03.2008
*
* This header contains a function object that does nothing.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The function object that does nothing
struct nop
{
typedef void result_type;
void operator() () const BOOST_NOEXCEPT {}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template< typename... ArgsT >
void operator() (ArgsT const&...) const BOOST_NOEXCEPT {}
#else
template< typename T >
void operator() (T const&) const BOOST_NOEXCEPT {}
template< typename T1, typename T2 >
void operator() (T1 const&, T2 const&) const BOOST_NOEXCEPT {}
template< typename T1, typename T2, typename T3 >
void operator() (T1 const&, T2 const&, T3 const&) const BOOST_NOEXCEPT {}
#endif
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_NOP_HPP_INCLUDED_
@@ -0,0 +1,60 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file save_result.hpp
* \author Andrey Semashev
* \date 19.01.2013
*
* This header contains function object adapter that saves the result of the adopted function to an external variable.
*/
#ifndef BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! Function object wrapper for saving the adopted function object result
template< typename FunT, typename AssigneeT >
struct save_result_wrapper
{
typedef void result_type;
save_result_wrapper(FunT fun, AssigneeT& assignee) : m_fun(fun), m_assignee(assignee) {}
template< typename ArgT >
result_type operator() (ArgT const& arg) const
{
m_assignee = m_fun(arg);
}
private:
FunT m_fun;
AssigneeT& m_assignee;
};
template< typename FunT, typename AssigneeT >
BOOST_FORCEINLINE save_result_wrapper< FunT, AssigneeT > save_result(FunT const& fun, AssigneeT& assignee)
{
return save_result_wrapper< FunT, AssigneeT >(fun, assignee);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_FUNCTIONAL_SAVE_RESULT_HPP_INCLUDED_
@@ -0,0 +1,271 @@
/*
* Copyright Andrey Semashev 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file utility/ipc/object_name.hpp
* \author Andrey Semashev
* \date 05.03.2016
*
* The header contains declaration of a system object name wrapper.
*/
#ifndef BOOST_LOG_UTILITY_IPC_OBJECT_NAME_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_IPC_OBJECT_NAME_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <cstddef>
#include <iosfwd>
#include <string>
#include <boost/move/core.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace ipc {
/*!
* \brief A system object name class
*
* In order to identify a system-wide object such as a shared memory segment or a named synchronization primitive the object has to be given a name.
* The format of the name is specific to the operating system and the \c object_name class provides an abstraction for names of objects. It also
* provides means for scoping, which allows to avoid name clashes between different processes.
*
* The object name is a UTF-8 encoded string. The portable object name should consist of the following characters:
*
* <pre>
* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
* a b c d e f g h i j k l m n o p q r s t u v w x y z
* 0 1 2 3 4 5 6 7 8 9 . _ -
* </pre>
*
* \note The character set corresponds to the POSIX Portable Filename Character Set (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278).
*
* Use of other characters may result in non-portable system-specific behavior.
*
* The name can have one of the following scopes:
*
* \li \c global - objects within this scope are visible to any process on the system. In order to use this scope the process may need to have
* extended privileges. This scope is not available for Windows Store applications.
* \li \c user - objects within this scope can be opened by processes running under the same user as the current process.
* \li \c session - objects within this scope are visible to processes within the session of the current process. The definition of a session may vary between
* operating systems. On POSIX, a session is typically a group of processes attached to a single virtual terminal device. On Windows a session is
* started when a user logs into the system. There is also a separate session for Windows services.
* \li \c process_group - objects within this scope are visible to processes within the process group of the current process. Currently, on Windows all processes
* running in the current session are considered members of the same process group. This may change in future.
*
* The scopes are not overlapping. For instance, if an object is created in the global scope, the object cannot be opened with the same name but in user's scope.
*
* Note that name scoping is not a security feature. On some systems any process on the system has technical capability to open objects within any scope.
* The scope is only used to help avoid name clashes between processes using \c object_name to identify objects.
*/
class object_name
{
public:
//! Name scopes
enum scope
{
global, //!< The name has global scope; any process in the system has the potential to open the resource identified by the name
user, //!< The name is limited to processes running under the current user
session, //!< The name is limited to processes running in the current login session
process_group //!< The name is limited to processes running in the current process group
};
#if !defined(BOOST_LOG_DOXYGEN_PASS)
BOOST_COPYABLE_AND_MOVABLE(object_name)
private:
std::string m_name;
#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
public:
/*!
* Default constructor. The method creates an empty object name.
*
* \post <tt>empty() == true</tt>
*/
object_name() BOOST_NOEXCEPT
{
}
/*!
* Move constructor.
*/
object_name(BOOST_RV_REF(object_name) that) BOOST_NOEXCEPT
{
m_name.swap(that.m_name);
}
/*!
* Copy constructor.
*/
object_name(object_name const& that) : m_name(that.m_name)
{
}
/*!
* Constructor from the native string.
*
* \param str The object name string, must not be \c NULL. The string format is specific to the operating system.
*/
static object_name from_native(const char* str)
{
object_name name;
name.m_name = str;
return name;
}
/*!
* Constructor from the native string.
*
* \param str The object name string. The string format is specific to the operating system.
*/
static object_name from_native(std::string const& str)
{
object_name name;
name.m_name = str;
return name;
}
/*!
* Constructor from the object name
* \param ns The scope of the object name
* \param str The object name, must not be NULL.
*/
BOOST_LOG_API object_name(scope ns, const char* str);
/*!
* Constructor from the object name
* \param ns The scope of the object name
* \param str The object name
*/
BOOST_LOG_API object_name(scope ns, std::string const& str);
/*!
* Move assignment
*/
object_name& operator= (BOOST_RV_REF(object_name) that) BOOST_NOEXCEPT
{
m_name.clear();
m_name.swap(that.m_name);
return *this;
}
/*!
* Copy assignment
*/
object_name& operator= (BOOST_COPY_ASSIGN_REF(object_name) that)
{
m_name = that.m_name;
return *this;
}
/*!
* Returns \c true if the object name is empty
*/
bool empty() const BOOST_NOEXCEPT { return m_name.empty(); }
/*!
* Returns length of the name, in bytes
*/
std::size_t size() const BOOST_NOEXCEPT { return m_name.size(); }
/*!
* Returns the name string
*/
const char* c_str() const BOOST_NOEXCEPT { return m_name.c_str(); }
/*!
* Swaps the object name with another object name
*/
void swap(object_name& that) BOOST_NOEXCEPT { m_name.swap(that.m_name); }
/*!
* Swaps two object names
*/
friend void swap(object_name& left, object_name& right) BOOST_NOEXCEPT
{
left.swap(right);
}
/*!
* Returns string representation of the object name
*/
friend std::string to_string(object_name const& name)
{
return name.m_name;
}
/*!
* Equality operator
*/
friend bool operator== (object_name const& left, object_name const& right) BOOST_NOEXCEPT
{
return left.m_name == right.m_name;
}
/*!
* Inequality operator
*/
friend bool operator!= (object_name const& left, object_name const& right) BOOST_NOEXCEPT
{
return left.m_name != right.m_name;
}
/*!
* Less operator
*/
friend bool operator< (object_name const& left, object_name const& right) BOOST_NOEXCEPT
{
return left.m_name < right.m_name;
}
/*!
* Greater operator
*/
friend bool operator> (object_name const& left, object_name const& right) BOOST_NOEXCEPT
{
return left.m_name > right.m_name;
}
/*!
* Less or equal operator
*/
friend bool operator<= (object_name const& left, object_name const& right) BOOST_NOEXCEPT
{
return left.m_name <= right.m_name;
}
/*!
* Greater or equal operator
*/
friend bool operator>= (object_name const& left, object_name const& right) BOOST_NOEXCEPT
{
return left.m_name >= right.m_name;
}
/*!
* Stream ouput operator
*/
template< typename CharT, typename TraitsT >
friend std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, object_name const& name)
{
strm << name.c_str();
return strm;
}
};
} // namespace ipc
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_IPC_OBJECT_NAME_HPP_INCLUDED_
@@ -0,0 +1,776 @@
/*
* Copyright Lingxi Li 2015.
* Copyright Andrey Semashev 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file utility/ipc/reliable_message_queue.hpp
* \author Lingxi Li
* \author Andrey Semashev
* \date 01.01.2016
*
* The header contains declaration of a reliable interprocess message queue.
*/
#ifndef BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/move/core.hpp>
#include <boost/log/keywords/open_mode.hpp>
#include <boost/log/keywords/name.hpp>
#include <boost/log/keywords/capacity.hpp>
#include <boost/log/keywords/block_size.hpp>
#include <boost/log/keywords/overflow_policy.hpp>
#include <boost/log/keywords/permissions.hpp>
#include <boost/log/utility/open_mode.hpp>
#include <boost/log/utility/permissions.hpp>
#include <boost/log/utility/ipc/object_name.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace ipc {
namespace aux {
template< typename T, typename R >
struct enable_if_byte {};
template< typename R >
struct enable_if_byte< char, R > { typedef R type; };
template< typename R >
struct enable_if_byte< signed char, R > { typedef R type; };
template< typename R >
struct enable_if_byte< unsigned char, R > { typedef R type; };
} // namespace aux
/*!
* \brief A reliable interprocess message queue
*
* The queue implements a reliable one-way channel of passing messages from one or multiple writers to a single reader.
* The format of the messages is user-defined and must be consistent across all writers and the reader. The queue does
* not enforce any specific format of the messages, other than they should be supplied as a contiguous array of bytes.
*
* The queue internally uses a process-shared storage identified by an \c object_name (the queue name). Refer to \c object_name
* documentation for details on restrictions imposed on object names.
*
* The queue storage is organized as a fixed number of blocks of a fixed size. The block size must be an integer power of 2 and
* is expressed in bytes. Each written message, together with some metadata added by the queue, consumes an integer number
* of blocks. Each read message received by the reader releases the blocks allocated for that message. As such the maximum size
* of a message is slightly less than block size times capacity of the queue. For efficiency, it is recommended to choose
* block size large enough to accommodate most of the messages to be passed through the queue.
*
* The queue is considered empty when no messages are enqueued (all blocks are free). The queue is considered full at the point
* of enqueueing a message when there is not enough free blocks to accommodate the message.
*
* The queue is reliable in that it will not drop successfully sent messages that are not received by the reader, other than the
* case when a non-empty queue is destroyed by the last user. If a message cannot be enqueued by the writer because the queue is
* full, the queue can either block the writer or return an error or throw an exception, depending on the policy specified at
* the queue creation. The policy is object local, i.e. different writers and the reader can have different overflow policies.
*
* If the queue is empty and the reader attempts to dequeue a message, it will block until a message is enqueued by a writer.
*
* A blocked reader or writer can be unblocked by calling \c stop_local. After this method is called, all threads blocked on
* this particular object are released and return \c operation_result::aborted. The other instances of the queue (in the current
* or other processes) are unaffected. In order to restore the normal functioning of the queue instance after the \c stop_local
* call the user has to invoke \c reset_local.
*
* The queue does not guarantee any particular order of received messages from different writer threads. Messages sent by a
* particular writer thread will be received in the order of sending.
*
* Methods of this class are not thread-safe, unless otherwise specified.
*/
class reliable_message_queue
{
public:
//! Result codes for various operations on the queue
enum operation_result
{
succeeded, //!< The operation has completed successfully
no_space, //!< The message could not be sent because the queue is full
aborted //!< The operation has been aborted because the queue method <tt>stop_local()</tt> has been called
};
//! Interprocess queue overflow policies
enum overflow_policy
{
//! Block the send operation when the queue is full
block_on_overflow,
//! Return \c operation_result::no_space when the queue is full
fail_on_overflow,
//! Throw \c capacity_limit_reached exception when the queue is full
throw_on_overflow
};
//! Queue message size type
typedef uint32_t size_type;
#if !defined(BOOST_LOG_DOXYGEN_PASS)
BOOST_MOVABLE_BUT_NOT_COPYABLE(reliable_message_queue)
private:
typedef void (*receive_handler)(void* state, const void* data, size_type size);
struct fixed_buffer_state
{
uint8_t* data;
size_type size;
};
struct implementation;
implementation* m_impl;
#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
public:
/*!
* Default constructor. The method constructs an object that is not associated with any
* message queue.
*
* \post <tt>is_open() == false</tt>
*/
BOOST_CONSTEXPR reliable_message_queue() BOOST_NOEXCEPT : m_impl(NULL)
{
}
/*!
* Constructor. The method is used to construct an object and create the associated
* message queue. The constructed object will be in running state if the message queue is
* successfully created.
*
* \post <tt>is_open() == true</tt>
*
* \param name Name of the message queue to be associated with.
* \param capacity Maximum number of allocation blocks the queue can hold.
* \param block_size Size in bytes of allocation block. Must be a power of 2.
* \param oflow_policy Queue behavior policy in case of overflow.
* \param perms Access permissions for the associated message queue.
*/
reliable_message_queue
(
open_mode::create_only_tag,
object_name const& name,
uint32_t capacity,
size_type block_size,
overflow_policy oflow_policy = block_on_overflow,
permissions const& perms = permissions()
) :
m_impl(NULL)
{
this->create(name, capacity, block_size, oflow_policy, perms);
}
/*!
* Constructor. The method is used to construct an object and create or open the associated
* message queue. The constructed object will be in running state if the message queue is
* successfully created or opened. If the message queue that is identified by the name already
* exists then the other queue parameters are ignored. The actual queue parameters can be obtained
* with accessors from the constructed object.
*
* \post <tt>is_open() == true</tt>
*
* \param name Name of the message queue to be associated with.
* \param capacity Maximum number of allocation blocks the queue can hold.
* \param block_size Size in bytes of allocation block. Must be a power of 2.
* \param oflow_policy Queue behavior policy in case of overflow.
* \param perms Access permissions for the associated message queue.
*/
reliable_message_queue
(
open_mode::open_or_create_tag,
object_name const& name,
uint32_t capacity,
size_type block_size,
overflow_policy oflow_policy = block_on_overflow,
permissions const& perms = permissions()
) :
m_impl(NULL)
{
this->open_or_create(name, capacity, block_size, oflow_policy, perms);
}
/*!
* Constructor. The method is used to construct an object and open the existing
* message queue. The constructed object will be in running state if the message queue is
* successfully opened.
*
* \post <tt>is_open() == true</tt>
*
* \param name Name of the message queue to be associated with.
* \param oflow_policy Queue behavior policy in case of overflow.
* \param perms Access permissions for the associated message queue. The permissions will only be used
* if the queue implementation has to create system objects while operating.
* This parameter is currently not used on POSIX systems.
*/
reliable_message_queue
(
open_mode::open_only_tag,
object_name const& name,
overflow_policy oflow_policy = block_on_overflow,
permissions const& perms = permissions()
) :
m_impl(NULL)
{
this->open(name, oflow_policy, perms);
}
/*!
* Constructor with named parameters. The method is used to construct an object and create or open
* the associated message queue. The constructed object will be in running state if the message queue is
* successfully created.
*
* The following named parameters are accepted:
*
* * open_mode - One of the open mode tags: \c open_mode::create_only, \c open_mode::open_only or
* \c open_mode::open_or_create.
* * name - Name of the message queue to be associated with.
* * capacity - Maximum number of allocation blocks the queue can hold. Used only if the queue is created.
* * block_size - Size in bytes of allocation block. Must be a power of 2. Used only if the queue is created.
* * overflow_policy - Queue behavior policy in case of overflow, see \c overflow_policy.
* * permissions - Access permissions for the associated message queue.
*
* \post <tt>is_open() == true</tt>
*/
#if !defined(BOOST_LOG_DOXYGEN_PASS)
BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(reliable_message_queue, construct)
#else
template< typename... Args >
explicit reliable_message_queue(Args const&... args);
#endif
/*!
* Destructor. Calls <tt>close()</tt>.
*/
~reliable_message_queue() BOOST_NOEXCEPT
{
this->close();
}
/*!
* Move constructor. The method move-constructs an object from \c other. After
* the call, the constructed object becomes \c other, while \c other is left in
* default constructed state.
*
* \param that The object to be moved.
*/
reliable_message_queue(BOOST_RV_REF(reliable_message_queue) that) BOOST_NOEXCEPT :
m_impl(that.m_impl)
{
that.m_impl = NULL;
}
/*!
* Move assignment operator. If the object is associated with a message queue,
* <tt>close()</tt> is first called and the precondition to calling <tt>close()</tt>
* applies. After the call, the object becomes \a that while \a that is left
* in default constructed state.
*
* \param that The object to be moved.
*
* \return A reference to the assigned object.
*/
reliable_message_queue& operator= (BOOST_RV_REF(reliable_message_queue) that) BOOST_NOEXCEPT
{
reliable_message_queue other(static_cast< BOOST_RV_REF(reliable_message_queue) >(that));
this->swap(other);
return *this;
}
/*!
* The method swaps the object with \a that.
*
* \param that The other object to swap with.
*/
void swap(reliable_message_queue& that) BOOST_NOEXCEPT
{
implementation* p = m_impl;
m_impl = that.m_impl;
that.m_impl = p;
}
//! Swaps the two \c reliable_message_queue objects.
friend void swap(reliable_message_queue& a, reliable_message_queue& b) BOOST_NOEXCEPT
{
a.swap(b);
}
/*!
* The method creates the message queue to be associated with the object. After the call,
* the object will be in running state if a message queue is successfully created.
*
* \pre <tt>is_open() == false</tt>
* \post <tt>is_open() == true</tt>
*
* \param name Name of the message queue to be associated with.
* \param capacity Maximum number of allocation blocks the queue can hold.
* \param block_size Size in bytes of allocation block. Must be a power of 2.
* \param oflow_policy Queue behavior policy in case of overflow.
* \param perms Access permissions for the associated message queue.
*/
BOOST_LOG_API void create
(
object_name const& name,
uint32_t capacity,
size_type block_size,
overflow_policy oflow_policy = block_on_overflow,
permissions const& perms = permissions()
);
/*!
* The method creates or opens the message queue to be associated with the object.
* After the call, the object will be in running state if a message queue is successfully
* created or opened. If the message queue that is identified by the name already exists then
* the other queue parameters are ignored. The actual queue parameters can be obtained
* with accessors from this object after this method returns.
*
* \pre <tt>is_open() == false</tt>
* \post <tt>is_open() == true</tt>
*
* \param name Name of the message queue to be associated with.
* \param capacity Maximum number of allocation blocks the queue can hold.
* \param block_size Size in bytes of allocation block. Must be a power of 2.
* \param oflow_policy Queue behavior policy in case of overflow.
* \param perms Access permissions for the associated message queue.
*/
BOOST_LOG_API void open_or_create
(
object_name const& name,
uint32_t capacity,
size_type block_size,
overflow_policy oflow_policy = block_on_overflow,
permissions const& perms = permissions()
);
/*!
* The method opens the existing message queue to be associated with the object.
* After the call, the object will be in running state if a message queue is successfully
* opened.
*
* \pre <tt>is_open() == false</tt>
* \post <tt>is_open() == true</tt>
*
* \param name Name of the message queue to be associated with.
* \param oflow_policy Queue behavior policy in case of overflow.
* \param perms Access permissions for the associated message queue. The permissions will only be used
* if the queue implementation has to create system objects while operating.
* This parameter is currently not used on POSIX systems.
*/
BOOST_LOG_API void open
(
object_name const& name,
overflow_policy oflow_policy = block_on_overflow,
permissions const& perms = permissions()
);
/*!
* Tests whether the object is associated with any message queue.
*
* \return \c true if the object is associated with a message queue, and \c false otherwise.
*/
bool is_open() const BOOST_NOEXCEPT
{
return m_impl != NULL;
}
/*!
* This method empties the associated message queue. Concurrent calls to this method, <tt>send()</tt>,
* <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, and <tt>stop_local()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*/
BOOST_LOG_API void clear();
/*!
* The method returns the name of the associated message queue.
*
* \pre <tt>is_open() == true</tt>
*
* \return Name of the associated message queue
*/
BOOST_LOG_API object_name const& name() const;
/*!
* The method returns the maximum number of allocation blocks the associated message queue
* can hold. Note that the returned value may be different from the corresponding
* value passed to the constructor or <tt>open_or_create()</tt>, for the message queue may
* not have been created by this object.
*
* \pre <tt>is_open() == true</tt>
*
* \return Maximum number of allocation blocks the associated message queue can hold.
*/
BOOST_LOG_API uint32_t capacity() const;
/*!
* The method returns the allocation block size, in bytes. Each message in the
* associated message queue consumes an integer number of allocation blocks.
* Note that the returned value may be different from the corresponding value passed
* to the constructor or <tt>open_or_create()</tt>, for the message queue may not
* have been created by this object.
*
* \pre <tt>is_open() == true</tt>
*
* \return Allocation block size, in bytes.
*/
BOOST_LOG_API size_type block_size() const;
/*!
* The method wakes up all threads that are blocked in calls to <tt>send()</tt> or
* <tt>receive()</tt>. Those calls would then return \c false with \c errno \c EINTR.
* Note that, the method does not block until the woken-up threads have actually
* returned from <tt>send()</tt> or <tt>receive()</tt>. Other means is needed to ensure
* that calls to <tt>send()</tt> or <tt>receive()</tt> have returned, e.g., joining the
* threads that might be blocking on the calls.
*
* The method also puts the object in stopped state. When in stopped state, calls to
* <tt>send()</tt> or <tt>receive()</tt> will return immediately with return value
* \c false and \c errno \c EINTR when they would otherwise block in running state.
*
* Concurrent calls to this method, <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*/
BOOST_LOG_API void stop_local();
/*!
* The method puts the object in running state where calls to <tt>send()</tt> or
* <tt>receive()</tt> may block. This method is not thread-safe.
*
* \pre <tt>is_open() == true</tt>
*/
BOOST_LOG_API void reset_local();
/*!
* The method disassociates the associated message queue, if any. No other threads
* should be using this object before calling this method. The <tt>stop_local()</tt> method
* can be used to have any threads currently blocked in <tt>send()</tt> or
* <tt>receive()</tt> return, and prevent further calls to them from blocking. Typically,
* before calling this method, one would first call <tt>stop_local()</tt> and then join all
* threads that might be blocking on <tt>send()</tt> or <tt>receive()</tt> to ensure that
* they have returned from the calls. The associated message queue is destroyed if the
* object represents the last outstanding reference to it.
*
* \post <tt>is_open() == false</tt>
*/
void close() BOOST_NOEXCEPT
{
if (is_open())
do_close();
}
/*!
* The method sends a message to the associated message queue. When the object is in
* running state and the queue has no free space for the message, the method either blocks
* or throws an exception, depending on the overflow policy that was specified on the queue
* opening/creation. If blocking policy is in effect, the blocking can be interrupted by
* calling <tt>stop_local()</tt>, in which case the method returns \c operation_result::aborted.
* When the object is already in the stopped state, the method does not block but returns
* immediately with return value \c operation_result::aborted.
*
* It is possible to send an empty message by passing \c 0 to the parameter \c message_size.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>,
* <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param message_data The message data to send. Ignored when \c message_size is \c 0.
* \param message_size Size of the message data in bytes. If the size is larger than
* the associated message queue capacity, an <tt>std::logic_error</tt> exception is thrown.
*
* \retval operation_result::succeeded if the operation is successful
* \retval operation_result::no_space if \c overflow_policy::fail_on_overflow is in effect and the queue is full
* \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
*
* <b>Throws:</b> <tt>std::logic_error</tt> in case if the message size exceeds the queue
* capacity, <tt>system_error</tt> in case if a native OS method fails.
*/
BOOST_LOG_API operation_result send(void const* message_data, size_type message_size);
/*!
* The method performs an attempt to send a message to the associated message queue.
* The method is non-blocking, and always returns immediately.
* <tt>boost::system::system_error</tt> is thrown for errors resulting from native
* operating system calls. Note that it is possible to send an empty message by passing
* \c 0 to the parameter \c message_size. Concurrent calls to <tt>send()</tt>,
* <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, <tt>stop_local()</tt>,
* and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param message_data The message data to send. Ignored when \c message_size is \c 0.
* \param message_size Size of the message data in bytes. If the size is larger than the
* maximum size allowed by the associated message queue, an
* <tt>std::logic_error</tt> exception is thrown.
*
* \return \c true if the message is successfully sent, and \c false otherwise (e.g.,
* when the queue is full).
*
* <b>Throws:</b> <tt>std::logic_error</tt> in case if the message size exceeds the queue
* capacity, <tt>system_error</tt> in case if a native OS method fails.
*/
BOOST_LOG_API bool try_send(void const* message_data, size_type message_size);
/*!
* The method takes a message from the associated message queue. When the object is in
* running state and the queue is empty, the method blocks. The blocking is interrupted
* when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted.
* When the object is already in the stopped state and the queue is empty, the method
* does not block but returns immediately with return value \c operation_result::aborted.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param buffer The memory buffer to store the received message in.
* \param buffer_size The size of the buffer, in bytes.
* \param message_size Receives the size of the received message, in bytes.
*
* \retval operation_result::succeeded if the operation is successful
* \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
*/
operation_result receive(void* buffer, size_type buffer_size, size_type& message_size)
{
fixed_buffer_state state = { static_cast< uint8_t* >(buffer), buffer_size };
operation_result result = do_receive(&reliable_message_queue::fixed_buffer_receive_handler, &state);
message_size = buffer_size - state.size;
return result;
}
/*!
* The method takes a message from the associated message queue. When the object is in
* running state and the queue is empty, the method blocks. The blocking is interrupted
* when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted.
* When the object is already in the stopped state and the queue is empty, the method
* does not block but returns immediately with return value \c operation_result::aborted.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param buffer The memory buffer to store the received message in.
* \param message_size Receives the size of the received message, in bytes.
*
* \retval operation_result::succeeded if the operation is successful
* \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
*/
template< typename ElementT, size_type SizeV >
#if !defined(BOOST_LOG_DOXYGEN_PASS)
typename aux::enable_if_byte< ElementT, operation_result >::type
#else
operation_result
#endif
receive(ElementT (&buffer)[SizeV], size_type& message_size)
{
return receive(buffer, SizeV, message_size);
}
/*!
* The method takes a message from the associated message queue. When the object is in
* running state and the queue is empty, the method blocks. The blocking is interrupted
* when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted.
* When the object is already in the stopped state and the queue is empty, the method
* does not block but returns immediately with return value \c operation_result::aborted.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param container The container to store the received message in. The container should have
* value type of <tt>char</tt>, <tt>signed char</tt> or <tt>unsigned char</tt>
* and support inserting elements at the end.
*
* \retval operation_result::succeeded if the operation is successful
* \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt>
*/
template< typename ContainerT >
#if !defined(BOOST_LOG_DOXYGEN_PASS)
typename aux::enable_if_byte< typename ContainerT::value_type, operation_result >::type
#else
operation_result
#endif
receive(ContainerT& container)
{
return do_receive(&reliable_message_queue::container_receive_handler< ContainerT >, &container);
}
/*!
* The method performs an attempt to take a message from the associated message queue. The
* method is non-blocking, and always returns immediately.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param buffer The memory buffer to store the received message in.
* \param buffer_size The size of the buffer, in bytes.
* \param message_size Receives the size of the received message, in bytes.
*
* \return \c true if a message is successfully received, and \c false otherwise (e.g.,
* when the queue is empty).
*/
bool try_receive(void* buffer, size_type buffer_size, size_type& message_size)
{
fixed_buffer_state state = { static_cast< uint8_t* >(buffer), buffer_size };
bool result = do_try_receive(&reliable_message_queue::fixed_buffer_receive_handler, &state);
message_size = buffer_size - state.size;
return result;
}
/*!
* The method performs an attempt to take a message from the associated message queue. The
* method is non-blocking, and always returns immediately.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param buffer The memory buffer to store the received message in.
* \param message_size Receives the size of the received message, in bytes.
*
* \return \c true if a message is successfully received, and \c false otherwise (e.g.,
* when the queue is empty).
*/
template< typename ElementT, size_type SizeV >
#if !defined(BOOST_LOG_DOXYGEN_PASS)
typename aux::enable_if_byte< ElementT, bool >::type
#else
bool
#endif
try_receive(ElementT (&buffer)[SizeV], size_type& message_size)
{
return try_receive(buffer, SizeV, message_size);
}
/*!
* The method performs an attempt to take a message from the associated message queue. The
* method is non-blocking, and always returns immediately.
*
* Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>,
* <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed.
*
* \pre <tt>is_open() == true</tt>
*
* \param container The container to store the received message in. The container should have
* value type of <tt>char</tt>, <tt>signed char</tt> or <tt>unsigned char</tt>
* and support inserting elements at the end.
*
* \return \c true if a message is successfully received, and \c false otherwise (e.g.,
* when the queue is empty).
*/
template< typename ContainerT >
#if !defined(BOOST_LOG_DOXYGEN_PASS)
typename aux::enable_if_byte< typename ContainerT::value_type, bool >::type
#else
bool
#endif
try_receive(ContainerT& container)
{
return do_try_receive(&reliable_message_queue::container_receive_handler< ContainerT >, &container);
}
/*!
* The method frees system-wide resources, associated with the interprocess queue with the supplied name.
* The queue referred to by the specified name must not be opened in any process at the point of this call.
* After this call succeeds a new queue with the specified name can be created.
*
* This call can be useful to recover from an earlier process misbehavior (e.g. a crash without properly
* closing the message queue). In this case resources allocated for the interprocess queue may remain
* allocated after the last process closed the queue, which in turn may prevent creating a new queue with
* the same name. By calling this method before creating a queue the application can attempt to ensure
* it starts with a clean slate.
*
* On some platforms resources associated with the queue are automatically reclaimed by the operating system
* when the last process using those resources terminates (even if it terminates abnormally). On these
* platforms this call may be a no-op. However, portable code should still call this method at appropriate
* places to ensure compatibility with other platforms and future library versions, which may change implementation
* of the queue.
*
* \param name Name of the message queue to be removed.
*/
static BOOST_LOG_API void remove(object_name const& name);
#if !defined(BOOST_LOG_DOXYGEN_PASS)
private:
//! Implementation of the constructor with named arguments
template< typename ArgsT >
void construct(ArgsT const& args)
{
m_impl = NULL;
construct_dispatch(args[keywords::open_mode], args);
}
//! Implementation of the constructor with named arguments
template< typename ArgsT >
void construct_dispatch(open_mode::create_only_tag, ArgsT const& args)
{
this->create(args[keywords::name], args[keywords::capacity], args[keywords::block_size], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]);
}
//! Implementation of the constructor with named arguments
template< typename ArgsT >
void construct_dispatch(open_mode::open_or_create_tag, ArgsT const& args)
{
this->open_or_create(args[keywords::name], args[keywords::capacity], args[keywords::block_size], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]);
}
//! Implementation of the constructor with named arguments
template< typename ArgsT >
void construct_dispatch(open_mode::open_only_tag, ArgsT const& args)
{
this->open(args[keywords::name], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]);
}
//! Closes the message queue, if it's open
BOOST_LOG_API void do_close() BOOST_NOEXCEPT;
//! Receives the message from the queue and calls the handler to place the data in the user's storage
BOOST_LOG_API operation_result do_receive(receive_handler handler, void* state);
//! Attempts to receives the message from the queue and calls the handler to place the data in the user's storage
BOOST_LOG_API bool do_try_receive(receive_handler handler, void* state);
//! Fixed buffer receive handler
static BOOST_LOG_API void fixed_buffer_receive_handler(void* state, const void* data, size_type size);
//! Receive handler for a container
template< typename ContainerT >
static void container_receive_handler(void* state, const void* data, size_type size)
{
ContainerT* const container = static_cast< ContainerT* >(state);
container->insert
(
container->end(),
static_cast< typename ContainerT::value_type const* >(data),
static_cast< typename ContainerT::value_type const* >(data) + size
);
}
#endif
};
} // namespace ipc
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
@@ -0,0 +1,28 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file manipulators.hpp
* \author Andrey Semashev
* \date 06.11.2012
*
* This header includes all manipulators.
*/
#ifndef BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/manipulators/to_log.hpp>
#include <boost/log/utility/manipulators/dump.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_LOG_UTILITY_MANIPULATORS_HPP_INCLUDED_
@@ -0,0 +1,165 @@
/*
* 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 add_value.hpp
* \author Andrey Semashev
* \date 26.11.2012
*
* This header contains the \c add_value manipulator.
*/
#ifndef BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/embedded_string_type.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/attributes/attribute_value_impl.hpp>
#include <boost/log/expressions/keyword_fwd.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifdef _MSC_VER
#pragma warning(push)
// 'boost::log::v2s_mt_nt6::add_value_manip<RefT>::m_value' : reference member is initialized to a temporary that doesn't persist after the constructor exits
// This is intentional since the manipulator can be used with a temporary, which will be used before the streaming expression ends and it is destroyed.
#pragma warning(disable: 4413)
// returning address of local variable or temporary
// This warning refers to add_value_manip<RefT>::get_value() when RefT is an rvalue reference. We store the reference in the manipulator and we intend to return it as is.
#pragma warning(disable: 4172)
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! Attribute value manipulator
template< typename RefT >
class add_value_manip
{
public:
//! Stored reference type
typedef RefT reference_type;
//! Attribute value type
typedef typename remove_cv< typename remove_reference< reference_type >::type >::type value_type;
private:
// The stored reference type is an lvalue reference since apparently different compilers (GCC and MSVC) have different quirks when rvalue references are stored as members.
// Additionally, MSVC (at least 11.0) has a bug which causes a dangling reference to be stored in the manipulator, if a scalar rvalue is passed to the add_value generator.
// To work around this problem we save the value inside the manipulator in this case.
typedef typename remove_reference< reference_type >::type& lvalue_reference_type;
typedef typename mpl::if_<
is_scalar< value_type >,
value_type,
lvalue_reference_type
>::type stored_type;
typedef typename mpl::if_<
is_scalar< value_type >,
value_type,
reference_type
>::type get_value_result_type;
private:
//! Attribute value
stored_type m_value;
//! Attribute name
attribute_name m_name;
public:
//! Initializing constructor
add_value_manip(attribute_name const& name, reference_type value) : m_value(static_cast< lvalue_reference_type >(value)), m_name(name)
{
}
//! Returns attribute name
attribute_name get_name() const { return m_name; }
//! Returns attribute value
get_value_result_type get_value() const { return static_cast< get_value_result_type >(m_value); }
};
//! The operator attaches an attribute value to the log record
template< typename CharT, typename RefT >
inline basic_record_ostream< CharT >& operator<< (basic_record_ostream< CharT >& strm, add_value_manip< RefT > const& manip)
{
typedef typename aux::make_embedded_string_type< typename add_value_manip< RefT >::value_type >::type value_type;
attribute_value value(new attributes::attribute_value_impl< value_type >(manip.get_value()));
strm.get_record().attribute_values().insert(manip.get_name(), value);
return strm;
}
//! The function creates a manipulator that attaches an attribute value to a log record
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template< typename T >
inline add_value_manip< T&& > add_value(attribute_name const& name, T&& value)
{
return add_value_manip< T&& >(name, static_cast< T&& >(value));
}
//! \overload
template< typename DescriptorT, template< typename > class ActorT >
inline add_value_manip< typename DescriptorT::value_type&& >
add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type&& value)
{
typedef typename DescriptorT::value_type value_type;
return add_value_manip< value_type&& >(DescriptorT::get_name(), static_cast< value_type&& >(value));
}
//! \overload
template< typename DescriptorT, template< typename > class ActorT >
inline add_value_manip< typename DescriptorT::value_type& >
add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type& value)
{
return add_value_manip< typename DescriptorT::value_type& >(DescriptorT::get_name(), value);
}
//! \overload
template< typename DescriptorT, template< typename > class ActorT >
inline add_value_manip< typename DescriptorT::value_type const& >
add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value)
{
return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value);
}
#else // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template< typename T >
inline add_value_manip< T const& > add_value(attribute_name const& name, T const& value)
{
return add_value_manip< T const& >(name, value);
}
template< typename DescriptorT, template< typename > class ActorT >
inline add_value_manip< typename DescriptorT::value_type const& >
add_value(expressions::attribute_keyword< DescriptorT, ActorT > const&, typename DescriptorT::value_type const& value)
{
return add_value_manip< typename DescriptorT::value_type const& >(DescriptorT::get_name(), value);
}
#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_MANIPULATORS_ADD_VALUE_HPP_INCLUDED_
@@ -0,0 +1,231 @@
/*
* 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 dump.hpp
* \author Andrey Semashev
* \date 03.05.2013
*
* This header contains the \c dump output manipulator.
*/
#ifndef BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_
#include <cstddef>
#include <iosfwd>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
typedef void dump_data_char_t(const void* data, std::size_t size, std::basic_ostream< char >& strm);
extern BOOST_LOG_API dump_data_char_t* dump_data_char;
BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char >& strm)
{
(dump_data_char)(data, size, strm);
}
typedef void dump_data_wchar_t(const void* data, std::size_t size, std::basic_ostream< wchar_t >& strm);
extern BOOST_LOG_API dump_data_wchar_t* dump_data_wchar;
BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< wchar_t >& strm)
{
(dump_data_wchar)(data, size, strm);
}
#if !defined(BOOST_NO_CXX11_CHAR16_T)
typedef void dump_data_char16_t(const void* data, std::size_t size, std::basic_ostream< char16_t >& strm);
extern BOOST_LOG_API dump_data_char16_t* dump_data_char16;
BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char16_t >& strm)
{
(dump_data_char16)(data, size, strm);
}
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
typedef void dump_data_char32_t(const void* data, std::size_t size, std::basic_ostream< char32_t >& strm);
extern BOOST_LOG_API dump_data_char32_t* dump_data_char32;
BOOST_FORCEINLINE void dump_data(const void* data, std::size_t size, std::basic_ostream< char32_t >& strm)
{
(dump_data_char32)(data, size, strm);
}
#endif
template< std::size_t SizeV, typename R >
struct enable_dump_size_based
{
};
template< typename R >
struct enable_dump_size_based< 1u, R >
{
typedef R type;
};
template< typename T, typename R >
struct enable_dump :
public enable_dump_size_based< sizeof(T), R >
{
};
template< typename R >
struct enable_dump< void, R >
{
typedef R type;
};
template< typename R >
struct enable_dump< const void, R >
{
typedef R type;
};
template< typename R >
struct enable_dump< volatile void, R >
{
typedef R type;
};
template< typename R >
struct enable_dump< const volatile void, R >
{
typedef R type;
};
} // namespace aux
/*!
* \brief Manipulator for printing binary representation of the data
*/
class dump_manip
{
private:
//! Beginning of the data
const void* m_data;
//! Size of the data, in bytes
std::size_t m_size;
public:
dump_manip(const void* data, std::size_t size) BOOST_NOEXCEPT : m_data(data), m_size(size) {}
dump_manip(dump_manip const& that) BOOST_NOEXCEPT : m_data(that.m_data), m_size(that.m_size) {}
const void* get_data() const BOOST_NOEXCEPT { return m_data; }
std::size_t get_size() const BOOST_NOEXCEPT { return m_size; }
};
//! The operator outputs binary data to a stream
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, dump_manip const& manip)
{
if (strm.good())
aux::dump_data(manip.get_data(), manip.get_size(), strm);
return strm;
}
/*!
* \brief Manipulator for printing binary representation of the data with a size limit
*/
class bounded_dump_manip :
public dump_manip
{
private:
//! Maximum size to output, in bytes
std::size_t m_max_size;
public:
bounded_dump_manip(const void* data, std::size_t size, std::size_t max_size) BOOST_NOEXCEPT : dump_manip(data, size), m_max_size(max_size) {}
bounded_dump_manip(bounded_dump_manip const& that) BOOST_NOEXCEPT : dump_manip(static_cast< dump_manip const& >(that)), m_max_size(that.m_max_size) {}
std::size_t get_max_size() const BOOST_NOEXCEPT { return m_max_size; }
};
//! The operator outputs binary data to a stream
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, bounded_dump_manip const& manip)
{
if (strm.good())
{
const std::size_t size = manip.get_size(), max_size = manip.get_max_size();
if (max_size >= size)
{
aux::dump_data(manip.get_data(), size, strm);
}
else
{
aux::dump_data(manip.get_data(), max_size, strm);
strm << " and " << (size - max_size) << " bytes more";
}
}
return strm;
}
/*!
* \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form
* \param data The pointer to the beginning of the region
* \param size The size of the region, in bytes
* \return The manipulator that is to be put to a stream
*/
template< typename T >
inline typename aux::enable_dump< T, dump_manip >::type dump(T* data, std::size_t size) BOOST_NOEXCEPT
{
return dump_manip((const void*)data, size);
}
/*!
* \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form
* \param data The pointer to the beginning of the array
* \param count The size of the region, in number of \c T elements
* \return The manipulator that is to be put to a stream
*/
template< typename T >
inline dump_manip dump_elements(T* data, std::size_t count) BOOST_NOEXCEPT
{
return dump_manip((const void*)data, count * sizeof(T));
}
/*!
* \brief Creates a stream manipulator that will output contents of a memory region in hexadecimal form
* \param data The pointer to the beginning of the region
* \param size The size of the region, in bytes
* \param max_size The maximum number of bytes of the region to output
* \return The manipulator that is to be put to a stream
*/
template< typename T >
inline typename aux::enable_dump< T, bounded_dump_manip >::type dump(T* data, std::size_t size, std::size_t max_size) BOOST_NOEXCEPT
{
return bounded_dump_manip((const void*)data, size, max_size);
}
/*!
* \brief Creates a stream manipulator that will dump elements of an array in hexadecimal form
* \param data The pointer to the beginning of the array
* \param count The size of the region, in number of \c T elements
* \param max_count The maximum number of elements to output
* \return The manipulator that is to be put to a stream
*/
template< typename T >
inline bounded_dump_manip dump_elements(T* data, std::size_t count, std::size_t max_count) BOOST_NOEXCEPT
{
return bounded_dump_manip((const void*)data, count * sizeof(T), max_count * sizeof(T));
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_MANIPULATORS_DUMP_HPP_INCLUDED_
@@ -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 to_log.hpp
* \author Andrey Semashev
* \date 06.11.2012
*
* This header contains the \c to_log output manipulator.
*/
#ifndef BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_
#include <iosfwd>
#include <boost/core/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/is_ostream.hpp>
#include <boost/log/utility/formatting_ostream_fwd.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief Generic manipulator for customizing output to log
*/
template< typename T, typename TagT = void >
class to_log_manip
{
public:
//! Output value type
typedef T value_type;
//! Value tag type
typedef TagT tag_type;
private:
//! Reference to the value
value_type const& m_value;
public:
explicit to_log_manip(value_type const& value) BOOST_NOEXCEPT : m_value(value) {}
to_log_manip(to_log_manip const& that) BOOST_NOEXCEPT : m_value(that.m_value) {}
value_type const& get() const BOOST_NOEXCEPT { return m_value; }
};
template< typename StreamT, typename T, typename TagT >
inline typename enable_if_c< log::aux::is_ostream< StreamT >::value, StreamT& >::type operator<< (StreamT& strm, to_log_manip< T, TagT > manip)
{
strm << manip.get();
return strm;
}
template< typename T >
inline to_log_manip< T > to_log(T const& value) BOOST_NOEXCEPT
{
return to_log_manip< T >(value);
}
template< typename TagT, typename T >
inline to_log_manip< T, TagT > to_log(T const& value) BOOST_NOEXCEPT
{
return to_log_manip< T, TagT >(value);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_MANIPULATORS_TO_LOG_HPP_INCLUDED_
@@ -0,0 +1,196 @@
/*
* 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 once_block.hpp
* \author Andrey Semashev
* \date 23.06.2010
*
* \brief The header defines classes and macros for once-blocks.
*/
#ifndef BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/unique_identifier_name.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_LOG_NO_THREADS
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief A flag to detect if a code block has already been executed.
*
* This structure should be used in conjunction with the \c BOOST_LOG_ONCE_BLOCK_FLAG
* macro. Usage example:
*
* <code>
* once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
*
* void foo()
* {
* BOOST_LOG_ONCE_BLOCK_FLAG(flag)
* {
* puts("Hello, world once!");
* }
* }
* </code>
*/
struct once_block_flag
{
#ifndef BOOST_LOG_DOXYGEN_PASS
// Do not use, implementation detail
enum
{
uninitialized = 0, // this must be zero, so that zero-initialized once_block_flag is equivalent to the one initialized with uninitialized
being_initialized,
initialized
};
unsigned char status;
#endif // BOOST_LOG_DOXYGEN_PASS
};
/*!
* \def BOOST_LOG_ONCE_BLOCK_INIT
*
* The static initializer for \c once_block_flag.
*/
#define BOOST_LOG_ONCE_BLOCK_INIT { boost::log::once_block_flag::uninitialized }
namespace aux {
class once_block_sentry
{
private:
once_block_flag& m_flag;
public:
explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f)
{
}
~once_block_sentry() BOOST_NOEXCEPT
{
if (BOOST_UNLIKELY(m_flag.status != once_block_flag::initialized))
rollback();
}
bool executed() const BOOST_NOEXCEPT
{
return (m_flag.status == once_block_flag::initialized || enter_once_block());
}
BOOST_LOG_API void commit() BOOST_NOEXCEPT;
private:
BOOST_LOG_API bool enter_once_block() const BOOST_NOEXCEPT;
BOOST_LOG_API void rollback() BOOST_NOEXCEPT;
// Non-copyable, non-assignable
BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&))
BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&))
};
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#else // BOOST_LOG_NO_THREADS
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
struct once_block_flag
{
bool status;
};
#define BOOST_LOG_ONCE_BLOCK_INIT { false }
namespace aux {
class once_block_sentry
{
private:
once_block_flag& m_flag;
public:
explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f)
{
}
bool executed() const BOOST_NOEXCEPT
{
return m_flag.status;
}
void commit() BOOST_NOEXCEPT
{
m_flag.status = true;
}
// Non-copyable, non-assignable
BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&))
BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&))
};
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#endif // BOOST_LOG_NO_THREADS
#ifndef BOOST_LOG_DOXYGEN_PASS
#define BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)\
for (boost::log::aux::once_block_sentry sentry_var((flag_var));\
BOOST_UNLIKELY(!sentry_var.executed()); sentry_var.commit())
// NOTE: flag_var deliberately doesn't have an initializer so that it is zero-initialized at the static initialization stage
#define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\
static boost::log::once_block_flag flag_var;\
BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)
#endif // BOOST_LOG_DOXYGEN_PASS
/*!
* \def BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)
*
* Begins a code block to be executed only once, with protection against thread concurrency.
* User has to provide the flag variable that controls whether the block has already
* been executed.
*/
#define BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)\
BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(\
flag_var,\
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
/*!
* \def BOOST_LOG_ONCE_BLOCK()
*
* Begins a code block to be executed only once, with protection against thread concurrency.
*/
#define BOOST_LOG_ONCE_BLOCK()\
BOOST_LOG_ONCE_BLOCK_INTERNAL(\
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_flag_),\
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
@@ -0,0 +1,46 @@
/*
* Copyright Andrey Semashev 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file open_mode.hpp
* \author Andrey Semashev
* \date 01.01.2016
*
* The header defines resource opening modes.
*/
#ifndef BOOST_LOG_UTILITY_OPEN_MODE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_OPEN_MODE_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace open_mode {
//! Create a new resource; fail if exists already
struct create_only_tag {} const create_only = create_only_tag();
//! Opens an existing resource; fail if not exist
struct open_only_tag {} const open_only = open_only_tag();
//! Creates a new resource or opens an existing one
struct open_or_create_tag {} const open_or_create = open_or_create_tag();
} // namespace open_mode
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_OPEN_MODE_HPP_INCLUDED_
@@ -0,0 +1,213 @@
/*
* Copyright Lingxi Li 2015.
* Copyright Andrey Semashev 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 permissions.hpp
* \author Lingxi Li
* \author Andrey Semashev
* \date 14.10.2015
*
* The header contains an abstraction wrapper for security permissions.
*/
#ifndef BOOST_LOG_UTILITY_PERMISSIONS_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_PERMISSIONS_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifdef BOOST_WINDOWS
extern "C" {
struct _SECURITY_ATTRIBUTES;
}
#endif // BOOST_WINDOWS
namespace boost {
#ifdef BOOST_WINDOWS
namespace detail {
namespace winapi {
struct BOOST_LOG_MAY_ALIAS _SECURITY_ATTRIBUTES;
}
}
#endif
namespace interprocess {
class permissions;
} // namespace interprocess
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief Access permissions wrapper.
*
* On Windows platforms, it represents a pointer to \c SECURITY_ATTRIBUTES. The user is responsible
* for allocating and reclaiming resources associated with the pointer, \c permissions instance does
* not own them.
*
* On POSIX platforms, it represents a \c mode_t value.
*/
class permissions
{
public:
#if defined(BOOST_LOG_DOXYGEN_PASS)
//! The type of security permissions, specific to the operating system
typedef implementation_defined native_type;
#elif defined(BOOST_WINDOWS)
typedef ::_SECURITY_ATTRIBUTES* native_type;
#else
// Equivalent to POSIX mode_t
typedef unsigned int native_type;
#endif
#if !defined(BOOST_LOG_DOXYGEN_PASS)
private:
native_type m_perms;
#endif
public:
/*!
* Default constructor. The method constructs an object that represents
* a null \c SECURITY_ATTRIBUTES pointer on Windows platforms, and a
* \c mode_t value \c 0644 on POSIX platforms.
*/
permissions() BOOST_NOEXCEPT
{
set_default();
}
/*!
* Copy constructor.
*/
permissions(permissions const& that) BOOST_NOEXCEPT : m_perms(that.m_perms)
{
}
/*!
* Copy assignment.
*/
permissions& operator=(permissions const& that) BOOST_NOEXCEPT
{
m_perms = that.m_perms;
return *this;
}
/*!
* Initializing constructor.
*/
permissions(native_type perms) BOOST_NOEXCEPT : m_perms(perms)
{
}
#ifdef BOOST_WINDOWS
permissions(boost::detail::winapi::_SECURITY_ATTRIBUTES* perms) BOOST_NOEXCEPT : m_perms(reinterpret_cast< native_type >(perms))
{
}
#endif
/*!
* Initializing constructor.
*/
BOOST_LOG_API permissions(boost::interprocess::permissions const& perms) BOOST_NOEXCEPT;
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
/*!
* Move constructor.
*/
permissions(permissions&& that) BOOST_NOEXCEPT : m_perms(that.m_perms)
{
that.set_default();
}
/*!
* Move assignment.
*/
permissions& operator=(permissions&& that) BOOST_NOEXCEPT
{
m_perms = that.m_perms;
that.set_default();
return *this;
}
#endif
/*!
* Sets permissions from the OS-specific permissions.
*/
void set_native(native_type perms) BOOST_NOEXCEPT
{
m_perms = perms;
}
/*!
* Returns the underlying OS-specific permissions.
*/
native_type get_native() const BOOST_NOEXCEPT
{
return m_perms;
}
/*!
* Sets the default permissions, which are equivalent to \c NULL \c SECURITY_ATTRIBUTES
* on Windows and \c 0644 on POSIX platforms.
*/
void set_default() BOOST_NOEXCEPT
{
#if defined(BOOST_WINDOWS)
m_perms = 0;
#else
m_perms = 0644;
#endif
}
/*!
* Sets unrestricted permissions, which are equivalent to \c SECURITY_ATTRIBUTES with \c NULL DACL
* on Windows and \c 0666 on POSIX platforms.
*/
void set_unrestricted()
{
#if defined(BOOST_WINDOWS)
m_perms = get_unrestricted_security_attributes();
#else
m_perms = 0666;
#endif
}
/*!
* The method swaps the object with \a that.
*
* \param that The other object to swap with.
*/
void swap(permissions& that) BOOST_NOEXCEPT
{
native_type perms = m_perms;
m_perms = that.m_perms;
that.m_perms = perms;
}
//! Swaps the two \c permissions objects.
friend void swap(permissions& a, permissions& b) BOOST_NOEXCEPT
{
a.swap(b);
}
#if !defined(BOOST_LOG_DOXYGEN_PASS) && defined(BOOST_WINDOWS)
private:
static BOOST_LOG_API native_type get_unrestricted_security_attributes();
#endif
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_PERMISSIONS_HPP_INCLUDED_
@@ -0,0 +1,229 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file record_ordering.hpp
* \author Andrey Semashev
* \date 23.08.2009
*
* This header contains ordering predicates for logging records.
*/
#ifndef BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/function_traits.hpp>
#include <boost/log/core/record_view.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/attributes/attribute_value.hpp>
#include <boost/log/attributes/value_visitation.hpp>
#include <boost/log/utility/functional/logical.hpp>
#include <boost/log/utility/functional/nop.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief Ordering predicate, based on opaque pointers to the record view implementation data
*
* Since record views only refer to a shared implementation data, this predicate is able to order the views
* by comparing the pointers to the data. Therefore two views are considered to be equivalent if they
* refer to the same implementation data. Otherwise it is not specified whether one record is ordered before
* the other until the predicate is applied. Note that the ordering may change every time the application runs.
*
* This kind of ordering may be useful if log records are to be stored in an associative
* container with as least performance overhead as possible, when the particular order is not important.
*
* The \c FunT template argument is the predicate that is used to actually compare pointers. It should be
* able to compare <tt>const void*</tt> pointers. The compared pointers may refer to distinct memory regions,
* the pointers must not be interpreted in any way.
*/
template< typename FunT = less >
class abstract_ordering :
private FunT
{
public:
//! Result type
typedef bool result_type;
public:
/*!
* Default constructor. Requires \c FunT to be default constructible.
*/
abstract_ordering() : FunT()
{
}
/*!
* Initializing constructor. Constructs \c FunT instance as a copy of the \a fun argument.
*/
explicit abstract_ordering(FunT const& fun) : FunT(fun)
{
}
/*!
* Ordering operator
*/
result_type operator() (record_view const& left, record_view const& right) const
{
// We rely on the fact that the attribute_values() method returns a reference to the object in the record implementation,
// so we can compare pointers.
return FunT::operator() (static_cast< const void* >(&left.attribute_values()), static_cast< const void* >(&right.attribute_values()));
}
};
/*!
* \brief Ordering predicate, based on attribute values associated with records
*
* This predicate allows to order log records based on values of a specifically named attribute
* associated with them. Two given log records being compared should both have the specified
* attribute value of the specified type to be able to be ordered properly. As a special case,
* if neither of the records have the value, these records are considered equivalent. Otherwise,
* the ordering results are unspecified.
*/
template< typename ValueT, typename FunT = less >
class attribute_value_ordering :
private FunT
{
public:
//! Result type
typedef bool result_type;
//! Compared attribute value type
typedef ValueT value_type;
private:
template< typename LeftT >
struct l2_visitor
{
typedef void result_type;
l2_visitor(FunT const& fun, LeftT const& left, bool& result) :
m_fun(fun), m_left(left), m_result(result)
{
}
template< typename RightT >
result_type operator() (RightT const& right) const
{
m_result = m_fun(m_left, right);
}
private:
FunT const& m_fun;
LeftT const& m_left;
bool& m_result;
};
struct l1_visitor;
friend struct l1_visitor;
struct l1_visitor
{
typedef void result_type;
l1_visitor(attribute_value_ordering const& owner, record_view const& right, bool& result) :
m_owner(owner), m_right(right), m_result(result)
{
}
template< typename LeftT >
result_type operator() (LeftT const& left) const
{
boost::log::visit< value_type >(m_owner.m_name, m_right, l2_visitor< LeftT >(static_cast< FunT const& >(m_owner), left, m_result));
}
private:
attribute_value_ordering const& m_owner;
record_view const& m_right;
bool& m_result;
};
private:
//! Attribute value name
const attribute_name m_name;
public:
/*!
* Initializing constructor.
*
* \param name The attribute value name to be compared
* \param fun The ordering functor
*/
explicit attribute_value_ordering(attribute_name const& name, FunT const& fun = FunT()) :
FunT(fun),
m_name(name)
{
}
/*!
* Ordering operator
*/
result_type operator() (record_view const& left, record_view const& right) const
{
bool result = false;
if (!boost::log::visit< value_type >(m_name, left, l1_visitor(*this, right, result)))
{
return !boost::log::visit< value_type >(m_name, right, nop());
}
return result;
}
};
/*!
* The function constructs a log record ordering predicate
*/
template< typename ValueT, typename FunT >
inline attribute_value_ordering< ValueT, FunT > make_attr_ordering(attribute_name const& name, FunT const& fun)
{
typedef attribute_value_ordering< ValueT, FunT > ordering_t;
return ordering_t(name, fun);
}
#if !defined(BOOST_LOG_NO_FUNCTION_TRAITS)
namespace aux {
//! An ordering predicate constructor that uses SFINAE to disable invalid instantiations
template<
typename FunT,
typename ArityCheckT = typename boost::enable_if_c< aux::arity_of< FunT >::value == 2 >::type,
typename Arg1T = typename aux::first_argument_type_of< FunT >::type,
typename Arg2T = typename aux::second_argument_type_of< FunT >::type,
typename ArgsCheckT = typename boost::enable_if_c< is_same< Arg1T, Arg2T >::value >::type
>
struct make_attr_ordering_type
{
typedef attribute_value_ordering< Arg1T, FunT > type;
};
} // namespace aux
/*!
* The function constructs a log record ordering predicate
*/
template< typename FunT >
inline typename aux::make_attr_ordering_type< FunT >::type make_attr_ordering(attribute_name const& name, FunT const& fun)
{
typedef typename aux::make_attr_ordering_type< FunT >::type ordering_t;
return ordering_t(name, fun);
}
#endif // BOOST_LOG_NO_FUNCTION_TRAITS
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
@@ -0,0 +1,37 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file setup.hpp
* \author Andrey Semashev
* \date 16.02.2013
*
* This header includes all library setup helpers.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/from_settings.hpp>
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/utility/setup/settings_parser.hpp>
#include <boost/log/utility/setup/filter_parser.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_LOG_UTILITY_SETUP_HPP_INCLUDED_
@@ -0,0 +1,76 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file common_attributes.hpp
* \author Andrey Semashev
* \date 16.05.2008
*
* The header contains implementation of convenience functions for registering commonly used attributes.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_
#include <iostream>
#include <boost/log/detail/config.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/attributes/clock.hpp>
#include <boost/log/attributes/counter.hpp>
#include <boost/log/attributes/current_process_id.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/attributes/current_thread_id.hpp>
#endif
#include <boost/log/detail/default_attribute_names.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief Simple attribute initialization routine
*
* The function adds commonly used attributes to the logging system. Specifically, the following
* attributes are registered globally:
*
* \li LineID - logging records counter with value type <tt>unsigned int</tt>
* \li TimeStamp - local time generator with value type <tt>boost::posix_time::ptime</tt>
* \li ProcessID - current process identifier with value type
* <tt>attributes::current_process_id::value_type</tt>
* \li ThreadID - in multithreaded builds, current thread identifier with
* value type <tt>attributes::current_thread_id::value_type</tt>
*/
inline void add_common_attributes()
{
shared_ptr< core > pCore = core::get();
pCore->add_global_attribute(
aux::default_attribute_names::line_id(),
attributes::counter< unsigned int >(1));
pCore->add_global_attribute(
aux::default_attribute_names::timestamp(),
attributes::local_clock());
pCore->add_global_attribute(
aux::default_attribute_names::process_id(),
attributes::current_process_id());
#if !defined(BOOST_LOG_NO_THREADS)
pCore->add_global_attribute(
aux::default_attribute_names::thread_id(),
attributes::current_thread_id());
#endif
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_COMMON_ATTRIBUTES_HPP_INCLUDED_
@@ -0,0 +1,243 @@
/*
* 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 console.hpp
* \author Andrey Semashev
* \date 16.05.2008
*
* The header contains implementation of convenience functions for enabling logging to console.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
#include <iostream>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/sink_init_helpers.hpp>
#ifndef BOOST_LOG_NO_THREADS
#include <boost/log/sinks/sync_frontend.hpp>
#else
#include <boost/log/sinks/unlocked_frontend.hpp>
#endif
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/keywords/format.hpp>
#include <boost/log/keywords/filter.hpp>
#include <boost/log/keywords/auto_flush.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_LOG_DOXYGEN_PASS
#ifndef BOOST_LOG_NO_THREADS
#define BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL sinks::synchronous_sink
#else
#define BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL sinks::unlocked_sink
#endif
#endif // BOOST_LOG_DOXYGEN_PASS
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
// The function creates and initializes the sink
template< typename CharT, typename ArgsT >
shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(std::basic_ostream< CharT >& strm, ArgsT const& args)
{
shared_ptr< std::basic_ostream< CharT > > pStream(&strm, boost::null_deleter());
typedef sinks::basic_text_ostream_backend< CharT > backend_t;
shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >();
pBackend->add_stream(pStream);
pBackend->auto_flush(args[keywords::auto_flush | false]);
typedef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL< backend_t > sink_t;
shared_ptr< sink_t > pSink = boost::make_shared< sink_t >(pBackend);
aux::setup_filter(*pSink, args,
typename is_void< typename parameter::binding< ArgsT, keywords::tag::filter, void >::type >::type());
aux::setup_formatter(*pSink, args,
typename is_void< typename parameter::binding< ArgsT, keywords::tag::format, void >::type >::type());
core::get()->add_sink(pSink);
return pSink;
}
template< typename CharT >
struct default_console_stream;
#ifdef BOOST_LOG_USE_CHAR
template< >
struct default_console_stream< char >
{
static std::ostream& get() { return std::clog; }
};
#endif // BOOST_LOG_USE_CHAR
#ifdef BOOST_LOG_USE_WCHAR_T
template< >
struct default_console_stream< wchar_t >
{
static std::wostream& get() { return std::wclog; }
};
#endif // BOOST_LOG_USE_WCHAR_T
} // namespace aux
#ifndef BOOST_LOG_DOXYGEN_PASS
template< typename CharT >
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log()
{
return aux::add_console_log(
aux::default_console_stream< CharT >::get(), keywords::auto_flush = false);
}
template< typename CharT >
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(std::basic_ostream< CharT >& strm)
{
return aux::add_console_log(strm, keywords::auto_flush = false);
}
template< typename CharT, typename ArgT1 >
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1)
{
return aux::add_console_log(strm, arg1);
}
template< typename CharT, typename ArgT1, typename ArgT2 >
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2)
{
return aux::add_console_log(strm, (arg1, arg2));
}
template< typename CharT, typename ArgT1, typename ArgT2, typename ArgT3 >
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(std::basic_ostream< CharT >& strm, ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3)
{
return aux::add_console_log(strm, (arg1, arg2, arg3));
}
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* The function constructs sink for the specified console stream and adds it to the core
*
* \param strm One of the standard console streams: <tt>std::cout</tt>, <tt>std::cerr</tt> or <tt>std::clog</tt>
* (or the corresponding wide-character analogues).
* \param args Optional additional named arguments for the sink initialization. The following arguments are supported:
* \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter,
* or a filter lambda expression.
* \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter,
* or a formatter lambda expression (either streaming or Boost.Format-like notation).
* \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the stream
* after each written record.
* \return Pointer to the constructed sink.
*/
template< typename CharT, typename... ArgsT >
shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(std::basic_ostream< CharT >& strm, ArgsT... const& args);
/*!
* Equivalent to: <tt>add_console_log(std::clog);</tt> or <tt>add_console_log(std::wclog);</tt>,
* depending on the \c CharT type.
*
* \overload
*/
template< typename CharT, typename... ArgsT >
shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::basic_text_ostream_backend< CharT >
>
> add_console_log(ArgsT... const& args);
#endif // BOOST_LOG_DOXYGEN_PASS
#ifdef BOOST_LOG_USE_CHAR
/*!
* The function constructs sink for the <tt>std::clog</tt> stream and adds it to the core
*
* \overload
*
* \return Pointer to the constructed sink.
*/
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::text_ostream_backend
>
> add_console_log()
{
return add_console_log(std::clog);
}
#endif // BOOST_LOG_USE_CHAR
#ifdef BOOST_LOG_USE_WCHAR_T
/*!
* The function constructs sink for the <tt>std::wclog</tt> stream and adds it to the core
*
* \return Pointer to the constructed sink.
*/
inline shared_ptr<
BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL<
sinks::wtext_ostream_backend
>
> wadd_console_log()
{
return add_console_log(std::wclog);
}
#endif // BOOST_LOG_USE_WCHAR_T
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#undef BOOST_LOG_CONSOLE_SINK_FRONTEND_INTERNAL
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_CONSOLE_HPP_INCLUDED_
@@ -0,0 +1,167 @@
/*
* 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 file.hpp
* \author Andrey Semashev
* \date 16.05.2008
*
* The header contains implementation of convenience functions for enabling logging to a file.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/parameter/parameters.hpp> // for is_named_argument
#include <boost/preprocessor/comparison/greater.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/sink_init_helpers.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/core/core.hpp>
#ifndef BOOST_LOG_NO_THREADS
#include <boost/log/sinks/sync_frontend.hpp>
#else
#include <boost/log/sinks/unlocked_frontend.hpp>
#endif
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/keywords/scan_method.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_LOG_DOXYGEN_PASS
#ifndef BOOST_LOG_NO_THREADS
#define BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL sinks::synchronous_sink
#else
#define BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL sinks::unlocked_sink
#endif
#endif // BOOST_LOG_DOXYGEN_PASS
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! The function creates a file collector according to the specified arguments
template< typename ArgsT >
inline shared_ptr< sinks::file::collector > setup_file_collector(ArgsT const&, mpl::true_ const&)
{
return shared_ptr< sinks::file::collector >();
}
template< typename ArgsT >
inline shared_ptr< sinks::file::collector > setup_file_collector(ArgsT const& args, mpl::false_ const&)
{
return sinks::file::make_collector(args);
}
//! The function constructs the sink and adds it to the core
template< typename ArgsT >
shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT const& args)
{
typedef sinks::text_file_backend backend_t;
shared_ptr< backend_t > pBackend = boost::make_shared< backend_t >(args);
shared_ptr< sinks::file::collector > pCollector = aux::setup_file_collector(args,
typename is_void< typename parameter::binding< ArgsT, keywords::tag::target, void >::type >::type());
if (pCollector)
{
pBackend->set_file_collector(pCollector);
pBackend->scan_for_files(args[keywords::scan_method | sinks::file::scan_matching]);
}
shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< backend_t > > pSink =
boost::make_shared< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< backend_t > >(pBackend);
aux::setup_filter(*pSink, args,
typename is_void< typename parameter::binding< ArgsT, keywords::tag::filter, void >::type >::type());
aux::setup_formatter(*pSink, args,
typename is_void< typename parameter::binding< ArgsT, keywords::tag::format, void >::type >::type());
core::get()->add_sink(pSink);
return pSink;
}
//! The function wraps the argument into a file_name named argument, if needed
template< typename T >
inline T const& wrap_file_name(T const& arg, mpl::true_)
{
return arg;
}
template< typename T >
inline typename parameter::aux::tag< keywords::tag::file_name, T const >::type
wrap_file_name(T const& arg, mpl::false_)
{
return keywords::file_name = arg;
}
} // namespace aux
#ifndef BOOST_LOG_DOXYGEN_PASS
#define BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL(z, n, data)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
inline shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\
{\
return aux::add_file_log((\
aux::wrap_file_name(arg0, typename parameter::aux::is_named_argument< T0 >::type())\
BOOST_PP_COMMA_IF(BOOST_PP_GREATER(n, 1))\
BOOST_PP_ENUM_SHIFTED_PARAMS(n, arg)\
));\
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL, ~)
#undef BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* The function initializes the logging library to write logs to a file stream.
*
* \param args A number of named arguments. The following parameters are supported:
* \li \c file_name The file name or its pattern. This parameter is mandatory.
* \li \c open_mode The mask that describes the open mode for the file. See <tt>std::ios_base::openmode</tt>.
* \li \c rotation_size The size of the file at which rotation should occur. See <tt>basic_text_file_backend</tt>.
* \li \c time_based_rotation The predicate for time-based file rotations. See <tt>basic_text_file_backend</tt>.
* \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the file
* after each written record.
* \li \c target The target directory to store rotated files in. See <tt>sinks::file::make_collector</tt>.
* \li \c max_size The maximum total size of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c min_free_space Minimum free space in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c max_files The maximum total number of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c scan_method The method of scanning the target directory for log files. See <tt>sinks::file::scan_method</tt>.
* \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter,
* or a filter lambda expression.
* \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter,
* or a formatter lambda expression (either streaming or Boost.Format-like notation).
* \return Pointer to the constructed sink.
*/
template< typename... ArgsT >
shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT... const& args);
#endif // BOOST_LOG_DOXYGEN_PASS
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#undef BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_FILE_HPP_INCLUDED_
@@ -0,0 +1,346 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file filter_parser.hpp
* \author Andrey Semashev
* \date 31.03.2008
*
* The header contains definition of a filter parser function.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_
#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/phoenix/operator/comparison.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/detail/code_conversion.hpp>
#include <boost/log/exceptions.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
#include <boost/log/expressions/filter.hpp>
#include <boost/log/expressions/keyword_fwd.hpp>
#include <boost/log/expressions/attr.hpp>
#include <boost/log/expressions/predicates/has_attr.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* The interface class for all filter factories.
*/
template< typename CharT >
struct filter_factory
{
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
/*!
* Default constructor
*/
BOOST_DEFAULTED_FUNCTION(filter_factory(), {})
/*!
* Virtual destructor
*/
virtual ~filter_factory() {}
/*!
* The callback for filter for the attribute existence test
*/
virtual filter on_exists_test(attribute_name const& name)
{
return filter(expressions::has_attr(name));
}
/*!
* The callback for equality relation filter
*/
virtual filter on_equality_relation(attribute_name const& name, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The equality attribute value relation is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The callback for inequality relation filter
*/
virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The inequality attribute value relation is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The callback for less relation filter
*/
virtual filter on_less_relation(attribute_name const& name, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less attribute value relation is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The callback for greater relation filter
*/
virtual filter on_greater_relation(attribute_name const& name, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater attribute value relation is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The callback for less or equal relation filter
*/
virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less-or-equal attribute value relation is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The callback for greater or equal relation filter
*/
virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater-or-equal attribute value relation is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The callback for custom relation filter
*/
virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(rel) + "\" is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
BOOST_DELETED_FUNCTION(filter_factory(filter_factory const&))
BOOST_DELETED_FUNCTION(filter_factory& operator= (filter_factory const&))
};
/*!
* The base class for filter factories. The class defines default implementations for most
* filter expressions. In order to be able to construct filters, the attribute value type must
* support reading from a stream. Also, the default filters will rely on relational operators for
* the type, so these operators must also be defined.
*/
template< typename CharT, typename AttributeValueT >
class basic_filter_factory :
public filter_factory< CharT >
{
//! Base type
typedef filter_factory< CharT > base_type;
public:
//! The type(s) of the attribute value expected
typedef AttributeValueT value_type;
// Type imports
typedef typename base_type::string_type string_type;
/*!
* The callback for filter for the attribute existence test
*/
virtual filter on_exists_test(attribute_name const& name)
{
return filter(expressions::has_attr< value_type >(name));
}
/*!
* The callback for equality relation filter
*/
virtual filter on_equality_relation(attribute_name const& name, string_type const& arg)
{
return filter(expressions::attr< value_type >(name) == parse_argument(arg));
}
/*!
* The callback for inequality relation filter
*/
virtual filter on_inequality_relation(attribute_name const& name, string_type const& arg)
{
return filter(expressions::attr< value_type >(name) != parse_argument(arg));
}
/*!
* The callback for less relation filter
*/
virtual filter on_less_relation(attribute_name const& name, string_type const& arg)
{
return filter(expressions::attr< value_type >(name) < parse_argument(arg));
}
/*!
* The callback for greater relation filter
*/
virtual filter on_greater_relation(attribute_name const& name, string_type const& arg)
{
return filter(expressions::attr< value_type >(name) > parse_argument(arg));
}
/*!
* The callback for less or equal relation filter
*/
virtual filter on_less_or_equal_relation(attribute_name const& name, string_type const& arg)
{
return filter(expressions::attr< value_type >(name) <= parse_argument(arg));
}
/*!
* The callback for greater or equal relation filter
*/
virtual filter on_greater_or_equal_relation(attribute_name const& name, string_type const& arg)
{
return filter(expressions::attr< value_type >(name) >= parse_argument(arg));
}
/*!
* The callback for custom relation filter
*/
virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg)
{
BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(rel) + "\" is not supported", (name));
BOOST_LOG_UNREACHABLE_RETURN(filter());
}
/*!
* The function parses the argument value for a binary relation
*/
virtual value_type parse_argument(string_type const& arg)
{
return boost::lexical_cast< value_type >(arg);
}
};
/*!
* The function registers a filter factory object for the specified attribute name. The factory will be
* used to construct a filter during parsing the filter string.
*
* \pre <tt>name != NULL && factory != NULL</tt>, <tt>name</tt> points to a zero-terminated string
* \param name Attribute name to associate the factory with
* \param factory The filter factory
*/
template< typename CharT >
BOOST_LOG_SETUP_API void register_filter_factory(
attribute_name const& name, shared_ptr< filter_factory< CharT > > const& factory);
/*!
* The function registers a filter factory object for the specified attribute name. The factory will be
* used to construct a filter during parsing the filter string.
*
* \pre <tt>name != NULL && factory != NULL</tt>, <tt>name</tt> points to a zero-terminated string
* \param name Attribute name to associate the factory with
* \param factory The filter factory
*/
template< typename FactoryT >
inline typename boost::enable_if_c<
is_base_and_derived< filter_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_filter_factory(attribute_name const& name, shared_ptr< FactoryT > const& factory)
{
typedef filter_factory< typename FactoryT::char_type > factory_base;
register_filter_factory(name, boost::static_pointer_cast< factory_base >(factory));
}
/*!
* The function registers a simple filter factory object for the specified attribute name. The factory will
* support attribute values of type \c AttributeValueT, which must support all relation operations, such as
* equality comparison and less/greater ordering, and also extraction from stream.
*
* \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string
* \param name Attribute name to associate the factory with
*/
template< typename AttributeValueT, typename CharT >
inline void register_simple_filter_factory(attribute_name const& name)
{
shared_ptr< filter_factory< CharT > > factory =
boost::make_shared< basic_filter_factory< CharT, AttributeValueT > >();
register_filter_factory(name, factory);
}
/*!
* The function registers a simple filter factory object for the specified attribute name. The factory will
* support attribute values of type \c AttributeValueT, which must support all relation operations, such as
* equality comparison and less/greater ordering, and also extraction from stream.
*
* \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string
* \param name Attribute name to associate the factory with
*/
template< typename AttributeValueT >
inline void register_simple_filter_factory(attribute_name const& name)
{
register_simple_filter_factory< AttributeValueT, char >(name);
}
/*!
* The function registers a simple filter factory object for the specified attribute keyword. The factory will
* support attribute values described by the keyword. The values must support all relation operations, such as
* equality comparison and less/greater ordering, and also extraction from stream.
*
* \pre <tt>name != NULL</tt>, <tt>name</tt> points to a zero-terminated string
* \param keyword Attribute keyword to associate the factory with
*/
template< typename CharT, typename DescriptorT, template< typename > class ActorT >
inline void register_simple_filter_factory(expressions::attribute_keyword< DescriptorT, ActorT > const& keyword)
{
register_simple_filter_factory< typename DescriptorT::value_type, CharT >(keyword.get_name());
}
/*!
* The function parses a filter from the sequence of characters
*
* \pre <tt>begin <= end</tt>, both pointers must not be \c NULL
* \param begin Pointer to the first character of the sequence
* \param end Pointer to the after-the-last character of the sequence
* \return A function object that can be used as a filter.
*
* \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence.
*/
template< typename CharT >
BOOST_LOG_SETUP_API filter parse_filter(const CharT* begin, const CharT* end);
/*!
* The function parses a filter from the string
*
* \param str A string that contains filter description
* \return A function object that can be used as a filter.
*
* \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence.
*/
template< typename CharT, typename TraitsT, typename AllocatorT >
inline filter parse_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& str)
{
const CharT* p = str.c_str();
return parse_filter(p, p + str.size());
}
/*!
* The function parses a filter from the string
*
* \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string.
* \param str A string that contains filter description.
* \return A function object that can be used as a filter.
*
* \b Throws: An <tt>std::exception</tt>-based exception, if a filter cannot be recognized in the character sequence.
*/
template< typename CharT >
inline filter parse_filter(const CharT* str)
{
return parse_filter(str, str + std::char_traits< CharT >::length(str));
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_FILTER_PARSER_HPP_INCLUDED_
@@ -0,0 +1,216 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file formatter_parser.hpp
* \author Andrey Semashev
* \date 07.04.2008
*
* The header contains definition of a formatter parser function, along with facilities to
* add support for custom formatters.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_
#include <iosfwd>
#include <map>
#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/expressions/formatter.hpp>
#include <boost/log/expressions/attr.hpp>
#include <boost/log/expressions/formatters/stream.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* Formatter factory base interface.
*/
template< typename CharT >
struct formatter_factory
{
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
//! The formatter function object
typedef basic_formatter< char_type > formatter_type;
/*!
* Type of the map of formatter factory arguments [argument name -> argument value].
* This type of maps will be passed to formatter factories on attempt to create a formatter.
*/
typedef std::map< string_type, string_type > args_map;
/*!
* Default constructor
*/
BOOST_DEFAULTED_FUNCTION(formatter_factory(), {})
/*!
* Virtual destructor
*/
virtual ~formatter_factory() {}
/*!
* The function creates a formatter for the specified attribute.
*
* \param name Attribute name
* \param args Formatter arguments
*/
virtual formatter_type create_formatter(attribute_name const& name, args_map const& args) = 0;
BOOST_DELETED_FUNCTION(formatter_factory(formatter_factory const&))
BOOST_DELETED_FUNCTION(formatter_factory& operator= (formatter_factory const&))
};
/*!
* Base class for formatter factories. This class provides default implementation of formatter expressions for
* types supporting stream output. The factory does not take into account any additional parameters that may be specified.
*/
template< typename CharT, typename AttributeValueT >
class basic_formatter_factory :
public formatter_factory< CharT >
{
private:
typedef formatter_factory< CharT > base_type;
public:
//! Attribute value type
typedef AttributeValueT value_type;
// Type imports from the base class
typedef typename base_type::formatter_type formatter_type;
typedef typename base_type::args_map args_map;
/*!
* The function creates a formatter for the specified attribute.
*
* \param name Attribute name
* \param args Formatter arguments
*/
formatter_type create_formatter(attribute_name const& name, args_map const& args)
{
return formatter_type(expressions::stream << expressions::attr< value_type >(name));
}
};
/*!
* \brief The function registers a user-defined formatter factory
*
* The function registers a user-defined formatter factory. The registered factory function will be
* called when the formatter parser detects the specified attribute name in the formatter string.
*
* \pre <tt>!!attr_name && !!factory</tt>.
*
* \param attr_name Attribute name
* \param factory Pointer to the formatter factory
*/
template< typename CharT >
BOOST_LOG_SETUP_API void register_formatter_factory(
attribute_name const& attr_name, shared_ptr< formatter_factory< CharT > > const& factory);
/*!
* \brief The function registers a user-defined formatter factory
*
* The function registers a user-defined formatter factory. The registered factory function will be
* called when the formatter parser detects the specified attribute name in the formatter string.
*
* \pre <tt>!!attr_name && !!factory</tt>.
*
* \param attr_name Attribute name
* \param factory Pointer to the formatter factory
*/
template< typename FactoryT >
inline typename boost::enable_if_c<
is_base_and_derived< formatter_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_formatter_factory(attribute_name const& attr_name, shared_ptr< FactoryT > const& factory)
{
typedef formatter_factory< typename FactoryT::char_type > factory_base;
register_formatter_factory(attr_name, boost::static_pointer_cast< factory_base >(factory));
}
/*!
* \brief The function registers a simple formatter factory
*
* The function registers a simple formatter factory. The registered factory will generate formatters
* that will be equivalent to the <tt>log::expressions::attr</tt> formatter (i.e. that will use the
* native \c operator<< to format the attribute value). The factory does not use any arguments from the format string,
* if specified.
*
* \pre <tt>!!attr_name</tt>.
*
* \param attr_name Attribute name
*/
template< typename AttributeValueT, typename CharT >
inline void register_simple_formatter_factory(attribute_name const& attr_name)
{
shared_ptr< formatter_factory< CharT > > factory =
boost::make_shared< basic_formatter_factory< CharT, AttributeValueT > >();
register_formatter_factory(attr_name, factory);
}
/*!
* The function parses a formatter from the sequence of characters
*
* \pre <tt>begin <= end</tt>, both pointers must not be NULL
* \param begin Pointer to the first character of the sequence
* \param end Pointer to the after-the-last character of the sequence
* \return The parsed formatter.
*
* \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence.
*/
template< typename CharT >
BOOST_LOG_SETUP_API basic_formatter< CharT > parse_formatter(const CharT* begin, const CharT* end);
/*!
* The function parses a formatter from the string
*
* \param str A string that contains format description
* \return The parsed formatter.
*
* \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence.
*/
template< typename CharT, typename TraitsT, typename AllocatorT >
inline basic_formatter< CharT > parse_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& str)
{
const CharT* p = str.c_str();
return parse_formatter(p, p + str.size());
}
/*!
* The function parses a formatter from the string
*
* \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string
* \param str A string that contains format description.
* \return The parsed formatter.
*
* \b Throws: An <tt>std::exception</tt>-based exception, if a formatter cannot be recognized in the character sequence.
*/
template< typename CharT >
inline basic_formatter< CharT > parse_formatter(const CharT* str)
{
return parse_formatter(str, str + std::char_traits< CharT >::length(str));
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_FORMATTER_PARSER_HPP_INCLUDED_
@@ -0,0 +1,164 @@
/*
* 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 from_settings.hpp
* \author Andrey Semashev
* \date 11.10.2009
*
* The header contains definition of facilities that allows to initialize the library from
* settings.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_
#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/sinks/sink.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* The function initializes the logging library from a settings container
*
* \param setts Library settings container
*
* \b Throws: An <tt>std::exception</tt>-based exception if the provided settings are not valid.
*/
template< typename CharT >
BOOST_LOG_SETUP_API void init_from_settings(basic_settings_section< CharT > const& setts);
/*!
* Sink factory base interface
*/
template< typename CharT >
struct sink_factory
{
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
//! Settings section type
typedef basic_settings_section< char_type > settings_section;
/*!
* Default constructor
*/
BOOST_DEFAULTED_FUNCTION(sink_factory(), {})
/*!
* Virtual destructor
*/
virtual ~sink_factory() {}
/*!
* The function creates a formatter for the specified attribute.
*
* \param settings Sink parameters
*/
virtual shared_ptr< sinks::sink > create_sink(settings_section const& settings) = 0;
BOOST_DELETED_FUNCTION(sink_factory(sink_factory const&))
BOOST_DELETED_FUNCTION(sink_factory& operator= (sink_factory const&))
};
/*!
* \brief The function registers a factory for a custom sink
*
* The function registers a factory for a sink. The factory will be called to create sink
* instance when the parser discovers the specified sink type in the settings file. The
* factory must accept a map of parameters [parameter name -> parameter value] that it
* may use to initialize the sink. The factory must return a non-NULL pointer to the
* constructed sink instance.
*
* \param sink_name The custom sink name. Must point to a zero-terminated sequence of characters,
* must not be NULL.
* \param factory Pointer to the custom sink factory. Must not be NULL.
*/
template< typename CharT >
BOOST_LOG_SETUP_API void register_sink_factory(const char* sink_name, shared_ptr< sink_factory< CharT > > const& factory);
/*!
* \brief The function registers a factory for a custom sink
*
* The function registers a factory for a sink. The factory will be called to create sink
* instance when the parser discovers the specified sink type in the settings file. The
* factory must accept a map of parameters [parameter name -> parameter value] that it
* may use to initialize the sink. The factory must return a non-NULL pointer to the
* constructed sink instance.
*
* \param sink_name The custom sink name
* \param factory Pointer to the custom sink factory. Must not be NULL.
*/
template< typename CharT >
inline void register_sink_factory(std::string const& sink_name, shared_ptr< sink_factory< CharT > > const& factory)
{
register_sink_factory(sink_name.c_str(), factory);
}
/*!
* \brief The function registers a factory for a custom sink
*
* The function registers a factory for a sink. The factory will be called to create sink
* instance when the parser discovers the specified sink type in the settings file. The
* factory must accept a map of parameters [parameter name -> parameter value] that it
* may use to initialize the sink. The factory must return a non-NULL pointer to the
* constructed sink instance.
*
* \param sink_name The custom sink name. Must point to a zero-terminated sequence of characters,
* must not be NULL.
* \param factory Pointer to the custom sink factory. Must not be NULL.
*/
template< typename FactoryT >
inline typename boost::enable_if_c<
is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_sink_factory(const char* sink_name, shared_ptr< FactoryT > const& factory)
{
typedef sink_factory< typename FactoryT::char_type > factory_base;
register_sink_factory(sink_name, boost::static_pointer_cast< factory_base >(factory));
}
/*!
* \brief The function registers a factory for a custom sink
*
* The function registers a factory for a sink. The factory will be called to create sink
* instance when the parser discovers the specified sink type in the settings file. The
* factory must accept a map of parameters [parameter name -> parameter value] that it
* may use to initialize the sink. The factory must return a non-NULL pointer to the
* constructed sink instance.
*
* \param sink_name The custom sink name
* \param factory Pointer to the custom sink factory. Must not be NULL.
*/
template< typename FactoryT >
inline typename boost::enable_if_c<
is_base_and_derived< sink_factory< typename FactoryT::char_type >, FactoryT >::value
>::type register_sink_factory(std::string const& sink_name, shared_ptr< FactoryT > const& factory)
{
typedef sink_factory< typename FactoryT::char_type > factory_base;
register_sink_factory(sink_name.c_str(), boost::static_pointer_cast< factory_base >(factory));
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_FROM_SETTINGS_HPP_INCLUDED_
@@ -0,0 +1,47 @@
/*
* 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 from_stream.hpp
* \author Andrey Semashev
* \date 22.03.2008
*
* The header contains definition of facilities that allows to initialize the library from a
* settings file.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_
#include <iosfwd>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* The function initializes the logging library from a stream containing logging settings
*
* \param strm Stream, that provides library settings
*
* \b Throws: An <tt>std::exception</tt>-based exception if the read data cannot be interpreted as the library settings
*/
template< typename CharT >
BOOST_LOG_SETUP_API void init_from_stream(std::basic_istream< CharT >& strm);
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_FROM_STREAM_HPP_INCLUDED_
@@ -0,0 +1,643 @@
/*
* 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 settings.hpp
* \author Andrey Semashev
* \date 11.10.2009
*
* The header contains definition of the library settings container.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
#include <cstddef>
#include <string>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/move/core.hpp>
#include <boost/mpl/if.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/optional/optional.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/detail/native_typeof.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#if !defined(BOOST_LOG_TYPEOF)
#include <boost/core/enable_if.hpp>
#endif
#if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
#include <boost/utility/declval.hpp>
#endif
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
// This workaround is needed for MSVC 10 to work around ICE caused by stack overflow
template< typename SectionT, bool IsConstV >
struct basic_settings_section_iterator_base;
template< typename SectionT >
struct basic_settings_section_iterator_base< SectionT, true >
{
typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type;
typedef typename SectionT::property_tree_type::const_iterator base_iterator_type;
typedef iterator_adaptor<
iterator_type,
base_iterator_type,
SectionT,
use_default,
const SectionT
> type;
};
template< typename SectionT >
struct basic_settings_section_iterator_base< SectionT, false >
{
typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type;
typedef typename SectionT::property_tree_type::iterator base_iterator_type;
typedef iterator_adaptor<
iterator_type,
base_iterator_type,
SectionT,
use_default,
SectionT
> type;
};
} // namespace aux
/*!
* \brief The class represents a reference to the settings container section
*
* The section refers to a sub-tree of the library settings container. It does not
* own the referred sub-tree but allows for convenient access to parameters within the subsection.
*/
template< typename CharT >
class basic_settings_section
{
template< typename SectionT, bool IsConstV >
friend struct aux::basic_settings_section_iterator_base;
public:
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
//! Property tree type
typedef property_tree::basic_ptree< std::string, string_type > property_tree_type;
//! Property tree path type
typedef typename property_tree_type::path_type path_type;
private:
#if !defined(BOOST_LOG_DOXYGEN_PASS)
//! A reference proxy object
#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
template< bool IsConstV >
class ref;
template< bool IsConstV >
friend class ref;
#endif
template< bool IsConstV >
class ref
{
private:
typedef typename mpl::if_c<
IsConstV,
basic_settings_section< char_type > const,
basic_settings_section< char_type >
>::type section_type;
private:
section_type& m_section;
path_type m_path;
public:
ref(section_type& section, std::string const& section_name) :
m_section(section),
m_path(section_name)
{
}
ref(section_type& section, const char* section_name) :
m_section(section),
m_path(section_name)
{
}
ref& operator[] (std::string const& param_name)
{
m_path /= param_name;
return *this;
}
ref& operator= (string_type const& value)
{
BOOST_ASSERT(m_section.m_ptree != NULL);
m_section.m_ptree->put(m_path, value);
return *this;
}
template< bool V >
ref& operator= (ref< V > const& value)
{
BOOST_ASSERT(m_section.m_ptree != NULL);
optional< string_type > val = value.get();
if (!!val)
{
m_section.m_ptree->put(m_path, val);
}
else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path))
{
node.put_value(string_type());
}
return *this;
}
template< typename T >
ref& operator= (T const& value)
{
BOOST_ASSERT(m_section.m_ptree != NULL);
m_section.m_ptree->put(m_path, value);
return *this;
}
BOOST_EXPLICIT_OPERATOR_BOOL()
bool operator! () const
{
return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path);
}
std::string get_name() const
{
return m_path.dump();
}
operator optional< string_type > () const
{
return get();
}
optional< string_type > get() const
{
if (m_section.m_ptree)
return m_section.m_ptree->template get_optional< string_type >(m_path);
else
return optional< string_type >();
}
template< typename T >
optional< T > get() const
{
if (m_section.m_ptree)
return m_section.m_ptree->template get_optional< T >(m_path);
else
return optional< T >();
}
operator section_type () const
{
return get_section();
}
section_type get_section() const
{
if (m_section.m_ptree)
return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr());
else
return section_type();
}
#if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5))
#if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
template< typename T >
auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value))
{
if (m_section.m_ptree)
return m_section.m_ptree->get(m_path, def_value);
else
return def_value;
}
#else
// GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled
template< typename T >
BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const
{
if (m_section.m_ptree)
return m_section.m_ptree->get(m_path, def_value);
else
return def_value;
}
#endif
#else
template< typename T >
T or_default(T const& def_value) const
{
if (m_section.m_ptree)
return m_section.m_ptree->get(m_path, def_value);
else
return def_value;
}
template< typename T >
typename boost::enable_if_c< boost::property_tree::detail::is_character< T >::value, std::basic_string< T > >::type
or_default(const T* def_value) const
{
if (m_section.m_ptree)
return m_section.m_ptree->get(m_path, def_value);
else
return def_value;
}
#endif
string_type or_default(string_type const& def_value) const
{
return get().get_value_or(def_value);
}
string_type or_default(typename string_type::value_type const* def_value) const
{
if (optional< string_type > val = get())
return val.get();
else
return def_value;
}
};
//! An iterator over subsections and parameters
#ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
template< bool IsConstV >
class iter;
template< bool IsConstV >
friend class iter;
#endif
template< bool IsConstV >
class iter :
public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type
{
friend class boost::iterator_core_access;
typedef typename iter::iterator_adaptor_ iterator_adaptor_;
// NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE
typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type;
public:
typedef typename iterator_adaptor_::reference reference;
public:
BOOST_DEFAULTED_FUNCTION(iter(), {})
template< bool OtherIsConstV >
iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {}
explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {}
//! Returns the section name
std::string const& get_name() const
{
return this->base()->first;
}
private:
reference dereference() const
{
return reference(const_cast< property_tree_type* >(&this->base()->second));
}
};
public:
typedef ref< true > const_reference;
typedef ref< false > reference;
typedef iter< true > const_iterator;
typedef iter< false > iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
typedef std::reverse_iterator< iterator > reverse_iterator;
#else
public:
/*!
* Constant reference to the parameter value
*/
typedef implementation_defined const_reference;
/*!
* Mutable reference to the parameter value
*/
typedef implementation_defined reference;
/*!
* Constant iterator over nested parameters and subsections
*/
typedef implementation_defined const_iterator;
/*!
* Mutable iterator over nested parameters and subsections
*/
typedef implementation_defined iterator;
#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
protected:
//! Parameters
property_tree_type* m_ptree;
public:
/*!
* Default constructor. Creates an empty settings container.
*/
basic_settings_section() : m_ptree(NULL)
{
}
/*!
* Copy constructor.
*/
basic_settings_section(basic_settings_section const& that) : m_ptree(that.m_ptree)
{
}
/*!
* Checks if the section refers to the container.
*/
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
/*!
* Checks if the section refers to the container.
*/
bool operator! () const BOOST_NOEXCEPT { return !m_ptree; }
/*!
* Returns an iterator over the nested subsections and parameters.
*/
iterator begin()
{
if (m_ptree)
return iterator(m_ptree->begin());
else
return iterator();
}
/*!
* Returns an iterator over the nested subsections and parameters.
*/
iterator end()
{
if (m_ptree)
return iterator(m_ptree->end());
else
return iterator();
}
/*!
* Returns an iterator over the nested subsections and parameters.
*/
const_iterator begin() const
{
if (m_ptree)
return const_iterator(m_ptree->begin());
else
return const_iterator();
}
/*!
* Returns an iterator over the nested subsections and parameters.
*/
const_iterator end() const
{
if (m_ptree)
return const_iterator(m_ptree->end());
else
return const_iterator();
}
/*!
* Returns a reverse iterator over the nested subsections and parameters.
*/
reverse_iterator rbegin() { return reverse_iterator(begin()); }
/*!
* Returns a reverse iterator over the nested subsections and parameters.
*/
reverse_iterator rend() { return reverse_iterator(end()); }
/*!
* Returns a reverse iterator over the nested subsections and parameters.
*/
const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); }
/*!
* Returns a reverse iterator over the nested subsections and parameters.
*/
const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
/*!
* Checks if the container is empty (i.e. contains no sections and parameters).
*/
bool empty() const { return m_ptree == NULL || m_ptree->empty(); }
/*!
* Accessor to a single parameter. This operator should be used in conjunction
* with the subsequent subscript operator that designates the parameter name.
*
* \param section_name The name of the section in which the parameter resides
* \return An unspecified reference type that can be used for parameter name specifying
*/
reference operator[] (std::string const& section_name) { return reference(*this, section_name); }
/*!
* Accessor to a single parameter. This operator should be used in conjunction
* with the subsequent subscript operator that designates the parameter name.
*
* \param section_name The name of the section in which the parameter resides
* \return An unspecified reference type that can be used for parameter name specifying
*/
const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); }
/*!
* Accessor to a single parameter. This operator should be used in conjunction
* with the subsequent subscript operator that designates the parameter name.
*
* \param section_name The name of the section in which the parameter resides
* \return An unspecified reference type that can be used for parameter name specifying
*/
reference operator[] (const char* section_name) { return reference(*this, section_name); }
/*!
* Accessor to a single parameter. This operator should be used in conjunction
* with the subsequent subscript operator that designates the parameter name.
*
* \param section_name The name of the section in which the parameter resides
* \return An unspecified reference type that can be used for parameter name specifying
*/
const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); }
/*!
* Accessor for the embedded property tree
*/
property_tree_type const& property_tree() const { return *m_ptree; }
/*!
* Accessor for the embedded property tree
*/
property_tree_type& property_tree() { return *m_ptree; }
/*!
* Checks if the specified section is present in the container.
*
* \param section_name The name of the section
*/
bool has_section(string_type const& section_name) const
{
return m_ptree != NULL && !!m_ptree->get_child_optional(section_name);
}
/*!
* Checks if the specified parameter is present in the container.
*
* \param section_name The name of the section in which the parameter resides
* \param param_name The name of the parameter
*/
bool has_parameter(string_type const& section_name, string_type const& param_name) const
{
if (m_ptree)
{
optional< property_tree_type& > section = m_ptree->get_child_optional(section_name);
if (!!section)
return (section->find(param_name) != section->not_found());
}
return false;
}
/*!
* Swaps two references to settings sections.
*/
void swap(basic_settings_section& that)
{
property_tree_type* const p = m_ptree;
m_ptree = that.m_ptree;
that.m_ptree = p;
}
protected:
explicit basic_settings_section(property_tree_type* tree) : m_ptree(tree)
{
}
};
template< typename CharT >
inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right)
{
left.swap(right);
}
/*!
* \brief The class represents settings container
*
* All settings are presented as a number of named parameters divided into named sections.
* The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this:
*
* <code><pre>
* optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1"
* // returns an empty value if no such parameter exists
* settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2"
* // to value "10"
* </pre></code>
*
* There are also other methods to work with parameters.
*/
template< typename CharT >
class basic_settings :
public basic_settings_section< CharT >
{
typedef basic_settings this_type;
BOOST_COPYABLE_AND_MOVABLE(this_type)
public:
//! Section type
typedef basic_settings_section< CharT > section;
//! Property tree type
typedef typename section::property_tree_type property_tree_type;
public:
/*!
* Default constructor. Creates an empty settings container.
*/
basic_settings() : section(new property_tree_type())
{
}
/*!
* Copy constructor.
*/
basic_settings(basic_settings const& that) :
section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL))
{
}
/*!
* Move constructor.
*/
basic_settings(BOOST_RV_REF(this_type) that)
{
this->swap(that);
}
/*!
* Initializing constructor. Creates a settings container with the copy of the specified property tree.
*/
explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree))
{
}
/*!
* Destructor
*/
~basic_settings()
{
delete this->m_ptree;
}
/*!
* Copy assignment operator.
*/
basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that)
{
if (this != &that)
{
basic_settings tmp = that;
this->swap(tmp);
}
return *this;
}
/*!
* Move assignment operator.
*/
basic_settings& operator= (BOOST_RV_REF(basic_settings) that)
{
this->swap(that);
return *this;
}
};
#ifdef BOOST_LOG_USE_CHAR
typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging
typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging
typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging
#endif
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
@@ -0,0 +1,47 @@
/*
* 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 settings_parser.hpp
* \author Andrey Semashev
* \date 20.07.2012
*
* The header contains definition of a settings parser function.
*/
#ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_
#include <iosfwd>
#include <boost/log/detail/setup_config.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* The function parses library settings from an input stream
*
* \param strm Stream, that provides library settings
*
* \b Throws: An <tt>std::exception</tt>-based exception if the read data cannot be interpreted as the library settings
*/
template< typename CharT >
BOOST_LOG_SETUP_API basic_settings< CharT > parse_settings(std::basic_istream< CharT >& strm);
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_PARSER_HPP_INCLUDED_
@@ -0,0 +1,219 @@
/*
* 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 utility/strictest_lock.hpp
* \author Andrey Semashev
* \date 30.05.2010
*
* The header contains definition of the \c strictest_lock metafunction that
* allows to select a lock with the strictest access requirements.
*/
#ifndef BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
#include <boost/mpl/integral_c.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/log/detail/pp_identity.hpp>
#endif
#if defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS)
#include <boost/mpl/less.hpp>
#endif
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if !defined(BOOST_LOG_STRICTEST_LOCK_LIMIT)
/*!
* The macro defines the maximum number of template arguments that the \c strictest_lock
* metafunction accepts. Should not be less than 2.
*/
#define BOOST_LOG_STRICTEST_LOCK_LIMIT 10
#endif // BOOST_LOG_STRICTEST_LOCK_LIMIT
#if BOOST_LOG_STRICTEST_LOCK_LIMIT < 2
#error The BOOST_LOG_STRICTEST_LOCK_LIMIT macro should not be less than 2
#endif
#endif // defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! Access modes for different types of locks
enum lock_access_mode
{
unlocked_access, //!< A thread that owns this kind of lock doesn't restrict other threads in any way
shared_access, //!< A thread that owns this kind of lock requires that no other thread modify the locked data
exclusive_access //!< A thread that owns this kind of lock requires that no other thread has access to the locked data
};
//! The trait allows to select an access mode by the lock type
template< typename LockT >
struct thread_access_mode_of;
template< typename MutexT >
struct thread_access_mode_of< no_lock< MutexT > > : mpl::integral_c< lock_access_mode, unlocked_access >
{
};
#if !defined(BOOST_LOG_NO_THREADS)
template< typename MutexT >
struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
{
};
template< typename MutexT >
struct thread_access_mode_of< shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
{
};
template< typename MutexT >
struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
{
};
template< typename MutexT >
struct thread_access_mode_of< shared_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
{
};
template< typename MutexT >
struct thread_access_mode_of< upgrade_lock< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
{
};
template< typename MutexT >
struct thread_access_mode_of< boost::log::aux::exclusive_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access >
{
};
template< typename MutexT >
struct thread_access_mode_of< boost::log::aux::shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access >
{
};
#endif // !defined(BOOST_LOG_NO_THREADS)
namespace aux {
//! The metafunction selects the most strict lock type of the two
template<
typename LeftLockT,
typename RightLockT,
#if !defined(BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS)
bool CondV = (thread_access_mode_of< LeftLockT >::value < thread_access_mode_of< RightLockT >::value)
#else
bool CondV = mpl::less< thread_access_mode_of< LeftLockT >, thread_access_mode_of< RightLockT > >::value
#endif
>
struct strictest_lock_impl
{
typedef RightLockT type;
};
template< typename LeftLockT, typename RightLockT >
struct strictest_lock_impl< LeftLockT, RightLockT, false >
{
typedef LeftLockT type;
};
} // namespace aux
#if defined(BOOST_LOG_DOXYGEN_PASS)
/*!
* \brief The metafunction selects the most strict lock type of the specified.
*
* The template supports all lock types provided by the Boost.Thread
* library (except for \c upgrade_to_unique_lock), plus additional
* pseudo-lock \c no_lock that indicates no locking at all.
* Exclusive locks are considered the strictest, shared locks are weaker,
* and \c no_lock is the weakest.
*/
template< typename... LocksT >
struct strictest_lock
{
typedef implementation_defined type;
};
#else // defined(BOOST_LOG_DOXYGEN_PASS)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template< typename LockT, typename... LocksT >
struct strictest_lock;
template< typename LockT >
struct strictest_lock< LockT >
{
typedef LockT type;
};
template< typename LeftLockT, typename RightLockT >
struct strictest_lock< LeftLockT, RightLockT >
{
typedef typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type type;
};
template< typename LeftLockT, typename RightLockT, typename... LocksT >
struct strictest_lock< LeftLockT, RightLockT, LocksT... >
{
typedef typename strictest_lock<
typename aux::strictest_lock_impl< LeftLockT, RightLockT >::type,
LocksT...
>::type type;
};
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
# define BOOST_LOG_TYPE_INTERNAL(z, i, data) BOOST_PP_CAT(T, BOOST_PP_INC(i))
template<
typename T,
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), typename T, void)
>
struct strictest_lock
{
typedef typename strictest_lock<
typename boost::log::aux::strictest_lock_impl< T, T0 >::type
BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_LOG_STRICTEST_LOCK_LIMIT, 2), BOOST_LOG_TYPE_INTERNAL, ~)
>::type type;
};
template< typename T >
struct strictest_lock<
T
BOOST_PP_ENUM_TRAILING(BOOST_PP_DEC(BOOST_LOG_STRICTEST_LOCK_LIMIT), BOOST_LOG_PP_IDENTITY, void)
>
{
typedef T type;
};
# undef BOOST_LOG_TYPE_INTERNAL
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif // defined(BOOST_LOG_DOXYGEN_PASS)
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_STRICTEST_LOCK_HPP_INCLUDED_
@@ -0,0 +1,711 @@
/*
* Copyright Andrey Semashev 2007 - 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file string_literal.hpp
* \author Andrey Semashev
* \date 24.06.2007
*
* The header contains implementation of a constant string literal wrapper.
*/
#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
#include <cstddef>
#include <stdexcept>
#include <iosfwd>
#include <ios> // std::streamsize
#include <string>
#include <iterator>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/string_literal_fwd.hpp>
#include <boost/log/detail/sfinae_tools.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief String literal wrapper
*
* The \c basic_string_literal is a thin wrapper around a constant string literal.
* It provides interface similar to STL strings, but because of read-only nature
* of string literals, lacks ability to modify string contents. However,
* \c basic_string_literal objects can be assigned to and cleared.
*
* The main advantage of this class comparing to other string classes is that
* it doesn't dynamically allocate memory and therefore is fast, thin and exception safe.
*/
template< typename CharT, typename TraitsT >
class basic_string_literal
{
//! Self type
typedef basic_string_literal< CharT, TraitsT > this_type;
public:
typedef CharT value_type;
typedef TraitsT traits_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type* const_pointer;
typedef value_type const& const_reference;
typedef const value_type* const_iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
//! Corresponding STL string type
typedef std::basic_string< value_type, traits_type > string_type;
private:
//! Pointer to the beginning of the literal
const_pointer m_pStart;
//! Length
size_type m_Len;
//! Empty string literal to support \c clear
#if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS)
static constexpr value_type g_EmptyString[1] = { 0 };
#else
static const value_type g_EmptyString[1];
#endif
public:
/*!
* Constructor
*
* \post <tt>empty() == true</tt>
*/
BOOST_CONSTEXPR basic_string_literal() BOOST_NOEXCEPT : m_pStart(g_EmptyString), m_Len(0) { }
/*!
* Constructor from a string literal
*
* \post <tt>*this == p</tt>
* \param p A zero-terminated constant sequence of characters
*/
template< typename T, size_type LenV >
BOOST_CONSTEXPR basic_string_literal(T(&p)[LenV]
//! \cond
, typename boost::enable_if_c< is_same< T, const value_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
//! \endcond
) BOOST_NOEXCEPT
: m_pStart(p), m_Len(LenV - 1)
{
}
/*!
* Copy constructor
*
* \post <tt>*this == that</tt>
* \param that Source literal to copy string from
*/
BOOST_CONSTEXPR basic_string_literal(basic_string_literal const& that) BOOST_NOEXCEPT : m_pStart(that.m_pStart), m_Len(that.m_Len) {}
/*!
* Assignment operator
*
* \post <tt>*this == that</tt>
* \param that Source literal to copy string from
*/
BOOST_CXX14_CONSTEXPR this_type& operator= (this_type const& that) BOOST_NOEXCEPT
{
return assign(that);
}
/*!
* Assignment from a string literal
*
* \post <tt>*this == p</tt>
* \param p A zero-terminated constant sequence of characters
*/
template< typename T, size_type LenV >
BOOST_CXX14_CONSTEXPR
#ifndef BOOST_LOG_DOXYGEN_PASS
typename boost::enable_if_c<
is_same< T, const value_type >::value,
this_type&
>::type
#else
this_type&
#endif // BOOST_LOG_DOXYGEN_PASS
operator= (T(&p)[LenV]) BOOST_NOEXCEPT
{
return assign(p);
}
/*!
* Lexicographical comparison (equality)
*
* \param that Comparand
* \return \c true if the comparand string equals to this string, \c false otherwise
*/
bool operator== (this_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) == 0);
}
/*!
* Lexicographical comparison (equality)
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return \c true if the comparand string equals to this string, \c false otherwise
*/
bool operator== (const_pointer str) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) == 0);
}
/*!
* Lexicographical comparison (equality)
*
* \param that Comparand
* \return \c true if the comparand string equals to this string, \c false otherwise
*/
bool operator== (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) == 0);
}
/*!
* Lexicographical comparison (inequality)
*
* \param that Comparand
* \return \c true if the comparand string is not equal to this string, \c false otherwise
*/
bool operator!= (this_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) != 0);
}
/*!
* Lexicographical comparison (inequality)
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return \c true if the comparand string is not equal to this string, \c false otherwise
*/
bool operator!= (const_pointer str) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) != 0);
}
/*!
* Lexicographical comparison (inequality)
*
* \param that Comparand
* \return \c true if the comparand string is not equal to this string, \c false otherwise
*/
bool operator!= (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) != 0);
}
/*!
* Lexicographical comparison (less ordering)
*
* \param that Comparand
* \return \c true if this string is less than the comparand, \c false otherwise
*/
bool operator< (this_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) < 0);
}
/*!
* Lexicographical comparison (less ordering)
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return \c true if this string is less than the comparand, \c false otherwise
*/
bool operator< (const_pointer str) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) < 0);
}
/*!
* Lexicographical comparison (less ordering)
*
* \param that Comparand
* \return \c true if this string is less than the comparand, \c false otherwise
*/
bool operator< (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) < 0);
}
/*!
* Lexicographical comparison (less or equal ordering)
*
* \param that Comparand
* \return \c true if this string is less or equal to the comparand, \c false otherwise
*/
bool operator<= (this_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) <= 0);
}
/*!
* Lexicographical comparison (less or equal ordering)
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return \c true if this string is less or equal to the comparand, \c false otherwise
*/
bool operator<= (const_pointer str) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) <= 0);
}
/*!
* Lexicographical comparison (less or equal ordering)
*
* \param that Comparand
* \return \c true if this string is less or equal to the comparand, \c false otherwise
*/
bool operator<= (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) <= 0);
}
/*!
* Lexicographical comparison (greater ordering)
*
* \param that Comparand
* \return \c true if this string is greater than the comparand, \c false otherwise
*/
bool operator> (this_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) > 0);
}
/*!
* Lexicographical comparison (greater ordering)
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return \c true if this string is greater than the comparand, \c false otherwise
*/
bool operator> (const_pointer str) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) > 0);
}
/*!
* Lexicographical comparison (greater ordering)
*
* \param that Comparand
* \return \c true if this string is greater than the comparand, \c false otherwise
*/
bool operator> (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) > 0);
}
/*!
* Lexicographical comparison (greater or equal ordering)
*
* \param that Comparand
* \return \c true if this string is greater or equal to the comparand, \c false otherwise
*/
bool operator>= (this_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.m_pStart, that.m_Len) >= 0);
}
/*!
* Lexicographical comparison (greater or qual ordering)
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return \c true if this string is greater or equal to the comparand, \c false otherwise
*/
bool operator>= (const_pointer str) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, str, traits_type::length(str)) >= 0);
}
/*!
* Lexicographical comparison (greater or equal ordering)
*
* \param that Comparand
* \return \c true if this string is greater or equal to the comparand, \c false otherwise
*/
bool operator>= (string_type const& that) const BOOST_NOEXCEPT
{
return (compare_internal(m_pStart, m_Len, that.c_str(), that.size()) >= 0);
}
/*!
* Subscript operator
*
* \pre <tt>i < size()</tt>
* \param i Requested character index
* \return Constant reference to the requested character
*/
BOOST_CONSTEXPR const_reference operator[] (size_type i) const BOOST_NOEXCEPT
{
return m_pStart[i];
}
/*!
* Checked subscript
*
* \param i Requested character index
* \return Constant reference to the requested character
*
* \b Throws: An <tt>std::exception</tt>-based exception if index \a i is out of string boundaries
*/
const_reference at(size_type i) const
{
if (BOOST_UNLIKELY(i >= m_Len))
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::at: the index value is out of range"));
return m_pStart[i];
}
/*!
* \return Pointer to the beginning of the literal
*/
BOOST_CONSTEXPR const_pointer c_str() const BOOST_NOEXCEPT { return m_pStart; }
/*!
* \return Pointer to the beginning of the literal
*/
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return m_pStart; }
/*!
* \return Length of the literal
*/
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return m_Len; }
/*!
* \return Length of the literal
*/
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return m_Len; }
/*!
* \return \c true if the literal is an empty string, \c false otherwise
*/
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
{
return (m_Len == 0);
}
/*!
* \return Iterator that points to the first character of the literal
*/
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return m_pStart; }
/*!
* \return Iterator that points after the last character of the literal
*/
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return m_pStart + m_Len; }
/*!
* \return Reverse iterator that points to the last character of the literal
*/
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
/*!
* \return Reverse iterator that points before the first character of the literal
*/
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
/*!
* \return STL string constructed from the literal
*/
string_type str() const
{
return string_type(m_pStart, m_Len);
}
/*!
* The method clears the literal
*
* \post <tt>empty() == true</tt>
*/
BOOST_CXX14_CONSTEXPR void clear() BOOST_NOEXCEPT
{
m_pStart = g_EmptyString;
m_Len = 0;
}
/*!
* The method swaps two literals
*/
BOOST_CXX14_CONSTEXPR void swap(this_type& that) BOOST_NOEXCEPT
{
const_pointer p = m_pStart;
m_pStart = that.m_pStart;
that.m_pStart = p;
size_type l = m_Len;
m_Len = that.m_Len;
that.m_Len = l;
}
/*!
* Assignment from another literal
*
* \post <tt>*this == that</tt>
* \param that Source literal to copy string from
*/
BOOST_CXX14_CONSTEXPR this_type& assign(this_type const& that) BOOST_NOEXCEPT
{
m_pStart = that.m_pStart;
m_Len = that.m_Len;
return *this;
}
/*!
* Assignment from another literal
*
* \post <tt>*this == p</tt>
* \param p A zero-terminated constant sequence of characters
*/
template< typename T, size_type LenV >
BOOST_CXX14_CONSTEXPR
#ifndef BOOST_LOG_DOXYGEN_PASS
typename boost::enable_if_c<
is_same< T, const value_type >::value,
this_type&
>::type
#else
this_type&
#endif // BOOST_LOG_DOXYGEN_PASS
assign(T(&p)[LenV]) BOOST_NOEXCEPT
{
m_pStart = p;
m_Len = LenV - 1;
return *this;
}
/*!
* The method copies the literal or its portion to an external buffer
*
* \pre <tt>pos <= size()</tt>
* \param str Pointer to the external buffer beginning. Must not be NULL.
* The buffer must have enough capacity to accommodate the requested number of characters.
* \param n Maximum number of characters to copy
* \param pos Starting position to start copying from
* \return Number of characters copied
*
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
*/
size_type copy(value_type* str, size_type n, size_type pos = 0) const
{
if (BOOST_UNLIKELY(pos > m_Len))
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::copy: the position is out of range"));
size_type len = m_Len - pos;
if (len > n)
len = n;
traits_type::copy(str, m_pStart + pos, len);
return len;
}
/*!
* Lexicographically compares the argument string to a part of this string
*
* \pre <tt>pos <= size()</tt>
* \param pos Starting position within this string to perform comparison to
* \param n Length of the substring of this string to perform comparison to
* \param str Comparand. Must point to a sequence of characters, must not be NULL.
* \param len Number of characters in the sequence \a str.
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
* a positive value if this string is greater than the comparand.
*
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
*/
int compare(size_type pos, size_type n, const_pointer str, size_type len) const
{
if (BOOST_UNLIKELY(pos > m_Len))
BOOST_THROW_EXCEPTION(std::out_of_range("basic_string_literal::compare: the position is out of range"));
size_type compare_size = m_Len - pos;
if (compare_size > len)
compare_size = len;
if (compare_size > n)
compare_size = n;
return compare_internal(m_pStart + pos, compare_size, str, compare_size);
}
/*!
* Lexicographically compares the argument string to a part of this string
*
* \pre <tt>pos <= size()</tt>
* \param pos Starting position within this string to perform comparison to
* \param n Length of the substring of this string to perform comparison to
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
* a positive value if this string is greater than the comparand.
*
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
*/
int compare(size_type pos, size_type n, const_pointer str) const BOOST_NOEXCEPT
{
return compare(pos, n, str, traits_type::length(str));
}
/*!
* Lexicographically compares the argument string literal to a part of this string
*
* \pre <tt>pos <= size()</tt>
* \param pos Starting position within this string to perform comparison to
* \param n Length of the substring of this string to perform comparison to
* \param that Comparand
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
* a positive value if this string is greater than the comparand.
*
* \b Throws: An <tt>std::exception</tt>-based exception if \a pos is out of range.
*/
int compare(size_type pos, size_type n, this_type const& that) const BOOST_NOEXCEPT
{
return compare(pos, n, that.c_str(), that.size());
}
/*!
* Lexicographically compares the argument string to this string
*
* \param str Comparand. Must point to a sequence of characters, must not be NULL.
* \param len Number of characters in the sequence \a str.
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
* a positive value if this string is greater than the comparand.
*/
int compare(const_pointer str, size_type len) const BOOST_NOEXCEPT
{
return compare(0, m_Len, str, len);
}
/*!
* Lexicographically compares the argument string to this string
*
* \param str Comparand. Must point to a zero-terminated sequence of characters, must not be NULL.
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
* a positive value if this string is greater than the comparand.
*/
int compare(const_pointer str) const BOOST_NOEXCEPT
{
return compare(0, m_Len, str, traits_type::length(str));
}
/*!
* Lexicographically compares the argument string to this string
*
* \param that Comparand
* \return Zero if the comparand equals this string, a negative value if this string is less than the comparand,
* a positive value if this string is greater than the comparand.
*/
int compare(this_type const& that) const BOOST_NOEXCEPT
{
return compare(0, m_Len, that.c_str(), that.size());
}
private:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Internal comparison implementation
static int compare_internal(const_pointer pLeft, size_type LeftLen, const_pointer pRight, size_type RightLen) BOOST_NOEXCEPT
{
if (pLeft != pRight)
{
const int result = traits_type::compare(pLeft, pRight, (LeftLen < RightLen ? LeftLen : RightLen));
if (result != 0)
return result;
}
return LeftLen < RightLen ? -1 : (LeftLen > RightLen ? 1 : 0);
}
#endif // BOOST_LOG_DOXYGEN_PASS
};
#if !defined(BOOST_LOG_NO_CXX11_CONSTEXPR_DATA_MEMBER_BRACE_INITIALIZERS)
template< typename CharT, typename TraitsT >
constexpr typename basic_string_literal< CharT, TraitsT >::value_type
basic_string_literal< CharT, TraitsT >::g_EmptyString[1];
#else
template< typename CharT, typename TraitsT >
const typename basic_string_literal< CharT, TraitsT >::value_type
basic_string_literal< CharT, TraitsT >::g_EmptyString[1] = { 0 };
#endif
namespace aux {
template< typename CharT, typename TraitsT >
inline void insert_fill_chars(std::basic_ostream< CharT, TraitsT >& strm, std::size_t n)
{
enum { chunk_size = 8 };
CharT fill_chars[chunk_size];
const CharT filler = strm.fill();
for (unsigned int i = 0; i < chunk_size; ++i)
fill_chars[i] = filler;
for (; n >= chunk_size && strm.good(); n -= chunk_size)
strm.write(fill_chars, static_cast< std::size_t >(chunk_size));
if (n > 0 && strm.good())
strm.write(fill_chars, n);
}
template< typename CharT, typename TraitsT >
void insert_aligned(std::basic_ostream< CharT, TraitsT >& strm, const CharT* p, std::size_t size)
{
const std::size_t alignment_size = static_cast< std::size_t >(strm.width()) - size;
const bool align_left = (strm.flags() & std::basic_ostream< CharT, TraitsT >::adjustfield) == std::basic_ostream< CharT, TraitsT >::left;
if (align_left)
{
strm.write(p, size);
if (strm.good())
aux::insert_fill_chars(strm, alignment_size);
}
else
{
aux::insert_fill_chars(strm, alignment_size);
if (strm.good())
strm.write(p, size);
}
}
} // namespace aux
//! Output operator
template< typename CharT, typename StrmTraitsT, typename LitTraitsT >
inline std::basic_ostream< CharT, StrmTraitsT >& operator<< (
std::basic_ostream< CharT, StrmTraitsT >& strm, basic_string_literal< CharT, LitTraitsT > const& lit)
{
if (strm.good())
{
const std::size_t size = lit.size();
const std::size_t w = static_cast< std::size_t >(strm.width());
if (w <= size)
strm.write(lit.c_str(), static_cast< std::streamsize >(size));
else
aux::insert_aligned(strm, lit.c_str(), lit.size());
strm.width(0);
}
return strm;
}
//! External swap
template< typename CharT, typename TraitsT >
inline BOOST_CXX14_CONSTEXPR void swap(basic_string_literal< CharT, TraitsT >& left, basic_string_literal< CharT, TraitsT >& right) BOOST_NOEXCEPT
{
left.swap(right);
}
//! Creates a string literal wrapper from a constant string literal
#ifdef BOOST_LOG_USE_CHAR
template< typename T, std::size_t LenV >
inline BOOST_CONSTEXPR
#ifndef BOOST_LOG_DOXYGEN_PASS
typename boost::enable_if_c<
is_same< T, const char >::value,
string_literal
>::type
#else
basic_string_literal< T >
#endif // BOOST_LOG_DOXYGEN_PASS
str_literal(T(&p)[LenV]) BOOST_NOEXCEPT
{
return string_literal(p);
}
#endif
#ifndef BOOST_LOG_DOXYGEN_PASS
#ifdef BOOST_LOG_USE_WCHAR_T
template< typename T, std::size_t LenV >
inline BOOST_CONSTEXPR typename boost::enable_if_c<
is_same< T, const wchar_t >::value,
wstring_literal
>::type
str_literal(T(&p)[LenV]) BOOST_NOEXCEPT
{
return wstring_literal(p);
}
#endif
#endif // BOOST_LOG_DOXYGEN_PASS
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_STRING_LITERAL_HPP_INCLUDED_
@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file string_literal_fwd.hpp
* \author Andrey Semashev
* \date 24.06.2007
*
* The header contains forward declaration of a constant string literal wrapper.
*/
#ifndef BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_
#include <string>
#include <boost/log/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief String literal wrapper
*
* The \c basic_string_literal is a thin wrapper around a constant string literal.
* It provides interface similar to STL strings, but because of read-only nature
* of string literals, lacks ability to modify string contents. However,
* \c basic_string_literal objects can be assigned to and cleared.
*
* The main advantage of this class comparing to other string classes is that
* it doesn't dynamically allocate memory and therefore is fast, thin and exception safe.
*/
template< typename CharT, typename TraitsT = std::char_traits< CharT > >
class basic_string_literal;
// Convenience typedefs
#ifdef BOOST_LOG_USE_CHAR
typedef basic_string_literal< char > string_literal; //!< String literal type for narrow characters
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
typedef basic_string_literal< wchar_t > wstring_literal; //!< String literal type for wide characters
#endif
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#endif // BOOST_LOG_UTILITY_STRING_LITERAL_FWD_HPP_INCLUDED_
@@ -0,0 +1,174 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file date_time_types.hpp
* \author Andrey Semashev
* \date 13.03.2008
*
* The header contains definition of date and time-related types supported by the library by default.
*/
#ifndef BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_
#define BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_
#include <ctime>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/local_time/local_time_types.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! Boost.Preprocessor sequence of the standard C date/time types
#define BOOST_LOG_NATIVE_DATE_TIME_TYPES()\
(std::time_t)(std::tm)
//! Boost.Preprocessor sequence of the standard C date types
#define BOOST_LOG_NATIVE_DATE_TYPES()\
BOOST_LOG_NATIVE_DATE_TIME_TYPES()
//! Boost.Preprocessor sequence of the Boost date/time types
#define BOOST_LOG_BOOST_DATE_TIME_TYPES()\
(boost::posix_time::ptime)(boost::local_time::local_date_time)
//! Boost.Preprocessor sequence of date/time types
#define BOOST_LOG_DATE_TIME_TYPES()\
BOOST_LOG_NATIVE_DATE_TIME_TYPES()BOOST_LOG_BOOST_DATE_TIME_TYPES()\
//! Boost.Preprocessor sequence of the Boost date types
#define BOOST_LOG_BOOST_DATE_TYPES()\
BOOST_LOG_BOOST_DATE_TIME_TYPES()(boost::gregorian::date)
//! Boost.Preprocessor sequence of date types
#define BOOST_LOG_DATE_TYPES()\
BOOST_LOG_NATIVE_DATE_TYPES()BOOST_LOG_BOOST_DATE_TYPES()
//! Boost.Preprocessor sequence of the standard time duration types
#define BOOST_LOG_NATIVE_TIME_DURATION_TYPES()\
(double) /* result of difftime() */
//! Boost.Preprocessor sequence of the Boost time duration types
#define BOOST_LOG_BOOST_TIME_DURATION_TYPES()\
(boost::posix_time::time_duration)(boost::gregorian::date_duration)
//! Boost.Preprocessor sequence of time duration types
#define BOOST_LOG_TIME_DURATION_TYPES()\
BOOST_LOG_NATIVE_TIME_DURATION_TYPES()BOOST_LOG_BOOST_TIME_DURATION_TYPES()
//! Boost.Preprocessor sequence of the Boost time period types
#define BOOST_LOG_BOOST_TIME_PERIOD_TYPES()\
(boost::posix_time::time_period)(boost::local_time::local_time_period)(boost::gregorian::date_period)
//! Boost.Preprocessor sequence of time period types
#define BOOST_LOG_TIME_PERIOD_TYPES()\
BOOST_LOG_BOOST_TIME_PERIOD_TYPES()
/*!
* An MPL-sequence of natively supported date and time types of attributes
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_NATIVE_DATE_TIME_TYPES())
> native_date_time_types;
/*!
* An MPL-sequence of Boost date and time types of attributes
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_DATE_TIME_TYPES())
> boost_date_time_types;
/*!
* An MPL-sequence with the complete list of the supported date and time types
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_DATE_TIME_TYPES())
> date_time_types;
/*!
* An MPL-sequence of natively supported date types of attributes
*/
typedef native_date_time_types native_date_types;
/*!
* An MPL-sequence of Boost date types of attributes
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_DATE_TYPES())
> boost_date_types;
/*!
* An MPL-sequence with the complete list of the supported date types
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_DATE_TYPES())
> date_types;
/*!
* An MPL-sequence of natively supported time types
*/
typedef native_date_time_types native_time_types;
//! An MPL-sequence of Boost time types
typedef boost_date_time_types boost_time_types;
/*!
* An MPL-sequence with the complete list of the supported time types
*/
typedef date_time_types time_types;
/*!
* An MPL-sequence of natively supported time duration types of attributes
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_NATIVE_TIME_DURATION_TYPES())
> native_time_duration_types;
/*!
* An MPL-sequence of Boost time duration types of attributes
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_TIME_DURATION_TYPES())
> boost_time_duration_types;
/*!
* An MPL-sequence with the complete list of the supported time duration types
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_TIME_DURATION_TYPES())
> time_duration_types;
/*!
* An MPL-sequence of Boost time duration types of attributes
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_TIME_PERIOD_TYPES())
> boost_time_period_types;
/*!
* An MPL-sequence with the complete list of the supported time period types
*/
typedef boost_time_period_types time_period_types;
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DATE_TIME_TYPES_HPP_INCLUDED_
@@ -0,0 +1,152 @@
/*
* 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 dynamic_type_dispatcher.hpp
* \author Andrey Semashev
* \date 15.04.2007
*
* The header contains implementation of the run-time type dispatcher.
*/
#ifndef BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
#define BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
#include <new>
#include <memory>
#include <map>
#include <boost/ref.hpp>
#include <boost/type_index.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief A dynamic type dispatcher
*
* The type dispatcher can be used to pass objects of arbitrary types from one
* component to another. With regard to the library, the type dispatcher
* can be used to extract attribute values.
*
* The dynamic type dispatcher can be initialized in run time and, therefore,
* can support different types, depending on runtime conditions. Each
* supported type is associated with a functional object that will be called
* when an object of the type is dispatched.
*/
class dynamic_type_dispatcher :
public type_dispatcher
{
private:
#ifndef BOOST_LOG_DOXYGEN_PASS
template< typename T, typename VisitorT >
class callback_impl :
public callback_base
{
private:
VisitorT m_Visitor;
public:
explicit callback_impl(VisitorT const& visitor) : m_Visitor(visitor)
{
this->m_pVisitor = (void*)boost::addressof(m_Visitor);
typedef void (*trampoline_t)(void*, T const&);
BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
union
{
void* as_pvoid;
trampoline_t as_trampoline;
}
caster;
caster.as_trampoline = (trampoline_t)&callback_base::trampoline< VisitorT, T >;
this->m_pTrampoline = caster.as_pvoid;
}
};
#endif // BOOST_LOG_DOXYGEN_PASS
//! The dispatching map
typedef std::map< typeindex::type_index, shared_ptr< callback_base > > dispatching_map;
dispatching_map m_DispatchingMap;
public:
/*!
* Default constructor
*/
dynamic_type_dispatcher() : type_dispatcher(&dynamic_type_dispatcher::get_callback)
{
}
/*!
* Copy constructor
*/
dynamic_type_dispatcher(dynamic_type_dispatcher const& that) :
type_dispatcher(static_cast< type_dispatcher const& >(that)),
m_DispatchingMap(that.m_DispatchingMap)
{
}
/*!
* Copy assignment
*/
dynamic_type_dispatcher& operator= (dynamic_type_dispatcher const& that)
{
m_DispatchingMap = that.m_DispatchingMap;
return *this;
}
/*!
* The method registers a new type
*
* \param visitor Function object that will be associated with the type \c T
*/
template< typename T, typename VisitorT >
void register_type(VisitorT const& visitor)
{
boost::shared_ptr< callback_base > p(
boost::make_shared< callback_impl< T, VisitorT > >(boost::cref(visitor)));
typeindex::type_index wrapper(typeindex::type_id< T >());
m_DispatchingMap[wrapper].swap(p);
}
/*!
* The method returns the number of registered types
*/
dispatching_map::size_type registered_types_count() const
{
return m_DispatchingMap.size();
}
private:
#ifndef BOOST_LOG_DOXYGEN_PASS
static callback_base get_callback(type_dispatcher* p, typeindex::type_index type)
{
dynamic_type_dispatcher* const self = static_cast< dynamic_type_dispatcher* >(p);
dispatching_map::iterator it = self->m_DispatchingMap.find(type);
if (it != self->m_DispatchingMap.end())
return *it->second;
else
return callback_base();
}
#endif // BOOST_LOG_DOXYGEN_PASS
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DYNAMIC_TYPE_DISPATCHER_HPP_INCLUDED_
@@ -0,0 +1,145 @@
/*
* 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 standard_types.hpp
* \author Andrey Semashev
* \date 19.05.2007
*
* The header contains definition of standard types supported by the library by default.
*/
#ifndef BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_
#define BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_
#include <string>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector/vector30.hpp> // needed to use mpl::vector sizes greater than 20 even when the default BOOST_MPL_LIMIT_VECTOR_SIZE is not set
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/string_literal_fwd.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
#define BOOST_LOG_AUX_STANDARD_TYPE_WCHAR_T() (wchar_t)
#else
#define BOOST_LOG_AUX_STANDARD_TYPE_WCHAR_T()
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR16_T() (char16_t)
#else
#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR16_T()
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR32_T() (char32_t)
#else
#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR32_T()
#endif
//! Boost.Preprocessor sequence of character types
#define BOOST_LOG_STANDARD_CHAR_TYPES()\
(char)BOOST_LOG_AUX_STANDARD_TYPE_WCHAR_T()BOOST_LOG_AUX_STANDARD_TYPE_CHAR16_T()BOOST_LOG_AUX_STANDARD_TYPE_CHAR32_T()
#if defined(BOOST_HAS_LONG_LONG)
#define BOOST_LOG_AUX_STANDARD_LONG_LONG_TYPES() (long long)(unsigned long long)
#else
#define BOOST_LOG_AUX_STANDARD_LONG_LONG_TYPES()
#endif
//! Boost.Preprocessor sequence of integral types
#define BOOST_LOG_STANDARD_INTEGRAL_TYPES()\
(bool)(signed char)(unsigned char)(short)(unsigned short)(int)(unsigned int)(long)(unsigned long)BOOST_LOG_AUX_STANDARD_LONG_LONG_TYPES()\
BOOST_LOG_STANDARD_CHAR_TYPES()
//! Boost.Preprocessor sequence of floating point types
#define BOOST_LOG_STANDARD_FLOATING_POINT_TYPES()\
(float)(double)(long double)
//! Boost.Preprocessor sequence of arithmetic types
#define BOOST_LOG_STANDARD_ARITHMETIC_TYPES()\
BOOST_LOG_STANDARD_INTEGRAL_TYPES()BOOST_LOG_STANDARD_FLOATING_POINT_TYPES()
#if defined(BOOST_LOG_USE_CHAR)
#define BOOST_LOG_AUX_STANDARD_STRING_TYPES() (std::string)(boost::log::string_literal)
#else
#define BOOST_LOG_AUX_STANDARD_STRING_TYPES()
#endif
#if defined(BOOST_LOG_USE_WCHAR_T)
#define BOOST_LOG_AUX_STANDARD_WSTRING_TYPES() (std::wstring)(boost::log::wstring_literal)
#else
#define BOOST_LOG_AUX_STANDARD_WSTRING_TYPES()
#endif
//! Boost.Preprocessor sequence of string types
#define BOOST_LOG_STANDARD_STRING_TYPES()\
BOOST_LOG_AUX_STANDARD_STRING_TYPES()BOOST_LOG_AUX_STANDARD_WSTRING_TYPES()
//! Boost.Preprocessor sequence of the default attribute value types supported by the library
#define BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()\
BOOST_LOG_STANDARD_ARITHMETIC_TYPES()BOOST_LOG_STANDARD_STRING_TYPES()
/*!
* An MPL-sequence of integral types of attributes, supported by default
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_INTEGRAL_TYPES())
> integral_types;
/*!
* An MPL-sequence of FP types of attributes, supported by default
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_FLOATING_POINT_TYPES())
> floating_point_types;
/*!
* An MPL-sequence of all numeric types of attributes, supported by default
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_ARITHMETIC_TYPES())
> arithmetic_types;
//! Deprecated alias
typedef arithmetic_types numeric_types;
/*!
* An MPL-sequence of string types of attributes, supported by default
*/
typedef mpl::vector<
BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_STRING_TYPES())
> string_types;
/*!
* An MPL-sequence of all attribute value types that are supported by the library by default.
*/
typedef BOOST_PP_CAT(mpl::vector, BOOST_PP_SEQ_SIZE(BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()))<
BOOST_PP_SEQ_ENUM(BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES())
> default_attribute_value_types;
//! Deprecated alias
typedef default_attribute_value_types default_attribute_types;
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_STANDARD_TYPES_HPP_INCLUDED_
@@ -0,0 +1,320 @@
/*
* 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 static_type_dispatcher.hpp
* \author Andrey Semashev
* \date 15.04.2007
*
* The header contains implementation of a compile-time type dispatcher.
*/
#ifndef BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_
#define BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_
#include <cstddef>
#include <utility>
#include <iterator>
#include <algorithm>
#include <boost/array.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_index.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/core/addressof.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/utility/once_block.hpp>
#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! Ordering predicate for type dispatching map
struct dispatching_map_order
{
typedef bool result_type;
typedef std::pair< typeindex::type_index, void* > first_argument_type, second_argument_type;
result_type operator() (first_argument_type const& left, second_argument_type const& right) const
{
return (left.first < right.first);
}
};
//! Dispatching map filler
template< typename VisitorT >
struct dispatching_map_initializer
{
template< typename IteratorT >
static BOOST_FORCEINLINE void init(IteratorT*, IteratorT*, std::pair< typeindex::type_index, void* >*)
{
}
template< typename BeginIteratorT, typename EndIteratorT >
static BOOST_FORCEINLINE void init(BeginIteratorT*, EndIteratorT* end, std::pair< typeindex::type_index, void* >* p)
{
typedef typename mpl::deref< BeginIteratorT >::type type;
do_init(static_cast< type* >(0), p);
typedef typename mpl::next< BeginIteratorT >::type next_iterator_type;
init(static_cast< next_iterator_type* >(0), end, p + 1);
}
private:
template< typename T >
static BOOST_FORCEINLINE void do_init(T*, std::pair< typeindex::type_index, void* >* p)
{
p->first = typeindex::type_id< T >();
typedef void (*trampoline_t)(void*, T const&);
BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
union
{
void* as_pvoid;
trampoline_t as_trampoline;
}
caster;
caster.as_trampoline = (trampoline_t)&type_dispatcher::callback_base::trampoline< VisitorT, T >;
p->second = caster.as_pvoid;
}
};
//! A base class for a dispatcher that supports a sequence of types
class type_sequence_dispatcher_base :
public type_dispatcher
{
private:
//! Dispatching map element type
typedef std::pair< typeindex::type_index, void* > dispatching_map_element_type;
private:
//! Dispatching map
const dispatching_map_element_type* m_dispatching_map_begin;
//! Dispatching map size
std::size_t m_dispatching_map_size;
//! Pointer to the receiver function
void* m_visitor;
protected:
//! Initializing constructor
type_sequence_dispatcher_base(const dispatching_map_element_type* disp_map, std::size_t disp_map_size, void* visitor) BOOST_NOEXCEPT :
type_dispatcher(&type_sequence_dispatcher_base::get_callback),
m_dispatching_map_begin(disp_map),
m_dispatching_map_size(disp_map_size),
m_visitor(visitor)
{
}
private:
//! The get_callback method implementation
static callback_base get_callback(type_dispatcher* p, typeindex::type_index type)
{
type_sequence_dispatcher_base* const self = static_cast< type_sequence_dispatcher_base* >(p);
const dispatching_map_element_type* begin = self->m_dispatching_map_begin;
const dispatching_map_element_type* end = begin + self->m_dispatching_map_size;
const dispatching_map_element_type* it = std::lower_bound
(
begin,
end,
dispatching_map_element_type(type, (void*)0),
dispatching_map_order()
);
if (it != end && it->first == type)
return callback_base(self->m_visitor, it->second);
else
return callback_base();
}
// Copying and assignment closed
BOOST_DELETED_FUNCTION(type_sequence_dispatcher_base(type_sequence_dispatcher_base const&))
BOOST_DELETED_FUNCTION(type_sequence_dispatcher_base& operator= (type_sequence_dispatcher_base const&))
};
//! A dispatcher that supports a sequence of types
template< typename TypeSequenceT >
class type_sequence_dispatcher :
public type_sequence_dispatcher_base
{
public:
//! Type sequence of the supported types
typedef TypeSequenceT supported_types;
private:
//! The dispatching map
typedef array<
std::pair< typeindex::type_index, void* >,
mpl::size< supported_types >::value
> dispatching_map;
public:
/*!
* Constructor. Initializes the dispatcher internals.
*/
template< typename VisitorT >
explicit type_sequence_dispatcher(VisitorT& visitor) :
type_sequence_dispatcher_base(get_dispatching_map< VisitorT >().data(), dispatching_map::static_size, (void*)boost::addressof(visitor))
{
}
private:
//! The method returns the dispatching map instance
template< typename VisitorT >
static dispatching_map const& get_dispatching_map()
{
static const dispatching_map* pinstance = NULL;
BOOST_LOG_ONCE_BLOCK()
{
static dispatching_map instance;
typename dispatching_map::value_type* p = &*instance.begin();
typedef typename mpl::begin< supported_types >::type begin_iterator_type;
typedef typename mpl::end< supported_types >::type end_iterator_type;
typedef dispatching_map_initializer< VisitorT > initializer;
initializer::init(static_cast< begin_iterator_type* >(0), static_cast< end_iterator_type* >(0), p);
std::sort(instance.begin(), instance.end(), dispatching_map_order());
pinstance = &instance;
}
return *pinstance;
}
// Copying and assignment closed
BOOST_DELETED_FUNCTION(type_sequence_dispatcher(type_sequence_dispatcher const&))
BOOST_DELETED_FUNCTION(type_sequence_dispatcher& operator= (type_sequence_dispatcher const&))
};
//! A base class for a single-type dispatcher
class single_type_dispatcher_base :
public type_dispatcher
{
private:
//! The type to match against
typeindex::type_index m_type;
//! A callback for the supported type
callback_base m_callback;
protected:
//! Initializing constructor
single_type_dispatcher_base(typeindex::type_index type, callback_base const& cb) BOOST_NOEXCEPT :
type_dispatcher(&single_type_dispatcher_base::get_callback),
m_type(type),
m_callback(cb)
{
}
private:
//! The get_callback method implementation
static callback_base get_callback(type_dispatcher* p, typeindex::type_index type)
{
single_type_dispatcher_base* const self = static_cast< single_type_dispatcher_base* >(p);
if (type == self->m_type)
return self->m_callback;
else
return callback_base();
}
// Copying and assignment closed
BOOST_DELETED_FUNCTION(single_type_dispatcher_base(single_type_dispatcher_base const&))
BOOST_DELETED_FUNCTION(single_type_dispatcher_base& operator= (single_type_dispatcher_base const&))
};
//! A simple dispatcher that only supports one type
template< typename T >
class single_type_dispatcher :
public single_type_dispatcher_base
{
private:
typedef void (*trampoline_t)(void*, T const&);
public:
//! Constructor
template< typename VisitorT >
explicit single_type_dispatcher(VisitorT& visitor) BOOST_NOEXCEPT :
single_type_dispatcher_base(typeindex::type_id< T >(), callback_base((void*)boost::addressof(visitor), (trampoline_t)&callback_base::trampoline< VisitorT, T >))
{
}
// Copying and assignment closed
BOOST_DELETED_FUNCTION(single_type_dispatcher(single_type_dispatcher const&))
BOOST_DELETED_FUNCTION(single_type_dispatcher& operator= (single_type_dispatcher const&))
};
} // namespace aux
/*!
* \brief A static type dispatcher class
*
* The type dispatcher can be used to pass objects of arbitrary types from one
* component to another. With regard to the library, the type dispatcher
* can be used to extract attribute values.
*
* Static type dispatchers allow to specify one or several supported types at compile
* time.
*/
template< typename T >
class static_type_dispatcher
#ifndef BOOST_LOG_DOXYGEN_PASS
:
public mpl::if_<
mpl::is_sequence< T >,
boost::log::aux::type_sequence_dispatcher< T >,
boost::log::aux::single_type_dispatcher< T >
>::type
#endif
{
private:
//! Base type
typedef typename mpl::if_<
mpl::is_sequence< T >,
boost::log::aux::type_sequence_dispatcher< T >,
boost::log::aux::single_type_dispatcher< T >
>::type base_type;
public:
/*!
* Constructor. Initializes the dispatcher internals.
*
* The \a receiver object is not copied inside the dispatcher, but references to
* it may be kept by the dispatcher after construction. The receiver object must remain
* valid until the dispatcher is destroyed.
*
* \param receiver Unary function object that will be called on a dispatched value. The receiver
* must be callable with an argument of any of the supported types of the dispatcher.
*/
template< typename ReceiverT >
explicit static_type_dispatcher(ReceiverT& receiver) :
base_type(receiver)
{
}
// Copying and assignment prohibited
BOOST_DELETED_FUNCTION(static_type_dispatcher(static_type_dispatcher const&))
BOOST_DELETED_FUNCTION(static_type_dispatcher& operator= (static_type_dispatcher const&))
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_STATIC_TYPE_DISPATCHER_HPP_INCLUDED_
@@ -0,0 +1,188 @@
/*
* 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 type_dispatcher.hpp
* \author Andrey Semashev
* \date 15.04.2007
*
* The header contains definition of generic type dispatcher interfaces.
*/
#ifndef BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
#define BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
#include <boost/type_index.hpp>
#include <boost/static_assert.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 A type dispatcher interface
*
* All type dispatchers support this interface. It is used to acquire the
* visitor interface for the requested type.
*/
class type_dispatcher
{
public:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! The base class for type dispatcher callbacks
class callback_base
{
protected:
void* m_pVisitor;
void* m_pTrampoline;
public:
explicit callback_base(void* visitor = 0, void* tramp = 0) BOOST_NOEXCEPT :
m_pVisitor(visitor),
m_pTrampoline(tramp)
{
}
template< typename ValueT >
explicit callback_base(void* visitor, void (*tramp)(void*, ValueT const&)) BOOST_NOEXCEPT :
m_pVisitor(visitor)
{
typedef void (*trampoline_t)(void*, ValueT const&);
BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
union
{
void* as_pvoid;
trampoline_t as_trampoline;
}
caster;
caster.as_trampoline = tramp;
m_pTrampoline = caster.as_pvoid;
}
template< typename VisitorT, typename T >
static void trampoline(void* visitor, T const& value)
{
(*static_cast< VisitorT* >(visitor))(value);
}
};
//! An interface to the callback for the concrete type visitor
template< typename T >
class callback :
private callback_base
{
private:
//! Type of the trampoline method
typedef void (*trampoline_t)(void*, T const&);
public:
//! The type, which the visitor is able to consume
typedef T supported_type;
public:
callback() BOOST_NOEXCEPT : callback_base()
{
}
explicit callback(callback_base const& base) BOOST_NOEXCEPT : callback_base(base)
{
}
void operator() (T const& value) const
{
BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
union
{
void* as_pvoid;
trampoline_t as_trampoline;
}
caster;
caster.as_pvoid = this->m_pTrampoline;
(caster.as_trampoline)(this->m_pVisitor, value);
}
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
bool operator! () const BOOST_NOEXCEPT { return (this->m_pVisitor == 0); }
};
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* This interface is used by type dispatchers to consume the dispatched value.
*/
template< typename T >
class callback
{
public:
/*!
* The operator invokes the visitor-specific logic with the given value
*
* \param value The dispatched value
*/
void operator() (T const& value) const;
/*!
* The operator checks if the visitor is attached to a receiver
*/
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
/*!
* The operator checks if the visitor is not attached to a receiver
*/
bool operator! () const BOOST_NOEXCEPT;
};
#endif // BOOST_LOG_DOXYGEN_PASS
protected:
//! Pointer to the callback acquisition method
typedef callback_base (*get_callback_impl_type)(type_dispatcher*, typeindex::type_index);
private:
//! Pointer to the callback acquisition method
get_callback_impl_type m_get_callback_impl;
protected:
/*!
* Initializing constructor
*/
explicit type_dispatcher(get_callback_impl_type get_callback_impl) BOOST_NOEXCEPT : m_get_callback_impl(get_callback_impl)
{
}
// Destructor and copying can only be called from the derived classes
BOOST_DEFAULTED_FUNCTION(~type_dispatcher(), {})
BOOST_DEFAULTED_FUNCTION(type_dispatcher(type_dispatcher const& that), : m_get_callback_impl(that.m_get_callback_impl) {})
BOOST_DEFAULTED_FUNCTION(type_dispatcher& operator= (type_dispatcher const& that), { m_get_callback_impl = that.m_get_callback_impl; return *this; })
public:
/*!
* The method requests a callback for the value of type \c T
*
* \return The type-specific callback or an empty value, if the type is not supported
*/
template< typename T >
callback< T > get_callback()
{
return callback< T >((this->m_get_callback_impl)(this, typeindex::type_id< T >()));
}
};
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
@@ -0,0 +1,51 @@
/*
* 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 unique_identifier_name.hpp
* \author Andrey Semashev
* \date 30.04.2008
*
* The header contains \c BOOST_LOG_UNIQUE_IDENTIFIER_NAME macro definition.
*/
#ifndef BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_
#include <boost/preprocessor/cat.hpp>
#include <boost/log/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_LOG_DOXYGEN_PASS
#define BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL_(prefix, postfix)\
BOOST_PP_CAT(prefix, postfix)
#define BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, postfix)\
BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL_(prefix, postfix)
#endif // BOOST_LOG_DOXYGEN_PASS
/*!
* \def BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)
*
* Constructs a unique (in the current file scope) token that can be used as a variable name.
* The name will contain a prefix passed in the \a prefix argument. This allows to use the
* macro multiple times on a single line.
*/
// In VC 7.0 and later when compiling with /ZI option __LINE__ macro is corrupted
#ifdef BOOST_MSVC
# define BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)\
BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, __COUNTER__)
#else
# define BOOST_LOG_UNIQUE_IDENTIFIER_NAME(prefix)\
BOOST_LOG_UNIQUE_IDENTIFIER_NAME_INTERNAL(prefix, __LINE__)
#endif // BOOST_MSVC
#endif // BOOST_LOG_UTILITY_UNIQUE_IDENTIFIER_NAME_HPP_INCLUDED_
@@ -0,0 +1,51 @@
/*
* 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 unused_variable.hpp
* \author Andrey Semashev
* \date 10.05.2008
*
* The header contains definition of a macro to suppress compiler warnings about unused variables.
*/
#ifndef BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__GNUC__)
//! The macro suppresses compiler warnings for \c var being unused
#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) __attribute__((unused)) type var initializer
#else
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
template< typename T >
BOOST_FORCEINLINE void no_unused_warnings(T const&) BOOST_NOEXCEPT {}
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
//! The macro suppresses compiler warnings for \c var being unused
#define BOOST_LOG_UNUSED_VARIABLE(type, var, initializer) type var initializer; ::boost::log::aux::no_unused_warnings(var)
#endif
#endif // BOOST_LOG_UTILITY_UNUSED_VARIABLE_HPP_INCLUDED_
@@ -0,0 +1,656 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file value_ref.hpp
* \author Andrey Semashev
* \date 27.07.2012
*
* The header contains implementation of a value reference wrapper.
*/
#ifndef BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
#include <cstddef>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/index_of.hpp>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/core/addressof.hpp>
#include <boost/optional/optional_fwd.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/detail/value_ref_visitation.hpp>
#include <boost/log/detail/sfinae_tools.hpp>
#include <boost/log/utility/formatting_ostream_fwd.hpp>
#include <boost/log/utility/functional/logical.hpp>
#include <boost/log/utility/functional/bind.hpp>
#include <boost/log/utility/functional/bind_output.hpp>
#include <boost/log/utility/functional/bind_to_log.hpp>
#include <boost/log/utility/manipulators/to_log.hpp>
#include <boost/log/utility/value_ref_fwd.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! The function object applies the function object to the bound visitable object and argument
template< typename VisitableT, typename FunT >
struct vistation_invoker
{
typedef typename FunT::result_type result_type;
vistation_invoker(VisitableT& visitable, result_type const& def_val) : m_visitable(visitable), m_def_val(def_val)
{
}
template< typename ArgT >
result_type operator() (ArgT const& arg) const
{
return m_visitable.apply_visitor_or_default(binder1st< FunT, ArgT const& >(FunT(), arg), m_def_val);
}
private:
VisitableT& m_visitable;
result_type m_def_val;
};
//! Traits for testing type compatibility with the reference wrapper
struct singular_ref_compatibility_traits
{
template< typename T, typename U >
struct is_compatible
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template< typename T >
struct is_compatible< T, T >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
};
//! Attribute value reference implementation for a single type case
template< typename T, typename TagT >
class singular_ref
{
public:
//! Referenced value type
typedef T value_type;
//! Tag type
typedef TagT tag_type;
protected:
//! Traits for testing type compatibility with the reference wrapper
typedef singular_ref_compatibility_traits compatibility_traits;
protected:
//! Pointer to the value
const value_type* m_ptr;
protected:
//! Default constructor
singular_ref() BOOST_NOEXCEPT : m_ptr(NULL)
{
}
//! Initializing constructor
explicit singular_ref(const value_type* p) BOOST_NOEXCEPT : m_ptr(p)
{
}
public:
//! Returns a pointer to the referred value
const value_type* operator-> () const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_ptr != NULL);
return m_ptr;
}
//! Returns a pointer to the referred value
const value_type* get_ptr() const BOOST_NOEXCEPT
{
return m_ptr;
}
//! Returns a pointer to the referred value
template< typename U >
typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, const U* >::type get_ptr() const BOOST_NOEXCEPT
{
return m_ptr;
}
//! Returns a reference to the value
value_type const& operator* () const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_ptr != NULL);
return *m_ptr;
}
//! Returns a reference to the value
value_type const& get() const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_ptr != NULL);
return *m_ptr;
}
//! Returns a reference to the value
template< typename U >
typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, U const& >::type get() const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_ptr != NULL);
return *m_ptr;
}
//! Resets the reference
void reset() BOOST_NOEXCEPT
{
m_ptr = NULL;
}
//! Returns the stored type index
static BOOST_CONSTEXPR unsigned int which()
{
return 0u;
}
//! Swaps two reference wrappers
void swap(singular_ref& that) BOOST_NOEXCEPT
{
const void* p = m_ptr;
m_ptr = that.m_ptr;
that.m_ptr = p;
}
//! Applies a visitor function object to the referred value
template< typename VisitorT >
typename VisitorT::result_type apply_visitor(VisitorT visitor) const
{
BOOST_ASSERT(m_ptr != NULL);
return visitor(*m_ptr);
}
//! Applies a visitor function object to the referred value
template< typename VisitorT >
typename boost::enable_if_c< is_void< typename VisitorT::result_type >::value, bool >::type apply_visitor_optional(VisitorT visitor) const
{
if (m_ptr)
{
visitor(*m_ptr);
return true;
}
else
return false;
}
//! Applies a visitor function object to the referred value
template< typename VisitorT >
typename boost::disable_if_c< is_void< typename VisitorT::result_type >::value, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
{
typedef optional< typename VisitorT::result_type > result_type;
if (m_ptr)
return result_type(visitor(*m_ptr));
else
return result_type();
}
//! Applies a visitor function object to the referred value or returns a default value
template< typename VisitorT, typename DefaultT >
typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
{
if (m_ptr)
return visitor(*m_ptr);
else
return def_val;
}
//! Applies a visitor function object to the referred value or returns a default value
template< typename VisitorT, typename DefaultT >
typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
{
if (m_ptr)
return visitor(*m_ptr);
else
return def_val;
}
};
//! Traits for testing type compatibility with the reference wrapper
struct variant_ref_compatibility_traits
{
template< typename T, typename U >
struct is_compatible
{
BOOST_STATIC_CONSTANT(bool, value = (mpl::contains< T, U >::type::value));
};
};
//! Attribute value reference implementation for multiple types case
template< typename T, typename TagT >
class variant_ref
{
public:
//! Referenced value type
typedef T value_type;
//! Tag type
typedef TagT tag_type;
protected:
//! Traits for testing type compatibility with the reference wrapper
typedef variant_ref_compatibility_traits compatibility_traits;
protected:
//! Pointer to the value
const void* m_ptr;
//! Type index
unsigned int m_type_idx;
protected:
//! Default constructor
variant_ref() BOOST_NOEXCEPT : m_ptr(NULL), m_type_idx(0)
{
}
//! Initializing constructor
template< typename U >
explicit variant_ref(const U* p) BOOST_NOEXCEPT : m_ptr(p), m_type_idx(mpl::index_of< value_type, U >::type::value)
{
}
public:
//! Resets the reference
void reset() BOOST_NOEXCEPT
{
m_ptr = NULL;
m_type_idx = 0;
}
//! Returns a pointer to the referred value
template< typename U >
typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, const U* >::type get_ptr() const BOOST_NOEXCEPT
{
if (m_type_idx == static_cast< unsigned int >(mpl::index_of< value_type, U >::type::value))
return static_cast< const U* >(m_ptr);
else
return NULL;
}
//! Returns a reference to the value
template< typename U >
typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, U const& >::type get() const BOOST_NOEXCEPT
{
const U* const p = get_ptr< U >();
BOOST_ASSERT(p != NULL);
return *p;
}
//! Returns the stored type index
unsigned int which() const BOOST_NOEXCEPT
{
return m_type_idx;
}
//! Swaps two reference wrappers
void swap(variant_ref& that) BOOST_NOEXCEPT
{
const void* p = m_ptr;
m_ptr = that.m_ptr;
that.m_ptr = p;
unsigned int type_idx = m_type_idx;
m_type_idx = that.m_type_idx;
that.m_type_idx = type_idx;
}
//! Applies a visitor function object to the referred value
template< typename VisitorT >
typename VisitorT::result_type apply_visitor(VisitorT visitor) const
{
BOOST_ASSERT(m_ptr != NULL);
return do_apply_visitor(visitor);
}
//! Applies a visitor function object to the referred value
template< typename VisitorT >
typename boost::enable_if_c< is_void< typename VisitorT::result_type >::value, bool >::type apply_visitor_optional(VisitorT visitor) const
{
if (m_ptr)
{
do_apply_visitor(visitor);
return true;
}
else
return false;
}
//! Applies a visitor function object to the referred value
template< typename VisitorT >
typename boost::disable_if_c< is_void< typename VisitorT::result_type >::value, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
{
typedef optional< typename VisitorT::result_type > result_type;
if (m_ptr)
return result_type(do_apply_visitor(visitor));
else
return result_type();
}
//! Applies a visitor function object to the referred value or returns a default value
template< typename VisitorT, typename DefaultT >
typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
{
if (m_ptr)
return do_apply_visitor(visitor);
else
return def_val;
}
//! Applies a visitor function object to the referred value or returns a default value
template< typename VisitorT, typename DefaultT >
typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
{
if (m_ptr)
return do_apply_visitor(visitor);
else
return def_val;
}
private:
template< typename VisitorT >
typename VisitorT::result_type do_apply_visitor(VisitorT& visitor) const
{
BOOST_ASSERT(m_type_idx < static_cast< unsigned int >(mpl::size< value_type >::value));
return apply_visitor_dispatch< value_type, VisitorT >::call(m_ptr, m_type_idx, visitor);
}
};
template< typename T, typename TagT >
struct value_ref_base
{
typedef typename mpl::eval_if<
mpl::and_< mpl::is_sequence< T >, mpl::equal_to< mpl::size< T >, mpl::int_< 1 > > >,
mpl::front< T >,
mpl::identity< T >
>::type value_type;
typedef typename mpl::if_<
mpl::is_sequence< value_type >,
variant_ref< value_type, TagT >,
singular_ref< value_type, TagT >
>::type type;
};
} // namespace aux
/*!
* \brief Reference wrapper for a stored attribute value.
*
* The \c value_ref class template provides access to the stored attribute value. It is not a traditional reference wrapper
* since it may be empty (i.e. refer to no value at all) and it can also refer to values of different types. Therefore its
* interface and behavior combines features of Boost.Ref, Boost.Optional and Boost.Variant, depending on the use case.
*
* The template parameter \c T can be a single type or an MPL sequence of possible types being referred. The reference wrapper
* will act as either an optional reference or an optional variant of references to the specified types. In any case, the
* referred values will not be modifiable (i.e. \c value_ref always models a const reference).
*
* Template parameter \c TagT is optional. It can be used for customizing the operations on this reference wrapper, such as
* putting the referred value to log.
*/
template< typename T, typename TagT >
class value_ref :
public aux::value_ref_base< T, TagT >::type
{
#ifndef BOOST_LOG_DOXYGEN_PASS
public:
typedef void _has_basic_formatting_ostream_insert_operator;
#endif
private:
//! Base implementation type
typedef typename aux::value_ref_base< T, TagT >::type base_type;
//! Traits for testing type compatibility with the reference wrapper
typedef typename base_type::compatibility_traits compatibility_traits;
public:
#ifndef BOOST_LOG_DOXYGEN_PASS
//! Referenced value type
typedef typename base_type::value_type value_type;
#else
//! Referenced value type
typedef T value_type;
//! Tag type
typedef TagT tag_type;
#endif
public:
/*!
* Default constructor. Creates a reference wrapper that does not refer to a value.
*/
BOOST_DEFAULTED_FUNCTION(value_ref(), BOOST_NOEXCEPT {})
/*!
* Copy constructor.
*/
BOOST_DEFAULTED_FUNCTION(value_ref(value_ref const& that), BOOST_NOEXCEPT : base_type(static_cast< base_type const& >(that)) {})
/*!
* Initializing constructor. Creates a reference wrapper that refers to the specified value.
*/
template< typename U >
explicit value_ref(U const& val
#ifndef BOOST_LOG_DOXYGEN_PASS
// MSVC-8 can't handle SFINAE in this case properly and often wrongly disables this constructor
#if !defined(_MSC_VER) || (_MSC_VER + 0) >= 1500
, typename boost::enable_if_c< compatibility_traits::BOOST_NESTED_TEMPLATE is_compatible< value_type, U >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()
#endif
#endif
) BOOST_NOEXCEPT :
base_type(boost::addressof(val))
{
}
/*!
* The operator verifies if the wrapper refers to a value.
*/
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
/*!
* The operator verifies if the wrapper does not refer to a value.
*/
bool operator! () const BOOST_NOEXCEPT
{
return !this->m_ptr;
}
/*!
* \return \c true if the wrapper does not refer to a value.
*/
bool empty() const BOOST_NOEXCEPT
{
return !this->m_ptr;
}
/*!
* Swaps two reference wrappers
*/
void swap(value_ref& that) BOOST_NOEXCEPT
{
base_type::swap(that);
}
};
//! Free swap function
template< typename T, typename TagT >
inline void swap(value_ref< T, TagT >& left, value_ref< T, TagT >& right)
{
left.swap(right);
}
//! Stream output operator
template< typename CharT, typename TraitsT, typename T, typename TagT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, value_ref< T, TagT > const& val)
{
if (!!val)
val.apply_visitor(boost::log::bind_output(strm));
return strm;
}
//! Log formatting operator
template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT >
inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, value_ref< T, TagT > const& val)
{
if (!!val)
val.apply_visitor(boost::log::bind_to_log< TagT >(strm));
return strm;
}
// Equality comparison
template< typename T, typename TagT, typename U >
inline bool operator== (value_ref< T, TagT > const& left, U const& right)
{
return left.apply_visitor_or_default(binder2nd< equal_to, U const& >(equal_to(), right), false);
}
template< typename U, typename T, typename TagT >
inline bool operator== (U const& left, value_ref< T, TagT > const& right)
{
return right.apply_visitor_or_default(binder1st< equal_to, U const& >(equal_to(), left), false);
}
template< typename T1, typename TagT1, typename T2, typename TagT2 >
inline bool operator== (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
{
if (!left && !right)
return true;
return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, equal_to >(right, false), false);
}
// Inequality comparison
template< typename T, typename TagT, typename U >
inline bool operator!= (value_ref< T, TagT > const& left, U const& right)
{
return left.apply_visitor_or_default(binder2nd< not_equal_to, U const& >(not_equal_to(), right), false);
}
template< typename U, typename T, typename TagT >
inline bool operator!= (U const& left, value_ref< T, TagT > const& right)
{
return right.apply_visitor_or_default(binder1st< not_equal_to, U const& >(not_equal_to(), left), false);
}
template< typename T1, typename TagT1, typename T2, typename TagT2 >
inline bool operator!= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
{
if (!left && !right)
return false;
return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, not_equal_to >(right, false), false);
}
// Less than ordering
template< typename T, typename TagT, typename U >
inline bool operator< (value_ref< T, TagT > const& left, U const& right)
{
return left.apply_visitor_or_default(binder2nd< less, U const& >(less(), right), false);
}
template< typename U, typename T, typename TagT >
inline bool operator< (U const& left, value_ref< T, TagT > const& right)
{
return right.apply_visitor_or_default(binder1st< less, U const& >(less(), left), false);
}
template< typename T1, typename TagT1, typename T2, typename TagT2 >
inline bool operator< (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
{
return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less >(right, false), false);
}
// Greater than ordering
template< typename T, typename TagT, typename U >
inline bool operator> (value_ref< T, TagT > const& left, U const& right)
{
return left.apply_visitor_or_default(binder2nd< greater, U const& >(greater(), right), false);
}
template< typename U, typename T, typename TagT >
inline bool operator> (U const& left, value_ref< T, TagT > const& right)
{
return right.apply_visitor_or_default(binder1st< greater, U const& >(greater(), left), false);
}
template< typename T1, typename TagT1, typename T2, typename TagT2 >
inline bool operator> (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
{
return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater >(right, false), false);
}
// Less or equal ordering
template< typename T, typename TagT, typename U >
inline bool operator<= (value_ref< T, TagT > const& left, U const& right)
{
return left.apply_visitor_or_default(binder2nd< less_equal, U const& >(less_equal(), right), false);
}
template< typename U, typename T, typename TagT >
inline bool operator<= (U const& left, value_ref< T, TagT > const& right)
{
return right.apply_visitor_or_default(binder1st< less_equal, U const& >(less_equal(), left), false);
}
template< typename T1, typename TagT1, typename T2, typename TagT2 >
inline bool operator<= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
{
if (!left && !right)
return true;
return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less_equal >(right, false), false);
}
// Greater or equal ordering
template< typename T, typename TagT, typename U >
inline bool operator>= (value_ref< T, TagT > const& left, U const& right)
{
return left.apply_visitor_or_default(binder2nd< greater_equal, U const& >(greater_equal(), right), false);
}
template< typename U, typename T, typename TagT >
inline bool operator>= (U const& left, value_ref< T, TagT > const& right)
{
return right.apply_visitor_or_default(binder1st< greater_equal, U const& >(greater_equal(), left), false);
}
template< typename T1, typename TagT1, typename T2, typename TagT2 >
inline bool operator>= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
{
if (!left && !right)
return true;
return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater_equal >(right, false), false);
}
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
@@ -0,0 +1,38 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file value_ref_fwd.hpp
* \author Andrey Semashev
* \date 27.07.2012
*
* The header contains forward declaration of a value reference wrapper.
*/
#ifndef BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_
#define BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
/*!
* \brief Reference wrapper for a stored attribute value.
*/
template< typename T, typename TagT = void >
class value_ref;
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#endif // BOOST_LOG_UTILITY_VALUE_REF_FWD_HPP_INCLUDED_