File indexing completed on 2025-01-18 09:39:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
0017 #define BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
0018
0019 #include <cstddef>
0020 #include <string>
0021 #include <vector>
0022 #include <iosfwd>
0023 #include <boost/assert.hpp>
0024 #include <boost/move/core.hpp>
0025 #include <boost/move/utility_core.hpp>
0026 #include <boost/core/uncaught_exceptions.hpp>
0027 #include <boost/log/detail/config.hpp>
0028 #include <boost/log/detail/cleanup_scope_guard.hpp>
0029 #include <boost/log/utility/formatting_ostream.hpp>
0030 #include <boost/log/detail/header.hpp>
0031
0032 #ifdef BOOST_HAS_PRAGMA_ONCE
0033 #pragma once
0034 #endif
0035
0036 namespace boost {
0037
0038 BOOST_LOG_OPEN_NAMESPACE
0039
0040 namespace aux {
0041
0042
0043 struct format_element
0044 {
0045
0046 int arg_number;
0047
0048 unsigned int literal_start_pos, literal_len;
0049
0050 format_element() : arg_number(0), literal_start_pos(0), literal_len(0)
0051 {
0052 }
0053
0054 static format_element literal(unsigned int start_pos, unsigned int len)
0055 {
0056 format_element el;
0057 el.arg_number = -1;
0058 el.literal_start_pos = start_pos;
0059 el.literal_len = len;
0060 return el;
0061 }
0062
0063 static format_element positional_argument(unsigned int arg_n)
0064 {
0065 format_element el;
0066 el.arg_number = arg_n;
0067 return el;
0068 }
0069 };
0070
0071
0072 template< typename CharT >
0073 struct format_description
0074 {
0075 BOOST_COPYABLE_AND_MOVABLE_ALT(format_description)
0076
0077 public:
0078
0079 typedef CharT char_type;
0080
0081 typedef std::basic_string< char_type > string_type;
0082
0083
0084 typedef std::vector< format_element > format_element_list;
0085
0086
0087 string_type literal_chars;
0088
0089 format_element_list format_elements;
0090
0091 BOOST_DEFAULTED_FUNCTION(format_description(), {})
0092
0093 format_description(format_description const& that) : literal_chars(that.literal_chars), format_elements(that.format_elements)
0094 {
0095 }
0096
0097 format_description(BOOST_RV_REF(format_description) that) BOOST_NOEXCEPT
0098 {
0099 literal_chars.swap(that.literal_chars);
0100 format_elements.swap(that.format_elements);
0101 }
0102
0103 format_description& operator= (format_description that) BOOST_NOEXCEPT
0104 {
0105 literal_chars.swap(that.literal_chars);
0106 format_elements.swap(that.format_elements);
0107 return *this;
0108 }
0109 };
0110
0111
0112 template< typename CharT >
0113 BOOST_LOG_API format_description< CharT > parse_format(const CharT* begin, const CharT* end);
0114
0115
0116 template< typename CharT >
0117 BOOST_FORCEINLINE format_description< CharT > parse_format(const CharT* begin)
0118 {
0119 return parse_format(begin, begin + std::char_traits< CharT >::length(begin));
0120 }
0121
0122
0123 template< typename CharT, typename TraitsT, typename AllocatorT >
0124 BOOST_FORCEINLINE format_description< CharT > parse_format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt)
0125 {
0126 const CharT* begin = fmt.c_str();
0127 return parse_format(begin, begin + fmt.size());
0128 }
0129
0130
0131 template< typename CharT >
0132 class basic_format
0133 {
0134 public:
0135
0136 typedef CharT char_type;
0137
0138 typedef std::basic_string< char_type > string_type;
0139
0140 typedef basic_formatting_ostream< char_type > stream_type;
0141
0142 typedef format_description< char_type > format_description_type;
0143
0144
0145 class pump;
0146 friend class pump;
0147
0148 private:
0149
0150 struct formatting_params
0151 {
0152
0153 unsigned int element_idx;
0154
0155 string_type target;
0156
0157 formatting_params() : element_idx(~0u) {}
0158 };
0159 typedef std::vector< formatting_params > formatting_params_list;
0160
0161 private:
0162
0163 format_description_type m_format;
0164
0165 formatting_params_list m_formatting_params;
0166
0167 unsigned int m_current_idx;
0168
0169 public:
0170
0171 explicit basic_format(string_type const& fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0)
0172 {
0173 init_params();
0174 }
0175
0176 explicit basic_format(const char_type* fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0)
0177 {
0178 init_params();
0179 }
0180
0181
0182 void clear() BOOST_NOEXCEPT
0183 {
0184 for (typename formatting_params_list::iterator it = m_formatting_params.begin(), end = m_formatting_params.end(); it != end; ++it)
0185 {
0186 it->target.clear();
0187 }
0188 m_current_idx = 0;
0189 }
0190
0191
0192 pump make_pump(stream_type& strm)
0193 {
0194
0195 strm.flush();
0196 return pump(*this, strm);
0197 }
0198
0199
0200 string_type str() const
0201 {
0202 string_type result;
0203 compose(result);
0204 return BOOST_LOG_NRVO_RESULT(result);
0205 }
0206
0207 private:
0208
0209 void init_params()
0210 {
0211 typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
0212 for (; it != end; ++it)
0213 {
0214 if (it->arg_number >= 0)
0215 {
0216 if (static_cast< unsigned int >(it->arg_number) >= m_formatting_params.size())
0217 m_formatting_params.resize(it->arg_number + 1);
0218 m_formatting_params[it->arg_number].element_idx = static_cast< unsigned int >(it - m_format.format_elements.begin());
0219 }
0220 }
0221 }
0222
0223
0224 template< typename T >
0225 void compose(T& str) const
0226 {
0227 typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
0228 for (; it != end; ++it)
0229 {
0230 if (it->arg_number >= 0)
0231 {
0232
0233 string_type const& target = m_formatting_params[it->arg_number].target;
0234 str.append(target.data(), target.size());
0235 }
0236 else
0237 {
0238
0239 const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos;
0240 str.append(p, it->literal_len);
0241 }
0242 }
0243 }
0244 };
0245
0246
0247 template< typename CharT >
0248 class basic_format< CharT >::pump
0249 {
0250 BOOST_MOVABLE_BUT_NOT_COPYABLE(pump)
0251
0252 private:
0253
0254 struct scoped_storage
0255 {
0256 scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_state_backup(strm.rdbuf()->get_storage_state())
0257 {
0258 strm.attach(storage);
0259 }
0260 ~scoped_storage()
0261 {
0262 m_stream.rdbuf()->set_storage_state(m_storage_state_backup);
0263 }
0264
0265 private:
0266 stream_type& m_stream;
0267 typename stream_type::streambuf_type::storage_state m_storage_state_backup;
0268 };
0269
0270 private:
0271
0272 basic_format* m_owner;
0273
0274 stream_type* m_stream;
0275
0276 const unsigned int m_exception_count;
0277
0278 public:
0279
0280 pump(basic_format& owner, stream_type& strm) BOOST_NOEXCEPT : m_owner(&owner), m_stream(&strm), m_exception_count(boost::core::uncaught_exceptions())
0281 {
0282 }
0283
0284
0285 pump(BOOST_RV_REF(pump) that) BOOST_NOEXCEPT : m_owner(that.m_owner), m_stream(that.m_stream), m_exception_count(that.m_exception_count)
0286 {
0287 that.m_owner = NULL;
0288 that.m_stream = NULL;
0289 }
0290
0291
0292 ~pump() BOOST_NOEXCEPT_IF(false)
0293 {
0294 if (m_owner)
0295 {
0296
0297 boost::log::aux::cleanup_guard< basic_format< char_type > > cleanup1(*m_owner);
0298
0299 BOOST_ASSERT(m_stream != NULL);
0300 if (m_exception_count >= boost::core::uncaught_exceptions())
0301 {
0302
0303 m_stream->flush();
0304 m_owner->compose(*m_stream->rdbuf());
0305 }
0306 }
0307 }
0308
0309
0310
0311
0312
0313
0314 template< typename T >
0315 pump operator% (T const& val)
0316 {
0317 BOOST_ASSERT_MSG(m_owner != NULL && m_stream != NULL, "Boost.Log: This basic_format::pump has already been moved from");
0318
0319 if (m_owner->m_current_idx < m_owner->m_formatting_params.size())
0320 {
0321 scoped_storage storage_guard(*m_stream, m_owner->m_formatting_params[m_owner->m_current_idx].target);
0322
0323 *m_stream << val;
0324 m_stream->flush();
0325
0326 ++m_owner->m_current_idx;
0327 }
0328
0329 return boost::move(*this);
0330 }
0331 };
0332
0333 }
0334
0335 BOOST_LOG_CLOSE_NAMESPACE
0336
0337 }
0338
0339 #include <boost/log/detail/footer.hpp>
0340
0341 #endif