File indexing completed on 2025-01-18 09:29:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
0011 #define BOOST_BEAST_DETAIL_OSTREAM_HPP
0012
0013 #include <boost/beast/core/buffers_prefix.hpp>
0014 #include <boost/beast/core/buffers_range.hpp>
0015 #include <boost/throw_exception.hpp>
0016 #include <boost/asio/buffer.hpp>
0017 #include <memory>
0018 #include <ostream>
0019 #include <streambuf>
0020 #include <type_traits>
0021 #include <utility>
0022
0023 namespace boost {
0024 namespace beast {
0025 namespace detail {
0026
0027 struct basic_streambuf_movable_helper :
0028 std::basic_streambuf<char, std::char_traits<char>>
0029 {
0030 basic_streambuf_movable_helper(
0031 basic_streambuf_movable_helper&&) = default;
0032 };
0033
0034 using basic_streambuf_movable =
0035 std::is_move_constructible<basic_streambuf_movable_helper>;
0036
0037 template<class DynamicBuffer,
0038 class CharT, class Traits, bool isMovable>
0039 class ostream_buffer;
0040
0041
0042
0043 template<class DynamicBuffer, class CharT, class Traits>
0044 class ostream_buffer
0045 <DynamicBuffer, CharT, Traits, true> final
0046 : public std::basic_streambuf<CharT, Traits>
0047 {
0048 using int_type = typename
0049 std::basic_streambuf<CharT, Traits>::int_type;
0050
0051 using traits_type = typename
0052 std::basic_streambuf<CharT, Traits>::traits_type;
0053
0054 DynamicBuffer& b_;
0055
0056 public:
0057 ostream_buffer(ostream_buffer&&) = default;
0058 ostream_buffer(ostream_buffer const&) = delete;
0059
0060 ~ostream_buffer() noexcept
0061 {
0062 sync();
0063 }
0064
0065 explicit
0066 ostream_buffer(DynamicBuffer& b)
0067 : b_(b)
0068 {
0069 b_.prepare(0);
0070 }
0071
0072 int_type
0073 overflow(int_type ch) override
0074 {
0075 BOOST_ASSERT(! Traits::eq_int_type(
0076 ch, Traits::eof()));
0077 sync();
0078
0079 static std::size_t constexpr max_size = 65536;
0080 auto const max_prepare = std::min<std::size_t>(
0081 std::max<std::size_t>(
0082 512, b_.capacity() - b_.size()),
0083 std::min<std::size_t>(
0084 max_size, b_.max_size() - b_.size()));
0085 if(max_prepare == 0)
0086 return Traits::eof();
0087 auto const bs = b_.prepare(max_prepare);
0088 auto const b = buffers_front(bs);
0089 auto const p = static_cast<CharT*>(b.data());
0090 this->setp(p, p + b.size() / sizeof(CharT));
0091
0092 BOOST_ASSERT(b_.capacity() > b_.size());
0093 return this->sputc(
0094 Traits::to_char_type(ch));
0095 }
0096
0097 int
0098 sync() override
0099 {
0100 b_.commit(
0101 (this->pptr() - this->pbase()) *
0102 sizeof(CharT));
0103 this->setp(nullptr, nullptr);
0104 return 0;
0105 }
0106 };
0107
0108
0109
0110
0111
0112
0113
0114 template<class DynamicBuffer, class CharT, class Traits>
0115 class ostream_buffer
0116 <DynamicBuffer, CharT, Traits, false>
0117 : public std::basic_streambuf<CharT, Traits>
0118 {
0119 using int_type = typename
0120 std::basic_streambuf<CharT, Traits>::int_type;
0121
0122 using traits_type = typename
0123 std::basic_streambuf<CharT, Traits>::traits_type;
0124
0125 DynamicBuffer& b_;
0126
0127 public:
0128 ostream_buffer(ostream_buffer&&) = delete;
0129 ostream_buffer(ostream_buffer const&) = delete;
0130
0131 ~ostream_buffer() noexcept
0132 {
0133 sync();
0134 }
0135
0136 explicit
0137 ostream_buffer(DynamicBuffer& b)
0138 : b_(b)
0139 {
0140 }
0141
0142 int_type
0143 overflow(int_type ch) override
0144 {
0145 BOOST_ASSERT(! Traits::eq_int_type(
0146 ch, Traits::eof()));
0147 sync();
0148
0149 static std::size_t constexpr max_size = 65536;
0150 auto const max_prepare = std::min<std::size_t>(
0151 std::max<std::size_t>(
0152 512, b_.capacity() - b_.size()),
0153 std::min<std::size_t>(
0154 max_size, b_.max_size() - b_.size()));
0155 if(max_prepare == 0)
0156 return Traits::eof();
0157 auto const bs = b_.prepare(max_prepare);
0158 auto const b = buffers_front(bs);
0159 auto const p = static_cast<CharT*>(b.data());
0160 this->setp(p, p + b.size() / sizeof(CharT));
0161
0162 BOOST_ASSERT(b_.capacity() > b_.size());
0163 return this->sputc(
0164 Traits::to_char_type(ch));
0165 }
0166
0167 int
0168 sync() override
0169 {
0170 b_.commit(
0171 (this->pptr() - this->pbase()) *
0172 sizeof(CharT));
0173 this->setp(nullptr, nullptr);
0174 return 0;
0175 }
0176 };
0177
0178
0179
0180 template<class DynamicBuffer,
0181 class CharT, class Traits, bool isMovable>
0182 class ostream_helper;
0183
0184 template<class DynamicBuffer, class CharT, class Traits>
0185 class ostream_helper<
0186 DynamicBuffer, CharT, Traits, true>
0187 : public std::basic_ostream<CharT, Traits>
0188 {
0189 ostream_buffer<
0190 DynamicBuffer, CharT, Traits, true> osb_;
0191
0192 public:
0193 explicit
0194 ostream_helper(DynamicBuffer& b);
0195
0196 ostream_helper(ostream_helper&& other);
0197 };
0198
0199 template<class DynamicBuffer, class CharT, class Traits>
0200 ostream_helper<DynamicBuffer, CharT, Traits, true>::
0201 ostream_helper(DynamicBuffer& b)
0202 : std::basic_ostream<CharT, Traits>(&this->osb_)
0203 , osb_(b)
0204 {
0205 }
0206
0207 template<class DynamicBuffer, class CharT, class Traits>
0208 ostream_helper<DynamicBuffer, CharT, Traits, true>::
0209 ostream_helper(ostream_helper&& other)
0210 : std::basic_ostream<CharT, Traits>(&osb_)
0211 , osb_(std::move(other.osb_))
0212 {
0213 }
0214
0215
0216
0217
0218 template<class T>
0219 class ostream_helper_base
0220 {
0221 protected:
0222 std::unique_ptr<T> member;
0223
0224 ostream_helper_base(
0225 ostream_helper_base&&) = default;
0226
0227 explicit
0228 ostream_helper_base(T* t)
0229 : member(t)
0230 {
0231 }
0232 };
0233
0234 template<class DynamicBuffer, class CharT, class Traits>
0235 class ostream_helper<
0236 DynamicBuffer, CharT, Traits, false>
0237 : private ostream_helper_base<ostream_buffer<
0238 DynamicBuffer, CharT, Traits, false>>
0239 , public std::basic_ostream<CharT, Traits>
0240 {
0241 public:
0242 explicit
0243 ostream_helper(DynamicBuffer& b)
0244 : ostream_helper_base<ostream_buffer<
0245 DynamicBuffer, CharT, Traits, false>>(
0246 new ostream_buffer<DynamicBuffer,
0247 CharT, Traits, false>(b))
0248 , std::basic_ostream<CharT, Traits>(
0249 this->member.get())
0250 {
0251 }
0252
0253 ostream_helper(ostream_helper&& other)
0254 : ostream_helper_base<ostream_buffer<
0255 DynamicBuffer, CharT, Traits, false>>(
0256 std::move(other))
0257 , std::basic_ostream<CharT, Traits>(
0258 this->member.get())
0259 {
0260 }
0261 };
0262
0263 }
0264 }
0265 }
0266
0267 #endif