attachable_sstream_buf.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2013.
  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 attachable_sstream_buf.hpp
  9. * \author Andrey Semashev
  10. * \date 29.07.2007
  11. *
  12. * \brief This header is the Boost.Log library implementation, see the library documentation
  13. * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
  14. */
  15. #ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
  16. #define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
  17. #include <memory>
  18. #include <string>
  19. #include <streambuf>
  20. #include <boost/assert.hpp>
  21. #include <boost/utility/addressof.hpp>
  22. #include <boost/log/detail/config.hpp>
  23. #include <boost/log/detail/header.hpp>
  24. #ifdef BOOST_HAS_PRAGMA_ONCE
  25. #pragma once
  26. #endif
  27. namespace boost {
  28. BOOST_LOG_OPEN_NAMESPACE
  29. namespace aux {
  30. //! A streambuf that puts the formatted data to an external string
  31. template<
  32. typename CharT,
  33. typename TraitsT = std::char_traits< CharT >,
  34. typename AllocatorT = std::allocator< CharT >
  35. >
  36. class basic_ostringstreambuf :
  37. public std::basic_streambuf< CharT, TraitsT >
  38. {
  39. //! Self type
  40. typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type;
  41. //! Base type
  42. typedef std::basic_streambuf< CharT, TraitsT > base_type;
  43. //! Buffer size
  44. enum { buffer_size = 16 };
  45. public:
  46. //! Character type
  47. typedef typename base_type::char_type char_type;
  48. //! Traits type
  49. typedef typename base_type::traits_type traits_type;
  50. //! String type
  51. typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
  52. //! Int type
  53. typedef typename base_type::int_type int_type;
  54. private:
  55. //! A reference to the string that will be filled
  56. string_type* m_Storage;
  57. //! A buffer used to temporarily store output
  58. char_type m_Buffer[buffer_size];
  59. public:
  60. //! Constructor
  61. explicit basic_ostringstreambuf() : m_Storage(0)
  62. {
  63. base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
  64. }
  65. //! Constructor
  66. explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage))
  67. {
  68. base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
  69. }
  70. //! Clears the buffer to the initial state
  71. void clear()
  72. {
  73. register char_type* pBase = this->pbase();
  74. register char_type* pPtr = this->pptr();
  75. if (pBase != pPtr)
  76. this->pbump(static_cast< int >(pBase - pPtr));
  77. }
  78. //! Detaches the buffer from the string
  79. void detach()
  80. {
  81. if (m_Storage)
  82. {
  83. this_type::sync();
  84. m_Storage = 0;
  85. }
  86. }
  87. //! Attaches the buffer to another string
  88. void attach(string_type& storage)
  89. {
  90. detach();
  91. m_Storage = boost::addressof(storage);
  92. }
  93. //! Returns a pointer to the attached string
  94. string_type* storage() const { return m_Storage; }
  95. protected:
  96. //! Puts all buffered data to the string
  97. int sync()
  98. {
  99. BOOST_ASSERT(m_Storage != 0);
  100. register char_type* pBase = this->pbase();
  101. register char_type* pPtr = this->pptr();
  102. if (pBase != pPtr)
  103. {
  104. m_Storage->append(pBase, pPtr);
  105. this->pbump(static_cast< int >(pBase - pPtr));
  106. }
  107. return 0;
  108. }
  109. //! Puts an unbuffered character to the string
  110. int_type overflow(int_type c)
  111. {
  112. BOOST_ASSERT(m_Storage != 0);
  113. basic_ostringstreambuf::sync();
  114. if (!traits_type::eq_int_type(c, traits_type::eof()))
  115. {
  116. m_Storage->push_back(traits_type::to_char_type(c));
  117. return c;
  118. }
  119. else
  120. return traits_type::not_eof(c);
  121. }
  122. //! Puts a character sequence to the string
  123. std::streamsize xsputn(const char_type* s, std::streamsize n)
  124. {
  125. BOOST_ASSERT(m_Storage != 0);
  126. basic_ostringstreambuf::sync();
  127. typedef typename string_type::size_type string_size_type;
  128. register const string_size_type max_storage_left =
  129. m_Storage->max_size() - m_Storage->size();
  130. if (static_cast< string_size_type >(n) < max_storage_left)
  131. {
  132. m_Storage->append(s, static_cast< string_size_type >(n));
  133. return n;
  134. }
  135. else
  136. {
  137. m_Storage->append(s, max_storage_left);
  138. return static_cast< std::streamsize >(max_storage_left);
  139. }
  140. }
  141. //! Copy constructor (closed)
  142. BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
  143. //! Assignment (closed)
  144. BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that))
  145. };
  146. } // namespace aux
  147. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  148. } // namespace boost
  149. #include <boost/log/detail/footer.hpp>
  150. #endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_