ゴミ箱
ostream.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2017 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 
10 #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
11 #define BOOST_BEAST_DETAIL_OSTREAM_HPP
12 
13 #include <boost/asio/buffer.hpp>
15 #include <memory>
16 #include <iosfwd>
17 #include <streambuf>
18 #include <type_traits>
19 #include <utility>
20 
21 namespace boost {
22 namespace beast {
23 namespace detail {
24 
25 template<class Buffers>
27 {
28  Buffers b_;
29 
30 public:
31  explicit
32  buffers_helper(Buffers const& b)
33  : b_(b)
34  {
35  }
36 
37  template<class B>
38  friend
41  buffers_helper<B> const& v);
42 };
43 
44 template<class Buffers>
47  buffers_helper<Buffers> const& v)
48 {
49  using boost::asio::buffer_cast;
50  using boost::asio::buffer_size;
51  for(boost::asio::const_buffer b : v.b_)
52  os.write(buffer_cast<char const*>(b),
53  buffer_size(b));
54  return os;
55 }
56 
57 //------------------------------------------------------------------------------
58 
60  std::basic_streambuf<char, std::char_traits<char>>
61 {
63  basic_streambuf_movable_helper&&) = default;
64 };
65 
67  std::is_move_constructible<basic_streambuf_movable_helper>;
68 
69 //------------------------------------------------------------------------------
70 
71 template<class DynamicBuffer,
72  class CharT, class Traits, bool isMovable>
74 
75 template<class DynamicBuffer, class CharT, class Traits>
77  <DynamicBuffer, CharT, Traits, true>
78  : public std::basic_streambuf<CharT, Traits>
79 {
80  using int_type = typename
81  std::basic_streambuf<CharT, Traits>::int_type;
82 
83  using traits_type = typename
84  std::basic_streambuf<CharT, Traits>::traits_type;
85 
86  static std::size_t constexpr max_size = 512;
87 
88  DynamicBuffer& buf_;
89 
90 public:
91  ostream_buffer(ostream_buffer&&) = default;
92  ostream_buffer(ostream_buffer const&) = delete;
93 
94  ~ostream_buffer() noexcept
95  {
96  sync();
97  }
98 
99  explicit
100  ostream_buffer(DynamicBuffer& buf)
101  : buf_(buf)
102  {
103  prepare();
104  }
105 
106  int_type
107  overflow(int_type ch) override
108  {
109  if(! Traits::eq_int_type(ch, Traits::eof()))
110  {
111  Traits::assign(*this->pptr(),
112  static_cast<CharT>(ch));
113  flush(1);
114  prepare();
115  return ch;
116  }
117  flush();
118  return traits_type::eof();
119  }
120 
121  int
122  sync() override
123  {
124  flush();
125  prepare();
126  return 0;
127  }
128 
129 private:
130  void
131  prepare()
132  {
133  using boost::asio::buffer_cast;
134  using boost::asio::buffer_size;
135  auto mbs = buf_.prepare(
136  read_size_or_throw(buf_, max_size));
137  auto const mb = *mbs.begin();
138  auto const p = buffer_cast<CharT*>(mb);
139  this->setp(p,
140  p + buffer_size(mb) / sizeof(CharT) - 1);
141  }
142 
143  void
144  flush(int extra = 0)
145  {
146  buf_.commit(
147  (this->pptr() - this->pbase() + extra) *
148  sizeof(CharT));
149  }
150 };
151 
152 // This nonsense is all to work around a glitch in libstdc++
153 // where std::basic_streambuf copy constructor is private:
154 // https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799
155 
156 template<class DynamicBuffer, class CharT, class Traits>
158  <DynamicBuffer, CharT, Traits, false>
159  : public std::basic_streambuf<CharT, Traits>
160 {
161  using int_type = typename
162  std::basic_streambuf<CharT, Traits>::int_type;
163 
164  using traits_type = typename
165  std::basic_streambuf<CharT, Traits>::traits_type;
166 
167  static std::size_t constexpr max_size = 512;
168 
169  DynamicBuffer& buf_;
170 
171 public:
172  ostream_buffer(ostream_buffer&&) = delete;
173  ostream_buffer(ostream_buffer const&) = delete;
174 
175  ~ostream_buffer() noexcept
176  {
177  sync();
178  }
179 
180  explicit
181  ostream_buffer(DynamicBuffer& buf)
182  : buf_(buf)
183  {
184  prepare();
185  }
186 
187  int_type
188  overflow(int_type ch) override
189  {
190  if(! Traits::eq_int_type(ch, Traits::eof()))
191  {
192  Traits::assign(*this->pptr(),
193  static_cast<CharT>(ch));
194  flush(1);
195  prepare();
196  return ch;
197  }
198  flush();
199  return traits_type::eof();
200  }
201 
202  int
203  sync() override
204  {
205  flush();
206  prepare();
207  return 0;
208  }
209 
210 private:
211  void
212  prepare()
213  {
214  using boost::asio::buffer_cast;
215  using boost::asio::buffer_size;
216  auto mbs = buf_.prepare(
217  read_size_or_throw(buf_, max_size));
218  auto const mb = *mbs.begin();
219  auto const p = buffer_cast<CharT*>(mb);
220  this->setp(p,
221  p + buffer_size(mb) / sizeof(CharT) - 1);
222  }
223 
224  void
225  flush(int extra = 0)
226  {
227  buf_.commit(
228  (this->pptr() - this->pbase() + extra) *
229  sizeof(CharT));
230  }
231 };
232 
233 //------------------------------------------------------------------------------
234 
235 template<class DynamicBuffer,
236  class CharT, class Traits, bool isMovable>
238 
239 template<class DynamicBuffer, class CharT, class Traits>
241  DynamicBuffer, CharT, Traits, true>
242  : public std::basic_ostream<CharT, Traits>
243 {
245  DynamicBuffer, CharT, Traits, true> osb_;
246 
247 public:
248  explicit
249  ostream_helper(DynamicBuffer& buf);
250 
252 };
253 
254 template<class DynamicBuffer, class CharT, class Traits>
256 ostream_helper(DynamicBuffer& buf)
257  : std::basic_ostream<CharT, Traits>(
258  &this->osb_)
259  , osb_(buf)
260 {
261 }
262 
263 template<class DynamicBuffer, class CharT, class Traits>
266  ostream_helper&& other)
267  : std::basic_ostream<CharT, Traits>(&osb_)
268  , osb_(std::move(other.osb_))
269 {
270 }
271 
272 // This work-around is for libstdc++ versions that
273 // don't have a movable std::basic_streambuf
274 
275 template<class T>
277 {
278 protected:
279  std::unique_ptr<T> member;
280 
282  ostream_helper_base&&) = default;
283 
284  explicit
286  : member(t)
287  {
288  }
289 };
290 
291 template<class DynamicBuffer, class CharT, class Traits>
293  DynamicBuffer, CharT, Traits, false>
294  : private ostream_helper_base<ostream_buffer<
295  DynamicBuffer, CharT, Traits, false>>
296  , public std::basic_ostream<CharT, Traits>
297 {
298 public:
299  explicit
300  ostream_helper(DynamicBuffer& buf)
302  DynamicBuffer, CharT, Traits, false>>(
303  new ostream_buffer<DynamicBuffer,
304  CharT, Traits, false>(buf))
305  , std::basic_ostream<CharT, Traits>(this->member.get())
306  {
307  }
308 
311  DynamicBuffer, CharT, Traits, false>>(
312  std::move(other))
313  , std::basic_ostream<CharT, Traits>(this->member.get())
314  {
315  }
316 };
317 
318 } // detail
319 } // beast
320 } // boost
321 
322 #endif
std::is_move_constructible< basic_streambuf_movable_helper > basic_streambuf_movable
Definition: ostream.hpp:67
Definition: async_result.hpp:20
detail::ostream_helper< DynamicBuffer, char, std::char_traits< char >, detail::basic_streambuf_movable::value > ostream(DynamicBuffer &buffer)
Definition: ostream.hpp:91
STL namespace.
buffers_helper(Buffers const &b)
Definition: ostream.hpp:32
ostream_helper(DynamicBuffer &buf)
Definition: ostream.hpp:300
ostream_buffer(DynamicBuffer &buf)
Definition: ostream.hpp:100
Definition: ostream.hpp:26
std::unique_ptr< T > member
Definition: ostream.hpp:279
friend std::ostream & operator<<(std::ostream &os, buffers_helper< B > const &v)
ostream_helper_base(T *t)
Definition: ostream.hpp:285
std::size_t read_size_or_throw(DynamicBuffer &buffer, std::size_t max_size)
Definition: read_size.ipp:66
int_type overflow(int_type ch) override
Definition: ostream.hpp:188
int_type overflow(int_type ch) override
Definition: ostream.hpp:107
Definition: ostream.hpp:237
ostream_helper(ostream_helper &&other)
Definition: ostream.hpp:309
Definition: ostream.hpp:73