]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-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 | ||
8 | #ifndef BEAST_IMPL_BUFFERS_ADAPTER_IPP | |
9 | #define BEAST_IMPL_BUFFERS_ADAPTER_IPP | |
10 | ||
11 | #include <beast/core/detail/type_traits.hpp> | |
12 | #include <boost/asio/buffer.hpp> | |
13 | #include <algorithm> | |
14 | #include <cstring> | |
15 | #include <iterator> | |
16 | #include <stdexcept> | |
17 | #include <type_traits> | |
18 | ||
19 | namespace beast { | |
20 | ||
21 | template<class MutableBufferSequence> | |
22 | class buffers_adapter<MutableBufferSequence>:: | |
23 | const_buffers_type | |
24 | { | |
25 | buffers_adapter const* ba_; | |
26 | ||
27 | public: | |
28 | using value_type = boost::asio::const_buffer; | |
29 | ||
30 | class const_iterator; | |
31 | ||
32 | const_buffers_type() = delete; | |
33 | const_buffers_type( | |
34 | const_buffers_type const&) = default; | |
35 | const_buffers_type& operator=( | |
36 | const_buffers_type const&) = default; | |
37 | ||
38 | const_iterator | |
39 | begin() const; | |
40 | ||
41 | const_iterator | |
42 | end() const; | |
43 | ||
44 | private: | |
45 | friend class buffers_adapter; | |
46 | ||
47 | const_buffers_type(buffers_adapter const& ba) | |
48 | : ba_(&ba) | |
49 | { | |
50 | } | |
51 | }; | |
52 | ||
53 | template<class MutableBufferSequence> | |
54 | class buffers_adapter<MutableBufferSequence>:: | |
55 | const_buffers_type::const_iterator | |
56 | { | |
57 | iter_type it_; | |
58 | buffers_adapter const* ba_ = nullptr; | |
59 | ||
60 | public: | |
61 | using value_type = boost::asio::const_buffer; | |
62 | using pointer = value_type const*; | |
63 | using reference = value_type; | |
64 | using difference_type = std::ptrdiff_t; | |
65 | using iterator_category = | |
66 | std::bidirectional_iterator_tag; | |
67 | ||
68 | const_iterator() = default; | |
69 | const_iterator(const_iterator&& other) = default; | |
70 | const_iterator(const_iterator const& other) = default; | |
71 | const_iterator& operator=(const_iterator&& other) = default; | |
72 | const_iterator& operator=(const_iterator const& other) = default; | |
73 | ||
74 | bool | |
75 | operator==(const_iterator const& other) const | |
76 | { | |
77 | return ba_ == other.ba_ && | |
78 | it_ == other.it_; | |
79 | } | |
80 | ||
81 | bool | |
82 | operator!=(const_iterator const& other) const | |
83 | { | |
84 | return !(*this == other); | |
85 | } | |
86 | ||
87 | reference | |
88 | operator*() const | |
89 | { | |
90 | using boost::asio::buffer_cast; | |
91 | using boost::asio::buffer_size; | |
92 | return value_type{buffer_cast<void const*>(*it_), | |
93 | (ba_->out_ == ba_->bs_.end() || | |
94 | it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} + | |
95 | (it_ == ba_->begin_ ? ba_->in_pos_ : 0); | |
96 | } | |
97 | ||
98 | pointer | |
99 | operator->() const = delete; | |
100 | ||
101 | const_iterator& | |
102 | operator++() | |
103 | { | |
104 | ++it_; | |
105 | return *this; | |
106 | } | |
107 | ||
108 | const_iterator | |
109 | operator++(int) | |
110 | { | |
111 | auto temp = *this; | |
112 | ++(*this); | |
113 | return temp; | |
114 | } | |
115 | ||
116 | const_iterator& | |
117 | operator--() | |
118 | { | |
119 | --it_; | |
120 | return *this; | |
121 | } | |
122 | ||
123 | const_iterator | |
124 | operator--(int) | |
125 | { | |
126 | auto temp = *this; | |
127 | --(*this); | |
128 | return temp; | |
129 | } | |
130 | ||
131 | private: | |
132 | friend class const_buffers_type; | |
133 | ||
134 | const_iterator(buffers_adapter const& ba, | |
135 | iter_type iter) | |
136 | : it_(iter) | |
137 | , ba_(&ba) | |
138 | { | |
139 | } | |
140 | }; | |
141 | ||
142 | template<class MutableBufferSequence> | |
143 | inline | |
144 | auto | |
145 | buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const -> | |
146 | const_iterator | |
147 | { | |
148 | return const_iterator{*ba_, ba_->begin_}; | |
149 | } | |
150 | ||
151 | template<class MutableBufferSequence> | |
152 | inline | |
153 | auto | |
154 | buffers_adapter<MutableBufferSequence>::const_buffers_type::end() const -> | |
155 | const_iterator | |
156 | { | |
157 | return const_iterator{*ba_, ba_->out_ == | |
158 | ba_->end_ ? ba_->end_ : std::next(ba_->out_)}; | |
159 | } | |
160 | ||
161 | //------------------------------------------------------------------------------ | |
162 | ||
163 | template<class MutableBufferSequence> | |
164 | class buffers_adapter<MutableBufferSequence>:: | |
165 | mutable_buffers_type | |
166 | { | |
167 | buffers_adapter const* ba_; | |
168 | ||
169 | public: | |
170 | using value_type = boost::asio::mutable_buffer; | |
171 | ||
172 | class const_iterator; | |
173 | ||
174 | mutable_buffers_type() = delete; | |
175 | mutable_buffers_type( | |
176 | mutable_buffers_type const&) = default; | |
177 | mutable_buffers_type& operator=( | |
178 | mutable_buffers_type const&) = default; | |
179 | ||
180 | const_iterator | |
181 | begin() const; | |
182 | ||
183 | const_iterator | |
184 | end() const; | |
185 | ||
186 | private: | |
187 | friend class buffers_adapter; | |
188 | ||
189 | mutable_buffers_type( | |
190 | buffers_adapter const& ba) | |
191 | : ba_(&ba) | |
192 | { | |
193 | } | |
194 | }; | |
195 | ||
196 | template<class MutableBufferSequence> | |
197 | class buffers_adapter<MutableBufferSequence>:: | |
198 | mutable_buffers_type::const_iterator | |
199 | { | |
200 | iter_type it_; | |
201 | buffers_adapter const* ba_ = nullptr; | |
202 | ||
203 | public: | |
204 | using value_type = boost::asio::mutable_buffer; | |
205 | using pointer = value_type const*; | |
206 | using reference = value_type; | |
207 | using difference_type = std::ptrdiff_t; | |
208 | using iterator_category = | |
209 | std::bidirectional_iterator_tag; | |
210 | ||
211 | const_iterator() = default; | |
212 | const_iterator(const_iterator&& other) = default; | |
213 | const_iterator(const_iterator const& other) = default; | |
214 | const_iterator& operator=(const_iterator&& other) = default; | |
215 | const_iterator& operator=(const_iterator const& other) = default; | |
216 | ||
217 | bool | |
218 | operator==(const_iterator const& other) const | |
219 | { | |
220 | return ba_ == other.ba_ && | |
221 | it_ == other.it_; | |
222 | } | |
223 | ||
224 | bool | |
225 | operator!=(const_iterator const& other) const | |
226 | { | |
227 | return !(*this == other); | |
228 | } | |
229 | ||
230 | reference | |
231 | operator*() const | |
232 | { | |
233 | using boost::asio::buffer_cast; | |
234 | using boost::asio::buffer_size; | |
235 | return value_type{buffer_cast<void*>(*it_), | |
236 | it_ == std::prev(ba_->end_) ? | |
237 | ba_->out_end_ : buffer_size(*it_)} + | |
238 | (it_ == ba_->out_ ? ba_->out_pos_ : 0); | |
239 | } | |
240 | ||
241 | pointer | |
242 | operator->() const = delete; | |
243 | ||
244 | const_iterator& | |
245 | operator++() | |
246 | { | |
247 | ++it_; | |
248 | return *this; | |
249 | } | |
250 | ||
251 | const_iterator | |
252 | operator++(int) | |
253 | { | |
254 | auto temp = *this; | |
255 | ++(*this); | |
256 | return temp; | |
257 | } | |
258 | ||
259 | const_iterator& | |
260 | operator--() | |
261 | { | |
262 | --it_; | |
263 | return *this; | |
264 | } | |
265 | ||
266 | const_iterator | |
267 | operator--(int) | |
268 | { | |
269 | auto temp = *this; | |
270 | --(*this); | |
271 | return temp; | |
272 | } | |
273 | ||
274 | private: | |
275 | friend class mutable_buffers_type; | |
276 | ||
277 | const_iterator(buffers_adapter const& ba, | |
278 | iter_type iter) | |
279 | : it_(iter) | |
280 | , ba_(&ba) | |
281 | { | |
282 | } | |
283 | }; | |
284 | ||
285 | template<class MutableBufferSequence> | |
286 | inline | |
287 | auto | |
288 | buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const -> | |
289 | const_iterator | |
290 | { | |
291 | return const_iterator{*ba_, ba_->out_}; | |
292 | } | |
293 | ||
294 | template<class MutableBufferSequence> | |
295 | inline | |
296 | auto | |
297 | buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const -> | |
298 | const_iterator | |
299 | { | |
300 | return const_iterator{*ba_, ba_->end_}; | |
301 | } | |
302 | ||
303 | //------------------------------------------------------------------------------ | |
304 | ||
305 | template<class MutableBufferSequence> | |
306 | buffers_adapter<MutableBufferSequence>::buffers_adapter( | |
307 | buffers_adapter&& other) | |
308 | : buffers_adapter(std::move(other), | |
309 | std::distance<iter_type>(other.bs_.begin(), other.begin_), | |
310 | std::distance<iter_type>(other.bs_.begin(), other.out_), | |
311 | std::distance<iter_type>(other.bs_.begin(), other.end_)) | |
312 | { | |
313 | } | |
314 | ||
315 | template<class MutableBufferSequence> | |
316 | buffers_adapter<MutableBufferSequence>::buffers_adapter( | |
317 | buffers_adapter const& other) | |
318 | : buffers_adapter(other, | |
319 | std::distance<iter_type>(other.bs_.begin(), other.begin_), | |
320 | std::distance<iter_type>(other.bs_.begin(), other.out_), | |
321 | std::distance<iter_type>(other.bs_.begin(), other.end_)) | |
322 | { | |
323 | } | |
324 | ||
325 | template<class MutableBufferSequence> | |
326 | auto | |
327 | buffers_adapter<MutableBufferSequence>::operator=( | |
328 | buffers_adapter&& other) -> buffers_adapter& | |
329 | { | |
330 | auto const nbegin = std::distance<iter_type>( | |
331 | other.bs_.begin(), other.begin_); | |
332 | auto const nout = std::distance<iter_type>( | |
333 | other.bs_.begin(), other.out_); | |
334 | auto const nend = std::distance<iter_type>( | |
335 | other.bs_.begin(), other.end_); | |
336 | bs_ = std::move(other.bs_); | |
337 | begin_ = std::next(bs_.begin(), nbegin); | |
338 | out_ = std::next(bs_.begin(), nout); | |
339 | end_ = std::next(bs_.begin(), nend); | |
340 | max_size_ = other.max_size_; | |
341 | in_pos_ = other.in_pos_; | |
342 | in_size_ = other.in_size_; | |
343 | out_pos_ = other.out_pos_; | |
344 | out_end_ = other.out_end_; | |
345 | return *this; | |
346 | } | |
347 | ||
348 | template<class MutableBufferSequence> | |
349 | auto | |
350 | buffers_adapter<MutableBufferSequence>::operator=( | |
351 | buffers_adapter const& other) -> buffers_adapter& | |
352 | { | |
353 | auto const nbegin = std::distance<iter_type>( | |
354 | other.bs_.begin(), other.begin_); | |
355 | auto const nout = std::distance<iter_type>( | |
356 | other.bs_.begin(), other.out_); | |
357 | auto const nend = std::distance<iter_type>( | |
358 | other.bs_.begin(), other.end_); | |
359 | bs_ = other.bs_; | |
360 | begin_ = std::next(bs_.begin(), nbegin); | |
361 | out_ = std::next(bs_.begin(), nout); | |
362 | end_ = std::next(bs_.begin(), nend); | |
363 | max_size_ = other.max_size_; | |
364 | in_pos_ = other.in_pos_; | |
365 | in_size_ = other.in_size_; | |
366 | out_pos_ = other.out_pos_; | |
367 | out_end_ = other.out_end_; | |
368 | return *this; | |
369 | } | |
370 | ||
371 | template<class MutableBufferSequence> | |
372 | buffers_adapter<MutableBufferSequence>::buffers_adapter( | |
373 | MutableBufferSequence const& bs) | |
374 | : bs_(bs) | |
375 | , begin_(bs_.begin()) | |
376 | , out_(bs_.begin()) | |
377 | , end_(bs_.begin()) | |
378 | , max_size_(boost::asio::buffer_size(bs_)) | |
379 | { | |
380 | } | |
381 | ||
382 | template<class MutableBufferSequence> | |
383 | auto | |
384 | buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) -> | |
385 | mutable_buffers_type | |
386 | { | |
387 | using boost::asio::buffer_size; | |
388 | end_ = out_; | |
389 | if(end_ != bs_.end()) | |
390 | { | |
391 | auto size = buffer_size(*end_) - out_pos_; | |
392 | if(n > size) | |
393 | { | |
394 | n -= size; | |
395 | while(++end_ != bs_.end()) | |
396 | { | |
397 | size = buffer_size(*end_); | |
398 | if(n < size) | |
399 | { | |
400 | out_end_ = n; | |
401 | n = 0; | |
402 | ++end_; | |
403 | break; | |
404 | } | |
405 | n -= size; | |
406 | out_end_ = size; | |
407 | } | |
408 | } | |
409 | else | |
410 | { | |
411 | ++end_; | |
412 | out_end_ = out_pos_ + n; | |
413 | n = 0; | |
414 | } | |
415 | } | |
416 | if(n > 0) | |
417 | throw detail::make_exception<std::length_error>( | |
418 | "no space", __FILE__, __LINE__); | |
419 | return mutable_buffers_type{*this}; | |
420 | } | |
421 | ||
422 | template<class MutableBufferSequence> | |
423 | void | |
424 | buffers_adapter<MutableBufferSequence>::commit(std::size_t n) | |
425 | { | |
426 | using boost::asio::buffer_size; | |
427 | if(out_ == end_) | |
428 | return; | |
429 | auto const last = std::prev(end_); | |
430 | while(out_ != last) | |
431 | { | |
432 | auto const avail = | |
433 | buffer_size(*out_) - out_pos_; | |
434 | if(n < avail) | |
435 | { | |
436 | out_pos_ += n; | |
437 | in_size_ += n; | |
438 | max_size_ -= n; | |
439 | return; | |
440 | } | |
441 | ++out_; | |
442 | n -= avail; | |
443 | out_pos_ = 0; | |
444 | in_size_ += avail; | |
445 | max_size_ -= avail; | |
446 | } | |
447 | ||
448 | n = (std::min)(n, out_end_ - out_pos_); | |
449 | out_pos_ += n; | |
450 | in_size_ += n; | |
451 | max_size_ -= n; | |
452 | if(out_pos_ == buffer_size(*out_)) | |
453 | { | |
454 | ++out_; | |
455 | out_pos_ = 0; | |
456 | out_end_ = 0; | |
457 | } | |
458 | } | |
459 | ||
460 | template<class MutableBufferSequence> | |
461 | inline | |
462 | auto | |
463 | buffers_adapter<MutableBufferSequence>::data() const -> | |
464 | const_buffers_type | |
465 | { | |
466 | return const_buffers_type{*this}; | |
467 | } | |
468 | ||
469 | template<class MutableBufferSequence> | |
470 | void | |
471 | buffers_adapter<MutableBufferSequence>::consume(std::size_t n) | |
472 | { | |
473 | using boost::asio::buffer_size; | |
474 | while(begin_ != out_) | |
475 | { | |
476 | auto const avail = | |
477 | buffer_size(*begin_) - in_pos_; | |
478 | if(n < avail) | |
479 | { | |
480 | in_size_ -= n; | |
481 | in_pos_ += n; | |
482 | return; | |
483 | } | |
484 | n -= avail; | |
485 | in_size_ -= avail; | |
486 | in_pos_ = 0; | |
487 | ++begin_; | |
488 | } | |
489 | auto const avail = out_pos_ - in_pos_; | |
490 | if(n < avail) | |
491 | { | |
492 | in_size_ -= n; | |
493 | in_pos_ += n; | |
494 | } | |
495 | else | |
496 | { | |
497 | in_size_ -= avail; | |
498 | in_pos_ = out_pos_; | |
499 | } | |
500 | } | |
501 | ||
502 | } // beast | |
503 | ||
504 | #endif |