2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
8 * \file formatters/c_decorator.hpp
9 * \author Andrey Semashev
12 * The header contains implementation of C-style character decorators.
15 #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_
16 #define BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_
19 #include <boost/range/iterator_range_core.hpp>
20 #include <boost/log/detail/config.hpp>
21 #include <boost/log/detail/snprintf.hpp>
22 #include <boost/log/expressions/formatters/char_decorator.hpp>
23 #include <boost/log/detail/header.hpp>
25 #ifdef BOOST_HAS_PRAGMA_ONCE
31 BOOST_LOG_OPEN_NAMESPACE
33 namespace expressions {
38 struct c_decorator_traits;
40 #ifdef BOOST_LOG_USE_CHAR
42 struct c_decorator_traits< char >
44 static boost::iterator_range< const char* const* > get_patterns()
46 static const char* const patterns[] =
48 "\\", "\a", "\b", "\f", "\n", "\r", "\t", "\v", "'", "\"", "?"
50 return boost::make_iterator_range(patterns);
52 static boost::iterator_range< const char* const* > get_replacements()
54 static const char* const replacements[] =
56 "\\\\", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v", "\\'", "\\\"", "\\?"
58 return boost::make_iterator_range(replacements);
60 template< unsigned int N >
61 static std::size_t print_escaped(char (&buf)[N], char c)
63 int n = boost::log::aux::snprintf(buf, N, "\\x%.2X", static_cast< unsigned int >(static_cast< uint8_t >(c)));
69 return static_cast< unsigned int >(n) >= N ? N - 1 : static_cast< unsigned int >(n);
72 #endif // BOOST_LOG_USE_CHAR
74 #ifdef BOOST_LOG_USE_WCHAR_T
76 struct c_decorator_traits< wchar_t >
78 static boost::iterator_range< const wchar_t* const* > get_patterns()
80 static const wchar_t* const patterns[] =
82 L"\\", L"\a", L"\b", L"\f", L"\n", L"\r", L"\t", L"\v", L"'", L"\"", L"?"
84 return boost::make_iterator_range(patterns);
86 static boost::iterator_range< const wchar_t* const* > get_replacements()
88 static const wchar_t* const replacements[] =
90 L"\\\\", L"\\a", L"\\b", L"\\f", L"\\n", L"\\r", L"\\t", L"\\v", L"\\'", L"\\\"", L"\\?"
92 return boost::make_iterator_range(replacements);
94 template< unsigned int N >
95 static std::size_t print_escaped(wchar_t (&buf)[N], wchar_t c)
97 const wchar_t* format;
99 if (sizeof(wchar_t) == 1)
102 val = static_cast< uint8_t >(c);
104 else if (sizeof(wchar_t) == 2)
107 val = static_cast< uint16_t >(c);
112 val = static_cast< uint32_t >(c);
115 int n = boost::log::aux::swprintf(buf, N, format, val);
121 return static_cast< unsigned int >(n) >= N ? N - 1 : static_cast< unsigned int >(n);
124 #endif // BOOST_LOG_USE_WCHAR_T
126 template< typename CharT >
127 struct c_decorator_gen
129 typedef CharT char_type;
131 template< typename SubactorT >
132 BOOST_FORCEINLINE char_decorator_actor< SubactorT, pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
134 typedef c_decorator_traits< char_type > traits_type;
135 typedef pattern_replacer< char_type > replacer_type;
136 typedef char_decorator_actor< SubactorT, replacer_type > result_type;
137 typedef typename result_type::terminal_type terminal_type;
138 typename result_type::base_type act = {{ terminal_type(subactor, replacer_type(traits_type::get_patterns(), traits_type::get_replacements())) }};
139 return result_type(act);
146 * C-style decorator generator object. The decorator replaces characters with specific meaning in C
147 * language with the corresponding escape sequences. The generator provides <tt>operator[]</tt> that
148 * can be used to construct the actual decorator. For example:
151 * c_decor[ stream << attr< std::string >("MyAttr") ]
154 * For wide-character formatting there is the similar \c wc_decor decorator generator object.
156 #ifdef BOOST_LOG_USE_CHAR
157 const aux::c_decorator_gen< char > c_decor = {};
159 #ifdef BOOST_LOG_USE_WCHAR_T
160 const aux::c_decorator_gen< wchar_t > wc_decor = {};
164 * The function creates a C-style decorator generator for arbitrary character type.
166 template< typename CharT >
167 BOOST_FORCEINLINE aux::c_decorator_gen< CharT > make_c_decor()
169 return aux::c_decorator_gen< CharT >();
173 * A character decorator implementation that escapes all non-prontable and non-ASCII characters
174 * in the output with C-style escape sequences.
176 template< typename CharT >
177 class c_ascii_pattern_replacer :
178 public pattern_replacer< CharT >
182 typedef pattern_replacer< CharT > base_type;
186 typedef typename base_type::result_type result_type;
188 typedef typename base_type::char_type char_type;
190 typedef typename base_type::string_type string_type;
194 typedef aux::c_decorator_traits< char_type > traits_type;
197 //! Default constructor
198 c_ascii_pattern_replacer() : base_type(traits_type::get_patterns(), traits_type::get_replacements())
202 //! Applies string replacements starting from the specified position
203 result_type operator() (string_type& str, typename string_type::size_type start_pos = 0) const
205 base_type::operator() (str, start_pos);
207 typedef typename string_type::iterator string_iterator;
208 for (string_iterator it = str.begin() + start_pos, end = str.end(); it != end; ++it)
211 if (c < 0x20 || c > 0x7e)
213 char_type buf[(std::numeric_limits< char_type >::digits + 3) / 4 + 3];
214 std::size_t n = traits_type::print_escaped(buf, c);
215 std::size_t pos = it - str.begin();
216 str.replace(pos, 1, buf, n);
217 it = str.begin() + n - 1;
226 template< typename CharT >
227 struct c_ascii_decorator_gen
229 typedef CharT char_type;
231 template< typename SubactorT >
232 BOOST_FORCEINLINE char_decorator_actor< SubactorT, c_ascii_pattern_replacer< char_type > > operator[] (SubactorT const& subactor) const
234 typedef c_ascii_pattern_replacer< char_type > replacer_type;
235 typedef char_decorator_actor< SubactorT, replacer_type > result_type;
236 typedef typename result_type::terminal_type terminal_type;
237 typename result_type::base_type act = {{ terminal_type(subactor, replacer_type()) }};
238 return result_type(act);
245 * C-style decorator generator object. Acts similarly to \c c_decor, except that \c c_ascii_decor also
246 * converts all non-ASCII and non-printable ASCII characters, except for space character, into
247 * C-style hexadecimal escape sequences. The generator provides <tt>operator[]</tt> that
248 * can be used to construct the actual decorator. For example:
251 * c_ascii_decor[ stream << attr< std::string >("MyAttr") ]
254 * For wide-character formatting there is the similar \c wc_ascii_decor decorator generator object.
256 #ifdef BOOST_LOG_USE_CHAR
257 const aux::c_ascii_decorator_gen< char > c_ascii_decor = {};
259 #ifdef BOOST_LOG_USE_WCHAR_T
260 const aux::c_ascii_decorator_gen< wchar_t > wc_ascii_decor = {};
264 * The function creates a C-style decorator generator for arbitrary character type.
266 template< typename CharT >
267 BOOST_FORCEINLINE aux::c_ascii_decorator_gen< CharT > make_c_ascii_decor()
269 return aux::c_ascii_decorator_gen< CharT >();
272 } // namespace expressions
274 BOOST_LOG_CLOSE_NAMESPACE // namespace log
278 #include <boost/log/detail/footer.hpp>
280 #endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_C_DECORATOR_HPP_INCLUDED_