formatting_ostream.hpp 38 KB

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