]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/log/include/boost/log/utility/formatting_ostream.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / log / include / boost / log / utility / formatting_ostream.hpp
CommitLineData
7c673cae
FG
1/*
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)
6 */
7/*!
8 * \file formatting_ostream.hpp
9 * \author Andrey Semashev
10 * \date 11.07.2012
11 *
12 * The header contains implementation of a string stream used for log record formatting.
13 */
14
15#ifndef BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
16#define BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_
17
18#include <ostream>
19#include <string>
20#include <memory>
21#include <locale>
22#include <boost/core/enable_if.hpp>
23#include <boost/core/explicit_operator_bool.hpp>
24#include <boost/utility/string_ref_fwd.hpp>
25#include <boost/utility/string_view_fwd.hpp>
26#include <boost/type_traits/is_enum.hpp>
27#include <boost/type_traits/is_scalar.hpp>
28#include <boost/type_traits/remove_cv.hpp>
29#include <boost/log/detail/config.hpp>
30#include <boost/log/detail/attachable_sstream_buf.hpp>
31#include <boost/log/detail/code_conversion.hpp>
32#include <boost/log/utility/string_literal_fwd.hpp>
33#include <boost/log/utility/formatting_ostream_fwd.hpp>
34#include <boost/log/detail/header.hpp>
35
36#ifdef BOOST_HAS_PRAGMA_ONCE
37#pragma once
38#endif
39
40namespace boost {
41
42BOOST_LOG_OPEN_NAMESPACE
43
44namespace aux {
45
46template< typename T, typename R >
47struct enable_if_streamable_char_type {};
48template< typename R >
49struct enable_if_streamable_char_type< char, R > { typedef R type; };
50template< typename R >
51struct enable_if_streamable_char_type< wchar_t, R > { typedef R type; };
52#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
53#if !defined(BOOST_NO_CXX11_CHAR16_T)
54template< typename R >
55struct enable_if_streamable_char_type< char16_t, R > { typedef R type; };
56#endif
57#if !defined(BOOST_NO_CXX11_CHAR32_T)
58template< typename R >
59struct enable_if_streamable_char_type< char32_t, R > { typedef R type; };
60#endif
61#endif
62
63template< typename StreamT, typename T, bool ByValueV, typename R >
64struct enable_formatting_ostream_generic_operator {};
65template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
66struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T, false, R > :
67 public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
68{
69};
70template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename R >
71struct enable_formatting_ostream_generic_operator< basic_formatting_ostream< CharT, TraitsT, AllocatorT >, T, true, R > :
72 public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
73{
74};
75
76} // namespace aux
77
78/*!
79 * \brief Stream wrapper for log records formatting.
80 *
81 * This stream wrapper is used by the library for log record formatting. It implements the standard string stream interface
82 * with a few differences:
83 *
84 * \li It does not derive from standard types <tt>std::basic_ostream</tt>, <tt>std::basic_ios</tt> and <tt>std::ios_base</tt>,
85 * although it tries to implement their interfaces closely. There are a few small differences, mostly regarding <tt>rdbuf</tt>
86 * and <tt>str</tt> signatures, as well as the supported insertion operator overloads. The actual wrapped stream can be accessed
87 * through the <tt>stream</tt> methods.
88 * \li By default, \c bool values are formatted using alphabetical representation rather than numeric.
89 * \li The stream supports writing strings of character types different from the stream character type. The stream will perform
90 * character code conversion as needed using the imbued locale.
91 * \li The stream operates on an external string object rather than on the embedded one. The string can be attached or detached
92 * from the stream dynamically.
93 *
94 * Although <tt>basic_formatting_ostream</tt> does not derive from <tt>std::basic_ostream</tt>, users are not required to add
95 * special overloads of \c operator<< for it since the stream will by default reuse the operators for <tt>std::basic_ostream</tt>.
96 * However, one can define special overloads of \c operator<< for <tt>basic_formatting_ostream</tt> if a certain type needs
97 * special formatting when output to log.
98 */
99template< typename CharT, typename TraitsT, typename AllocatorT >
100class basic_formatting_ostream
101{
102public:
103 //! Character type
104 typedef CharT char_type;
105 //! Character traits
106 typedef TraitsT traits_type;
107 //! Memory allocator
108 typedef AllocatorT allocator_type;
109 //! Stream buffer type
110 typedef boost::log::aux::basic_ostringstreambuf< char_type, traits_type, allocator_type > streambuf_type;
111 //! Target string type
112 typedef typename streambuf_type::string_type string_type;
113
114 //! Stream type
115 typedef std::basic_ostream< char_type, traits_type > ostream_type;
116 //! Stream position type
117 typedef typename ostream_type::pos_type pos_type;
118 //! Stream offset type
119 typedef typename ostream_type::off_type off_type;
120 //! Integer type for characters
121 typedef typename ostream_type::int_type int_type;
122
123 typedef typename ostream_type::failure failure;
124 typedef typename ostream_type::fmtflags fmtflags;
125 typedef typename ostream_type::iostate iostate;
126 typedef typename ostream_type::openmode openmode;
127 typedef typename ostream_type::seekdir seekdir;
128 typedef typename ostream_type::Init Init;
129
130 typedef typename ostream_type::event event;
131 typedef typename ostream_type::event_callback event_callback;
132
133 class sentry :
134 public ostream_type::sentry
135 {
136 typedef typename ostream_type::sentry base_type;
137
138 public:
139 explicit sentry(basic_formatting_ostream& strm) : base_type(strm.stream())
140 {
141 }
142
143 // A workaround for Solaris Studio 12.4 compiler, see: https://svn.boost.org/trac/boost/ticket/11545
144 BOOST_EXPLICIT_OPERATOR_BOOL()
145 bool operator! () const { return !static_cast< base_type const& >(*this); }
146
147 BOOST_DELETED_FUNCTION(sentry(sentry const&))
148 BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&))
149 };
150
151protected:
152 // Function types
153 typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
154 typedef std::basic_ios< char_type, traits_type >& (*basic_ios_manip)(std::basic_ios< char_type, traits_type >&);
155 typedef ostream_type& (*stream_manip)(ostream_type&);
156
157public:
158 static BOOST_CONSTEXPR_OR_CONST fmtflags boolalpha = ostream_type::boolalpha;
159 static BOOST_CONSTEXPR_OR_CONST fmtflags dec = ostream_type::dec;
160 static BOOST_CONSTEXPR_OR_CONST fmtflags fixed = ostream_type::fixed;
161 static BOOST_CONSTEXPR_OR_CONST fmtflags hex = ostream_type::hex;
162 static BOOST_CONSTEXPR_OR_CONST fmtflags internal = ostream_type::internal;
163 static BOOST_CONSTEXPR_OR_CONST fmtflags left = ostream_type::left;
164 static BOOST_CONSTEXPR_OR_CONST fmtflags oct = ostream_type::oct;
165 static BOOST_CONSTEXPR_OR_CONST fmtflags right = ostream_type::right;
166 static BOOST_CONSTEXPR_OR_CONST fmtflags scientific = ostream_type::scientific;
167 static BOOST_CONSTEXPR_OR_CONST fmtflags showbase = ostream_type::showbase;
168 static BOOST_CONSTEXPR_OR_CONST fmtflags showpoint = ostream_type::showpoint;
169 static BOOST_CONSTEXPR_OR_CONST fmtflags skipws = ostream_type::skipws;
170 static BOOST_CONSTEXPR_OR_CONST fmtflags unitbuf = ostream_type::unitbuf;
171 static BOOST_CONSTEXPR_OR_CONST fmtflags uppercase = ostream_type::uppercase;
172 static BOOST_CONSTEXPR_OR_CONST fmtflags adjustfield = ostream_type::adjustfield;
173 static BOOST_CONSTEXPR_OR_CONST fmtflags basefield = ostream_type::basefield;
174 static BOOST_CONSTEXPR_OR_CONST fmtflags floatfield = ostream_type::floatfield;
175
176 static BOOST_CONSTEXPR_OR_CONST iostate badbit = ostream_type::badbit;
177 static BOOST_CONSTEXPR_OR_CONST iostate eofbit = ostream_type::eofbit;
178 static BOOST_CONSTEXPR_OR_CONST iostate failbit = ostream_type::failbit;
179 static BOOST_CONSTEXPR_OR_CONST iostate goodbit = ostream_type::goodbit;
180
181 static BOOST_CONSTEXPR_OR_CONST openmode app = ostream_type::app;
182 static BOOST_CONSTEXPR_OR_CONST openmode ate = ostream_type::ate;
183 static BOOST_CONSTEXPR_OR_CONST openmode binary = ostream_type::binary;
184 static BOOST_CONSTEXPR_OR_CONST openmode in = ostream_type::in;
185 static BOOST_CONSTEXPR_OR_CONST openmode out = ostream_type::out;
186 static BOOST_CONSTEXPR_OR_CONST openmode trunc = ostream_type::trunc;
187
188 static BOOST_CONSTEXPR_OR_CONST seekdir beg = ostream_type::beg;
189 static BOOST_CONSTEXPR_OR_CONST seekdir cur = ostream_type::cur;
190 static BOOST_CONSTEXPR_OR_CONST seekdir end = ostream_type::end;
191
192 static BOOST_CONSTEXPR_OR_CONST event erase_event = ostream_type::erase_event;
193 static BOOST_CONSTEXPR_OR_CONST event imbue_event = ostream_type::imbue_event;
194 static BOOST_CONSTEXPR_OR_CONST event copyfmt_event = ostream_type::copyfmt_event;
195
196private:
197 mutable streambuf_type m_streambuf;
198 ostream_type m_stream;
199
200public:
201 /*!
202 * Default constructor. Creates an empty record that is equivalent to the invalid record handle.
203 * The stream capability is not available after construction.
204 *
205 * \post <tt>!*this == true</tt>
206 */
207 basic_formatting_ostream() : m_stream(&m_streambuf)
208 {
209 init_stream();
210 }
211
212 /*!
213 * Initializing constructor. Attaches the string to the constructed stream.
214 * The string will be used to store the formatted characters.
215 *
216 * \post <tt>!*this == false</tt>
217 * \param str The string buffer to attach.
218 */
219 explicit basic_formatting_ostream(string_type& str) :
220 m_streambuf(str),
221 m_stream(&m_streambuf)
222 {
223 init_stream();
224 }
225
226 /*!
227 * Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
228 */
229 ~basic_formatting_ostream()
230 {
231 if (m_streambuf.storage())
232 flush();
233 }
234
235 /*!
236 * Attaches the stream to the string. The string will be used to store the formatted characters.
237 *
238 * \param str The string buffer to attach.
239 */
240 void attach(string_type& str)
241 {
242 m_streambuf.attach(str);
243 m_stream.clear(ostream_type::goodbit);
244 }
245 /*!
246 * Detaches the stream from the string. Any buffered data is flushed to the string.
247 */
248 void detach()
249 {
250 m_streambuf.detach();
251 m_stream.clear(ostream_type::badbit);
252 }
253
254 /*!
255 * \returns Reference to the attached string. The string must be attached before calling this method.
256 */
257 string_type const& str() const
258 {
259 string_type* const storage = m_streambuf.storage();
260 BOOST_ASSERT(storage != NULL);
261
262 m_streambuf.pubsync();
263
264 return *storage;
265 }
266
267 /*!
268 * \returns Reference to the wrapped stream
269 */
270 ostream_type& stream() { return m_stream; }
271
272 /*!
273 * \returns Reference to the wrapped stream
274 */
275 ostream_type const& stream() const { return m_stream; }
276
277 // std::ios_base method forwarders
278 fmtflags flags() const { return m_stream.flags(); }
279 fmtflags flags(fmtflags f) { return m_stream.flags(f); }
280 fmtflags setf(fmtflags f) { return m_stream.setf(f); }
281 fmtflags setf(fmtflags f, fmtflags mask) { return m_stream.setf(f, mask); }
282 void unsetf(fmtflags f) { m_stream.unsetf(f); }
283
284 std::streamsize precision() const { return m_stream.precision(); }
285 std::streamsize precision(std::streamsize p) { return m_stream.precision(p); }
286
287 std::streamsize width() const { return m_stream.width(); }
288 std::streamsize width(std::streamsize w) { return m_stream.width(w); }
289
290 std::locale getloc() const { return m_stream.getloc(); }
291 std::locale imbue(std::locale const& loc) { return m_stream.imbue(loc); }
292
293 static int xalloc() { return ostream_type::xalloc(); }
294 long& iword(int index) { return m_stream.iword(index); }
295 void*& pword(int index) { return m_stream.pword(index); }
296
297 void register_callback(event_callback fn, int index) { m_stream.register_callback(fn, index); }
298
299 static bool sync_with_stdio(bool sync = true) { return ostream_type::sync_with_stdio(sync); }
300
301 // std::basic_ios method forwarders
302 BOOST_EXPLICIT_OPERATOR_BOOL()
303 bool operator! () const { return !m_stream; }
304
305 iostate rdstate() const { return m_stream.rdstate(); }
306 void clear(iostate state = goodbit) { m_stream.clear(state); }
307 void setstate(iostate state) { m_stream.setstate(state); }
308 bool good() const { return m_stream.good(); }
309 bool eof() const { return m_stream.eof(); }
310 bool fail() const { return m_stream.fail(); }
311 bool bad() const { return m_stream.bad(); }
312
313 iostate exceptions() const { return m_stream.exceptions(); }
314 void exceptions(iostate s) { m_stream.exceptions(s); }
315
316 ostream_type* tie() const { return m_stream.tie(); }
317 ostream_type* tie(ostream_type* strm) { return m_stream.tie(strm); }
318
319 streambuf_type* rdbuf() const { return &m_streambuf; }
320
321 basic_formatting_ostream& copyfmt(std::basic_ios< char_type, traits_type >& rhs)
322 {
323 m_stream.copyfmt(rhs);
324 return *this;
325 }
326 basic_formatting_ostream& copyfmt(basic_formatting_ostream& rhs)
327 {
328 m_stream.copyfmt(rhs.stream());
329 return *this;
330 }
331
332 char_type fill() const { return m_stream.fill(); }
333 char_type fill(char_type ch) { return m_stream.fill(ch); }
334
335 char narrow(char_type ch, char def) const { return m_stream.narrow(ch, def); }
336 char_type widen(char ch) const { return m_stream.widen(ch); }
337
338 // std::basic_ostream method forwarders
339 basic_formatting_ostream& flush()
340 {
341 m_stream.flush();
342 return *this;
343 }
344
345 pos_type tellp() { return m_stream.tellp(); }
346 basic_formatting_ostream& seekp(pos_type pos)
347 {
348 m_stream.seekp(pos);
349 return *this;
350 }
351 basic_formatting_ostream& seekp(off_type off, std::ios_base::seekdir dir)
352 {
353 m_stream.seekp(off, dir);
354 return *this;
355 }
356
357 basic_formatting_ostream& put(char_type c)
358 {
359 m_stream.put(c);
360 return *this;
361 }
362
363 template< typename OtherCharT >
364 typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
365 put(OtherCharT c)
366 {
367 write(&c, 1);
368 return *this;
369 }
370
371 basic_formatting_ostream& write(const char_type* p, std::streamsize size)
372 {
373 m_stream.write(p, size);
374 return *this;
375 }
376
377 template< typename OtherCharT >
378 typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
379 write(const OtherCharT* p, std::streamsize size)
380 {
381 sentry guard(*this);
382 if (!!guard)
383 {
384 m_stream.flush();
385
386 if (!m_streambuf.storage_overflow())
387 {
388 string_type* storage = m_streambuf.storage();
389 if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
390 m_streambuf.storage_overflow(true);
391 }
392 }
393
394 return *this;
395 }
396
397 basic_formatting_ostream& operator<< (ios_base_manip manip)
398 {
399 m_stream << manip;
400 return *this;
401 }
402 basic_formatting_ostream& operator<< (basic_ios_manip manip)
403 {
404 m_stream << manip;
405 return *this;
406 }
407 basic_formatting_ostream& operator<< (stream_manip manip)
408 {
409 m_stream << manip;
410 return *this;
411 }
412
413 basic_formatting_ostream& operator<< (char c)
414 {
415 return this->formatted_write(&c, 1);
416 }
417 basic_formatting_ostream& operator<< (const char* p)
418 {
419 return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p)));
420 }
421
422 // When no native character type is supported, the following overloads are disabled as they have ambiguous meaning.
423 // Use basic_string_view or basic_string to explicitly indicate that the data is a string.
424#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
425 basic_formatting_ostream& operator<< (wchar_t c)
426 {
427 return this->formatted_write(&c, 1);
428 }
429 basic_formatting_ostream& operator<< (const wchar_t* p)
430 {
431 return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p)));
432 }
433#endif
434#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
435#if !defined(BOOST_NO_CXX11_CHAR16_T)
436 basic_formatting_ostream& operator<< (char16_t c)
437 {
438 return this->formatted_write(&c, 1);
439 }
440 basic_formatting_ostream& operator<< (const char16_t* p)
441 {
442 return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p)));
443 }
444#endif
445#if !defined(BOOST_NO_CXX11_CHAR32_T)
446 basic_formatting_ostream& operator<< (char32_t c)
447 {
448 return this->formatted_write(&c, 1);
449 }
450 basic_formatting_ostream& operator<< (const char32_t* p)
451 {
452 return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p)));
453 }
454#endif
455#endif
456
457 basic_formatting_ostream& operator<< (bool value)
458 {
459 m_stream << value;
460 return *this;
461 }
462 basic_formatting_ostream& operator<< (signed char value)
463 {
464 m_stream << value;
465 return *this;
466 }
467 basic_formatting_ostream& operator<< (unsigned char value)
468 {
469 m_stream << value;
470 return *this;
471 }
472 basic_formatting_ostream& operator<< (short value)
473 {
474 m_stream << value;
475 return *this;
476 }
477 basic_formatting_ostream& operator<< (unsigned short value)
478 {
479 m_stream << value;
480 return *this;
481 }
482 basic_formatting_ostream& operator<< (int value)
483 {
484 m_stream << value;
485 return *this;
486 }
487 basic_formatting_ostream& operator<< (unsigned int value)
488 {
489 m_stream << value;
490 return *this;
491 }
492 basic_formatting_ostream& operator<< (long value)
493 {
494 m_stream << value;
495 return *this;
496 }
497 basic_formatting_ostream& operator<< (unsigned long value)
498 {
499 m_stream << value;
500 return *this;
501 }
502#if !defined(BOOST_NO_LONG_LONG)
503 basic_formatting_ostream& operator<< (long long value)
504 {
505 m_stream << value;
506 return *this;
507 }
508 basic_formatting_ostream& operator<< (unsigned long long value)
509 {
510 m_stream << value;
511 return *this;
512 }
513#endif
514
515 basic_formatting_ostream& operator<< (float value)
516 {
517 m_stream << value;
518 return *this;
519 }
520 basic_formatting_ostream& operator<< (double value)
521 {
522 m_stream << value;
523 return *this;
524 }
525 basic_formatting_ostream& operator<< (long double value)
526 {
527 m_stream << value;
528 return *this;
529 }
530
531 basic_formatting_ostream& operator<< (const void* value)
532 {
533 m_stream << value;
534 return *this;
535 }
536
537 basic_formatting_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
538 {
539 m_stream << buf;
540 return *this;
541 }
542
543 template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
544 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
545 operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
546 {
547 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
548 }
549
550 template< typename OtherCharT, typename OtherTraitsT >
551 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
552 operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
553 {
554 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
555 }
556
557 template< typename OtherCharT, typename OtherTraitsT >
558 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
559 operator<< (basic_formatting_ostream& strm, basic_string_view< OtherCharT, OtherTraitsT > const& str)
560 {
561 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
562 }
563
564 // Deprecated overload
565 template< typename OtherCharT, typename OtherTraitsT >
566 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
567 operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
568 {
569 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
570 }
571
572 template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
573 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
574 operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT >& str)
575 {
576 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
577 }
578
579 template< typename OtherCharT, typename OtherTraitsT >
580 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
581 operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str)
582 {
583 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
584 }
585
586 template< typename OtherCharT, typename OtherTraitsT >
587 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
588 operator<< (basic_formatting_ostream& strm, basic_string_view< OtherCharT, OtherTraitsT >& str)
589 {
590 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
591 }
592
593 // Deprecated overload
594 template< typename OtherCharT, typename OtherTraitsT >
595 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
596 operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT >& str)
597 {
598 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
599 }
600
601#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
602 template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
603 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
604 operator<< (basic_formatting_ostream&& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
605 {
606 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
607 }
608
609 template< typename OtherCharT, typename OtherTraitsT >
610 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
611 operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
612 {
613 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
614 }
615
616 template< typename OtherCharT, typename OtherTraitsT >
617 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
618 operator<< (basic_formatting_ostream&& strm, basic_string_view< OtherCharT, OtherTraitsT > const& str)
619 {
620 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
621 }
622
623 // Deprecated overload
624 template< typename OtherCharT, typename OtherTraitsT >
625 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
626 operator<< (basic_formatting_ostream&& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
627 {
628 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
629 }
630
631 template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
632 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
633 operator<< (basic_formatting_ostream&& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT >& str)
634 {
635 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
636 }
637
638 template< typename OtherCharT, typename OtherTraitsT >
639 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
640 operator<< (basic_formatting_ostream&& strm, basic_string_literal< OtherCharT, OtherTraitsT >& str)
641 {
642 return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
643 }
644
645 template< typename OtherCharT, typename OtherTraitsT >
646 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
647 operator<< (basic_formatting_ostream&& strm, basic_string_view< OtherCharT, OtherTraitsT >& str)
648 {
649 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
650 }
651
652 // Deprecated overload
653 template< typename OtherCharT, typename OtherTraitsT >
654 friend typename aux::enable_if_streamable_char_type< OtherCharT, basic_formatting_ostream& >::type
655 operator<< (basic_formatting_ostream&& strm, basic_string_ref< OtherCharT, OtherTraitsT >& str)
656 {
657 return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
658 }
659#endif
660
661protected:
662 void init_stream()
663 {
664 m_stream.exceptions(ostream_type::goodbit);
665 m_stream.clear(m_streambuf.storage() ? ostream_type::goodbit : ostream_type::badbit);
666 m_stream.flags
667 (
668 ostream_type::dec |
669 ostream_type::skipws |
670 ostream_type::boolalpha // this differs from the default stream flags but makes logs look better
671 );
672 m_stream.width(0);
673 m_stream.precision(6);
674 m_stream.fill(static_cast< char_type >(' '));
675 }
676
677private:
678 basic_formatting_ostream& formatted_write(const char_type* p, std::streamsize size)
679 {
680 sentry guard(*this);
681 if (!!guard)
682 {
683 m_stream.flush();
684
685 if (m_stream.width() <= size)
686 m_streambuf.append(p, static_cast< std::size_t >(size));
687 else
688 this->aligned_write(p, size);
689
690 m_stream.width(0);
691 }
692
693 return *this;
694 }
695
696 template< typename OtherCharT >
697 basic_formatting_ostream& formatted_write(const OtherCharT* p, std::streamsize size)
698 {
699 sentry guard(*this);
700 if (!!guard)
701 {
702 m_stream.flush();
703
704 if (m_stream.width() <= size)
705 {
706 if (!m_streambuf.storage_overflow())
707 {
708 if (!aux::code_convert(p, static_cast< std::size_t >(size), *m_streambuf.storage(), m_streambuf.max_size(), m_stream.getloc()))
709 m_streambuf.storage_overflow(true);
710 }
711 }
712 else
713 this->aligned_write(p, size);
714
715 m_stream.width(0);
716 }
717
718 return *this;
719 }
720
721 void aligned_write(const char_type* p, std::streamsize size);
722
723 template< typename OtherCharT >
724 void aligned_write(const OtherCharT* p, std::streamsize size);
725
726 //! Copy constructor (closed)
727 BOOST_DELETED_FUNCTION(basic_formatting_ostream(basic_formatting_ostream const& that))
728 //! Assignment (closed)
729 BOOST_DELETED_FUNCTION(basic_formatting_ostream& operator= (basic_formatting_ostream const& that))
730};
731
732template< typename CharT, typename TraitsT, typename AllocatorT >
733BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::boolalpha;
734template< typename CharT, typename TraitsT, typename AllocatorT >
735BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::dec;
736template< typename CharT, typename TraitsT, typename AllocatorT >
737BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fixed;
738template< typename CharT, typename TraitsT, typename AllocatorT >
739BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::hex;
740template< typename CharT, typename TraitsT, typename AllocatorT >
741BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::internal;
742template< typename CharT, typename TraitsT, typename AllocatorT >
743BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::left;
744template< typename CharT, typename TraitsT, typename AllocatorT >
745BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::oct;
746template< typename CharT, typename TraitsT, typename AllocatorT >
747BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::right;
748template< typename CharT, typename TraitsT, typename AllocatorT >
749BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::scientific;
750template< typename CharT, typename TraitsT, typename AllocatorT >
751BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showbase;
752template< typename CharT, typename TraitsT, typename AllocatorT >
753BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::showpoint;
754template< typename CharT, typename TraitsT, typename AllocatorT >
755BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::skipws;
756template< typename CharT, typename TraitsT, typename AllocatorT >
757BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::unitbuf;
758template< typename CharT, typename TraitsT, typename AllocatorT >
759BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::uppercase;
760template< typename CharT, typename TraitsT, typename AllocatorT >
761BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::adjustfield;
762template< typename CharT, typename TraitsT, typename AllocatorT >
763BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::basefield;
764template< typename CharT, typename TraitsT, typename AllocatorT >
765BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::fmtflags basic_formatting_ostream< CharT, TraitsT, AllocatorT >::floatfield;
766
767template< typename CharT, typename TraitsT, typename AllocatorT >
768BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::badbit;
769template< typename CharT, typename TraitsT, typename AllocatorT >
770BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::eofbit;
771template< typename CharT, typename TraitsT, typename AllocatorT >
772BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::failbit;
773template< typename CharT, typename TraitsT, typename AllocatorT >
774BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::iostate basic_formatting_ostream< CharT, TraitsT, AllocatorT >::goodbit;
775
776template< typename CharT, typename TraitsT, typename AllocatorT >
777BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::app;
778template< typename CharT, typename TraitsT, typename AllocatorT >
779BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::ate;
780template< typename CharT, typename TraitsT, typename AllocatorT >
781BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::binary;
782template< typename CharT, typename TraitsT, typename AllocatorT >
783BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::in;
784template< typename CharT, typename TraitsT, typename AllocatorT >
785BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::out;
786template< typename CharT, typename TraitsT, typename AllocatorT >
787BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::openmode basic_formatting_ostream< CharT, TraitsT, AllocatorT >::trunc;
788
789template< typename CharT, typename TraitsT, typename AllocatorT >
790BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::beg;
791template< typename CharT, typename TraitsT, typename AllocatorT >
792BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::cur;
793template< typename CharT, typename TraitsT, typename AllocatorT >
794BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::seekdir basic_formatting_ostream< CharT, TraitsT, AllocatorT >::end;
795
796template< typename CharT, typename TraitsT, typename AllocatorT >
797BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::erase_event;
798template< typename CharT, typename TraitsT, typename AllocatorT >
799BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::imbue_event;
800template< typename CharT, typename TraitsT, typename AllocatorT >
801BOOST_CONSTEXPR_OR_CONST typename basic_formatting_ostream< CharT, TraitsT, AllocatorT >::event basic_formatting_ostream< CharT, TraitsT, AllocatorT >::copyfmt_event;
802
803template< typename CharT, typename TraitsT, typename AllocatorT >
804void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const char_type* p, std::streamsize size)
805{
806 typename string_type::size_type const alignment_size =
807 static_cast< typename string_type::size_type >(m_stream.width() - size);
808 const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
809 if (align_left)
810 {
811 m_streambuf.append(p, static_cast< std::size_t >(size));
812 m_streambuf.append(alignment_size, m_stream.fill());
813 }
814 else
815 {
816 m_streambuf.append(alignment_size, m_stream.fill());
817 m_streambuf.append(p, static_cast< std::size_t >(size));
818 }
819}
820
821template< typename CharT, typename TraitsT, typename AllocatorT >
822template< typename OtherCharT >
823void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const OtherCharT* p, std::streamsize size)
824{
825 string_type* const storage = m_streambuf.storage();
826 typename string_type::size_type const alignment_size =
827 static_cast< typename string_type::size_type >(m_stream.width() - size);
828 const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
829 if (align_left)
830 {
831 if (!m_streambuf.storage_overflow())
832 {
833 if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
834 m_streambuf.storage_overflow(true);
835 }
836 m_streambuf.append(alignment_size, m_stream.fill());
837 }
838 else
839 {
840 m_streambuf.append(alignment_size, m_stream.fill());
841 if (!m_streambuf.storage_overflow())
842 {
843 if (!aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_streambuf.max_size(), m_stream.getloc()))
844 m_streambuf.storage_overflow(true);
845 }
846 }
847}
848
849// Implementation note: these operators below should be the least attractive for the compiler
850// so that user's overloads are chosen, when present. We use function template partial ordering for this purpose.
851// We also don't use perfect forwarding for the right hand argument because in this case the generic overload
852// would be more preferred than the typical one written by users:
853//
854// formatting_ostream& operator<< (formatting_ostream& strm, my_type const& arg);
855//
856// This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required
857// if there is a perfect forwarding overload.
858template< typename StreamT, typename T >
859inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, true, StreamT& >::type
860operator<< (StreamT& strm, T value)
861{
862 strm.stream() << value;
863 return strm;
864}
865
866template< typename StreamT, typename T >
867inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
868operator<< (StreamT& strm, T const& value)
869{
870 strm.stream() << value;
871 return strm;
872}
873
874template< typename StreamT, typename T >
875inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
876operator<< (StreamT& strm, T& value)
877{
878 strm.stream() << value;
879 return strm;
880}
881
882#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
883
884template< typename StreamT, typename T >
885inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, true, StreamT& >::type
886operator<< (StreamT&& strm, T value)
887{
888 strm.stream() << value;
889 return strm;
890}
891
892template< typename StreamT, typename T >
893inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
894operator<< (StreamT&& strm, T const& value)
895{
896 strm.stream() << value;
897 return strm;
898}
899
900template< typename StreamT, typename T >
901inline typename boost::log::aux::enable_formatting_ostream_generic_operator< StreamT, T, false, StreamT& >::type
902operator<< (StreamT&& strm, T& value)
903{
904 strm.stream() << value;
905 return strm;
906}
907
908#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
909
910BOOST_LOG_CLOSE_NAMESPACE // namespace log
911
912} // namespace boost
913
914#include <boost/log/detail/footer.hpp>
915
916#endif // BOOST_LOG_UTILITY_FORMATTING_OSTREAM_HPP_INCLUDED_