static_ostream.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
  10. #define BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
  11. #include <locale>
  12. #include <ostream>
  13. #include <streambuf>
  14. namespace boost {
  15. namespace beast {
  16. namespace detail {
  17. // http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
  18. class static_ostream_buffer
  19. : public std::basic_streambuf<char>
  20. {
  21. using CharT = char;
  22. using Traits = std::char_traits<CharT>;
  23. using int_type = typename
  24. std::basic_streambuf<CharT, Traits>::int_type;
  25. using traits_type = typename
  26. std::basic_streambuf<CharT, Traits>::traits_type;
  27. char* data_;
  28. std::size_t size_;
  29. std::size_t len_ = 0;
  30. std::string s_;
  31. public:
  32. static_ostream_buffer(static_ostream_buffer&&) = delete;
  33. static_ostream_buffer(static_ostream_buffer const&) = delete;
  34. static_ostream_buffer(char* data, std::size_t size)
  35. : data_(data)
  36. , size_(size)
  37. {
  38. this->setp(data_, data_ + size - 1);
  39. }
  40. ~static_ostream_buffer() noexcept
  41. {
  42. }
  43. string_view
  44. str() const
  45. {
  46. if(! s_.empty())
  47. return {s_.data(), len_};
  48. return {data_, len_};
  49. }
  50. int_type
  51. overflow(int_type ch) override
  52. {
  53. if(! Traits::eq_int_type(ch, Traits::eof()))
  54. {
  55. Traits::assign(*this->pptr(),
  56. static_cast<CharT>(ch));
  57. flush(1);
  58. prepare();
  59. return ch;
  60. }
  61. flush();
  62. return traits_type::eof();
  63. }
  64. int
  65. sync() override
  66. {
  67. flush();
  68. prepare();
  69. return 0;
  70. }
  71. private:
  72. void
  73. prepare()
  74. {
  75. static auto const growth_factor = 1.5;
  76. if(len_ < size_ - 1)
  77. {
  78. this->setp(
  79. data_ + len_, data_ + size_ - 2);
  80. return;
  81. }
  82. if(s_.empty())
  83. {
  84. s_.resize(static_cast<std::size_t>(
  85. growth_factor * len_));
  86. Traits::copy(&s_[0], data_, len_);
  87. }
  88. else
  89. {
  90. s_.resize(static_cast<std::size_t>(
  91. growth_factor * len_));
  92. }
  93. this->setp(&s_[len_], &s_[len_] +
  94. s_.size() - len_ - 1);
  95. }
  96. void
  97. flush(int extra = 0)
  98. {
  99. len_ += static_cast<std::size_t>(
  100. this->pptr() - this->pbase() + extra);
  101. }
  102. };
  103. class static_ostream : public std::basic_ostream<char>
  104. {
  105. static_ostream_buffer osb_;
  106. public:
  107. static_ostream(char* data, std::size_t size)
  108. : std::basic_ostream<char>(&this->osb_)
  109. , osb_(data, size)
  110. {
  111. imbue(std::locale::classic());
  112. }
  113. string_view
  114. str() const
  115. {
  116. return osb_.str();
  117. }
  118. };
  119. } // detail
  120. } // beast
  121. } // boost
  122. #endif