Skip to content

Commit

Permalink
Refs #9123. Implemented support for incomplete and empty markers for …
Browse files Browse the repository at this point in the history
…the named scope formatter.
  • Loading branch information
Lastique committed Mar 15, 2014
1 parent 9ce8a45 commit 25b59e5
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 24 deletions.
2 changes: 2 additions & 0 deletions doc/changelog.qbk
Expand Up @@ -16,6 +16,8 @@
* Added indexing operators with [class_log_attribute_name] arguments to [class_log_record] and [class_log_record_view]. The operators behave the same way as the similar operators of [class_log_attribute_value_set] (i.e. return an [class_log_attribute_value] identified by the name).
* Added operators for non-const object output to [class_log_basic_formatting_ostream]. ([ticket 9389])
* Added new format flags "%c", "%C" and "%F" to the [link log.detailed.expressions.formatters.named_scope named scope formatter]. The new flags allow putting function names and source file names of named scopes into the formatted strings. ([ticket 9263])
* Added support for incomplete and empty markers to the [link log.detailed.expressions.formatters.named_scope named scope formatter]. The markers can be used to customize the scope list presentation when the list is empty or limited by the `depth` named parameter. ([ticket 9123])
* The default presentation for incomplete named scope lists has changed. In previous releases the incomplete marker included a trailing delimiter, for example "scope1<-scope2<-...". From this release the trailing delimiter is omitted, so in the same case the formatting result would be: "scope1<-scope2..." (note the missing trailing "<-").

[*Bug fixes:]

Expand Down
9 changes: 7 additions & 2 deletions doc/expressions.qbk
Expand Up @@ -378,6 +378,8 @@ While the format string describes the presentation of each named scope in the li
* `iteration`. The argument describes the direction of iteration through scopes. Can have values `forward` (default) or `reverse`.
* `delimiter`. The argument can be used to specify the delimiters between scopes. The default delimiter depends on the `iteration` argument. If `iteration == forward` the default `delimiter` will be "->", otherwise it will be "<-".
* `depth`. The argument can be used to limit the number of scopes to put to log. The formatter will print `depth` innermost scopes and, if there are more scopes left, append an ellipsis to the written sequence. By default the formatter will write all scope names.
* `incomplete_marker`. The argument can be used to specify the string that is used to indicate that the list has been limited by the `depth` argument. By default the "..." string is used as the marker.
* `empty_marker`. The argument can be used to specify the string to output in case if the scope list is empty. By default nothing is output in this case.

Here are a few usage examples:

Expand Down Expand Up @@ -405,7 +407,7 @@ Here are a few usage examples:
);

// Puts the scope stack in forward order, no more than 2 inner scopes:
// ... -> outer scope -> inner scope
// ... outer scope -> inner scope
sink->set_formatter
(
expr::stream
Expand All @@ -417,17 +419,20 @@ Here are a few usage examples:
);

// Puts the scope stack in reverse order, no more than 2 inner scopes:
// inner scope <- outer scope <- ...
// inner scope <- outer scope <<and more>>...
sink->set_formatter
(
expr::stream
<< expr::format_named_scope(
"Scopes",
keywords::format = "%n",
keywords::iteration = expr::reverse,
keywords::incomplete_marker = " <<and more>>..."
keywords::depth = 2)
);

[tip An empty string can be specified as the `incomplete_marker` parameter, in which case there will be no indication that the list was truncated.]

[endsect]

[section:conditional Conditional formatters]
Expand Down
10 changes: 10 additions & 0 deletions include/boost/log/detail/custom_terminal_spec.hpp
Expand Up @@ -61,6 +61,16 @@ struct custom_terminal< T, typename T::_is_boost_log_terminal >
}
};

//namespace result_of {

//template< typename T >
//struct is_nullary< custom_terminal< T >, typename T::_is_boost_log_terminal > :
// public mpl::false_
//{
//};

//} // namespace result_of

} // namespace phoenix

} // namespace boost
Expand Down
80 changes: 62 additions & 18 deletions include/boost/log/expressions/formatters/named_scope.hpp
Expand Up @@ -50,6 +50,8 @@
#include <boost/log/keywords/delimiter.hpp>
#include <boost/log/keywords/depth.hpp>
#include <boost/log/keywords/iteration.hpp>
#include <boost/log/keywords/empty_marker.hpp>
#include <boost/log/keywords/incomplete_marker.hpp>
#include <boost/log/detail/header.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
Expand Down Expand Up @@ -132,16 +134,30 @@ class format_named_scope_impl
element_formatter_type m_element_formatter;
//! Element delimiter
string_type m_delimiter;
//! Incomplete list marker
string_type m_incomplete_marker;
//! Empty list marker
string_type m_empty_marker;
//! Maximum number of elements to output
value_type::size_type m_depth;
//! Iteration direction
scope_iteration_direction m_direction;

public:
//! Initializing constructor
format_named_scope_impl(element_formatter_type const& element_formatter, string_type const& delimiter, value_type::size_type depth, scope_iteration_direction direction) :
format_named_scope_impl
(
element_formatter_type const& element_formatter,
string_type const& delimiter,
string_type const& incomplete_marker,
string_type const& empty_marker,
value_type::size_type depth,
scope_iteration_direction direction
) :
m_element_formatter(element_formatter),
m_delimiter(delimiter),
m_incomplete_marker(incomplete_marker),
m_empty_marker(empty_marker),
m_depth(depth),
m_direction(direction)
{
Expand All @@ -150,6 +166,8 @@ class format_named_scope_impl
format_named_scope_impl(format_named_scope_impl const& that) :
m_element_formatter(that.m_element_formatter),
m_delimiter(that.m_delimiter),
m_incomplete_marker(that.m_incomplete_marker),
m_empty_marker(that.m_empty_marker),
m_depth(that.m_depth),
m_direction(that.m_direction)
{
Expand All @@ -158,10 +176,17 @@ class format_named_scope_impl
//! Formatting operator
result_type operator() (stream_type& strm, value_type const& scopes) const
{
if (m_direction == expressions::forward)
format_forward(strm, scopes);
if (!scopes.empty())
{
if (m_direction == expressions::forward)
format_forward(strm, scopes);
else
format_reverse(strm, scopes);
}
else
format_reverse(strm, scopes);
{
strm << m_empty_marker;
}
}

private:
Expand All @@ -183,7 +208,7 @@ class format_named_scope_impl
if (it != end)
{
if (it != scopes.begin())
strm << "..." << m_delimiter;
strm << m_incomplete_marker;

m_element_formatter(strm, *it);
for (++it; it != end; ++it)
Expand Down Expand Up @@ -218,7 +243,7 @@ class format_named_scope_impl
}

if (it != scopes.rend())
strm << m_delimiter << "...";
strm << m_incomplete_marker;
}
}
};
Expand Down Expand Up @@ -266,8 +291,18 @@ class format_named_scope_terminal
public:
//! Initializing constructor
template< typename FormatT >
format_named_scope_terminal(attribute_name const& name, fallback_policy const& fallback, FormatT const& element_format, string_type const& delimiter, value_type::size_type depth, scope_iteration_direction direction) :
m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, depth, direction), m_visitor_invoker(fallback)
format_named_scope_terminal
(
attribute_name const& name,
fallback_policy const& fallback,
FormatT const& element_format,
string_type const& delimiter,
string_type const& incomplete_marker,
string_type const& empty_marker,
value_type::size_type depth,
scope_iteration_direction direction
) :
m_name(name), m_formatter(aux::parse_named_scope_format(element_format), delimiter, incomplete_marker, empty_marker, depth, direction), m_visitor_invoker(fallback)
{
}
//! Copy constructor
Expand Down Expand Up @@ -392,24 +427,28 @@ class format_named_scope_actor :

namespace aux {

//! Auxiliary traits to acquire correct default delimiter depending on the character type
//! Auxiliary traits to acquire default formatter parameters depending on the character type
template< typename CharT >
struct default_scope_delimiter;
struct default_named_scope_params;

#ifdef BOOST_LOG_USE_CHAR
template< >
struct default_scope_delimiter< char >
struct default_named_scope_params< char >
{
static const char* forward() { return "->"; }
static const char* reverse() { return "<-"; }
static const char* forward_delimiter() { return "->"; }
static const char* reverse_delimiter() { return "<-"; }
static const char* incomplete_marker() { return "..."; }
static const char* empty_marker() { return ""; }
};
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
template< >
struct default_scope_delimiter< wchar_t >
struct default_named_scope_params< wchar_t >
{
static const wchar_t* forward() { return L"->"; }
static const wchar_t* reverse() { return L"<-"; }
static const wchar_t* forward_delimiter() { return L"->"; }
static const wchar_t* reverse_delimiter() { return L"<-"; }
static const wchar_t* incomplete_marker() { return L"..."; }
static const wchar_t* empty_marker() { return L""; }
};
#endif

Expand All @@ -418,8 +457,9 @@ BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > for
{
typedef format_named_scope_actor< FallbackPolicyT, CharT, ActorT > actor_type;
typedef typename actor_type::terminal_type terminal_type;
typedef default_named_scope_params< CharT > default_params;
scope_iteration_direction dir = args[keywords::iteration | expressions::forward];
const CharT* default_delimiter = (dir == expressions::forward ? default_scope_delimiter< CharT >::forward() : default_scope_delimiter< CharT >::reverse());
const CharT* default_delimiter = (dir == expressions::forward ? default_params::forward_delimiter() : default_params::reverse_delimiter());
typename actor_type::base_type act =
{{
terminal_type
Expand All @@ -428,6 +468,8 @@ BOOST_FORCEINLINE format_named_scope_actor< FallbackPolicyT, CharT, ActorT > for
fallback,
args[keywords::format],
args[keywords::delimiter | default_delimiter],
args[keywords::incomplete_marker | default_params::incomplete_marker()],
args[keywords::empty_marker | default_params::empty_marker()],
args[keywords::depth | static_cast< attributes::named_scope::value_type::size_type >(0)],
dir
)
Expand Down Expand Up @@ -552,7 +594,7 @@ format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& pl
#if !defined(BOOST_LOG_DOXYGEN_PASS)

# define BOOST_PP_FILENAME_1 <boost/log/detail/named_scope_fmt_pp.hpp>
# define BOOST_PP_ITERATION_LIMITS (1, 4)
# define BOOST_PP_ITERATION_LIMITS (1, 6)
# include BOOST_PP_ITERATE()

#else // BOOST_LOG_DOXYGEN_PASS
Expand All @@ -564,6 +606,8 @@ format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& pl
* \param args An set of named parameters. Supported parameters:
* \li \c format - A format string for named scopes. The string can contain "%n", "%f" and "%l" placeholders for the scope name, file and line number, respectively. This parameter is mandatory.
* \li \c delimiter - A string that is used to delimit the formatted scope names. Default: "->" or "<-", depending on the iteration direction.
* \li \c incomplete_marker - A string that is used to indicate that the list was printed incomplete because of depth limitation. Default: "...".
* \li \c empty_marker - A string that is output in case if the scope list is empty. Default: "", i.e. nothing is output.
* \li \c iteration - Iteration direction, see \c scope_iteration_direction enumeration. Default: forward.
* \li \c depth - Iteration depth. Default: unlimited.
*/
Expand Down
40 changes: 40 additions & 0 deletions include/boost/log/keywords/empty_marker.hpp
@@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2014.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file keywords/empty_marker.hpp
* \author Andrey Semashev
* \date 15.03.2014
*
* The header contains the \c empty_marker keyword declaration.
*/

#ifndef BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_
#define BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_

#include <boost/parameter/keyword.hpp>
#include <boost/log/detail/config.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace keywords {

//! The keyword for passing the marker for the empty list of scopes to the \c named_scope formatter
BOOST_PARAMETER_KEYWORD(tag, empty_marker)

} // namespace keywords

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#endif // BOOST_LOG_KEYWORDS_EMPTY_MARKER_HPP_INCLUDED_
40 changes: 40 additions & 0 deletions include/boost/log/keywords/incomplete_marker.hpp
@@ -0,0 +1,40 @@
/*
* Copyright Andrey Semashev 2007 - 2014.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file keywords/incomplete_marker.hpp
* \author Andrey Semashev
* \date 15.03.2014
*
* The header contains the \c incomplete_marker keyword declaration.
*/

#ifndef BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_
#define BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_

#include <boost/parameter/keyword.hpp>
#include <boost/log/detail/config.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace keywords {

//! The keyword for passing incomplete marker for the list of scopes to the \c named_scope formatter
BOOST_PARAMETER_KEYWORD(tag, incomplete_marker)

} // namespace keywords

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#endif // BOOST_LOG_KEYWORDS_INCOMPLETE_MARKER_HPP_INCLUDED_

0 comments on commit 25b59e5

Please sign in to comment.