]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/experimental/buffer
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / experimental / buffer
CommitLineData
e5989e71
JW
1// <experimental/buffer> -*- C++ -*-
2
8d9254fc 3// Copyright (C) 2015-2020 Free Software Foundation, Inc.
e5989e71
JW
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file experimental/buffer
26 * This is a TS C++ Library header.
3084625d 27 * @ingroup networking-ts
e5989e71
JW
28 */
29
30#ifndef _GLIBCXX_EXPERIMENTAL_BUFFER
31#define _GLIBCXX_EXPERIMENTAL_BUFFER 1
32
33#pragma GCC system_header
34
35#if __cplusplus >= 201402L
36
37#include <array>
38#include <string>
39#include <system_error>
40#include <vector>
41#include <cstring>
42#include <experimental/string_view>
43#include <experimental/bits/net.h>
44
45namespace std _GLIBCXX_VISIBILITY(default)
46{
a70a4be9 47_GLIBCXX_BEGIN_NAMESPACE_VERSION
e5989e71
JW
48namespace experimental
49{
50namespace net
51{
52inline namespace v1
53{
e5989e71 54
3084625d
JW
55 /** @addtogroup networking-ts
56 * @{
e5989e71
JW
57 */
58
59 enum class stream_errc { // TODO decide values
60 eof = 1,
61 not_found = 2
62 };
63
64 const error_category& stream_category() noexcept // TODO not inline
65 {
66 struct __cat : error_category
67 {
68 const char* name() const noexcept { return "stream"; }
69
70 std::string message(int __e) const
71 {
72 if (__e == (int)stream_errc::eof)
73 return "EOF";
74 else if (__e == (int)stream_errc::not_found)
75 return "not found";
76 return "stream";
77 }
78
79 virtual void __message(int) { } // TODO dual ABI XXX
80 };
81 static __cat __c;
82 return __c;
83 }
84
85 inline error_code
86 make_error_code(stream_errc __e) noexcept
87 { return error_code(static_cast<int>(__e), stream_category()); }
88
89 inline error_condition
90 make_error_condition(stream_errc __e) noexcept
91 { return error_condition(static_cast<int>(__e), stream_category()); }
92
93 class mutable_buffer
94 {
95 public:
96 // constructors:
97 mutable_buffer() noexcept : _M_data(), _M_size() { }
98
99 mutable_buffer(void* __p, size_t __n) noexcept
100 : _M_data(__p), _M_size(__n) { }
101
102 // members:
103 void* data() const noexcept { return _M_data; }
104 size_t size() const noexcept { return _M_size; }
105
106 private:
107 void* _M_data;
108 size_t _M_size;
109 };
110
111 class const_buffer
112 {
113 public:
114 // constructors:
115 const_buffer() noexcept : _M_data(), _M_size() { }
116
117 const_buffer(const void* __p, size_t __n) noexcept
118 : _M_data(__p), _M_size(__n) { }
119
120 const_buffer(const mutable_buffer& __b) noexcept
121 : _M_data(__b.data()), _M_size(__b.size()) { }
122
123 // members:
124 const void* data() const noexcept { return _M_data; }
125 size_t size() const noexcept { return _M_size; }
126
127 private:
128 const void* _M_data;
129 size_t _M_size;
130 };
131
132
133 /** @brief buffer sequence access
134 *
135 * Uniform access to types that meet the BufferSequence requirements.
136 * @{
137 */
138
139 inline const mutable_buffer*
140 buffer_sequence_begin(const mutable_buffer& __b)
141 { return std::addressof(__b); }
142
143 inline const const_buffer*
144 buffer_sequence_begin(const const_buffer& __b)
145 { return std::addressof(__b); }
146
147 inline const mutable_buffer*
148 buffer_sequence_end(const mutable_buffer& __b)
149 { return std::addressof(__b) + 1; }
150
151 inline const const_buffer*
152 buffer_sequence_end(const const_buffer& __b)
153 { return std::addressof(__b) + 1; }
154
155 template<typename _Cont>
156 auto
157 buffer_sequence_begin(_Cont& __c) -> decltype(__c.begin())
158 { return __c.begin(); }
159
160 template<typename _Cont>
161 auto
162 buffer_sequence_begin(const _Cont& __c) -> decltype(__c.begin())
163 { return __c.begin(); }
164
165 template<typename _Cont>
166 auto
167 buffer_sequence_end(_Cont& __c) -> decltype(__c.end())
168 { return __c.end(); }
169
170 template<typename _Cont>
171 auto
172 buffer_sequence_end(const _Cont& __c) -> decltype(__c.end())
173 { return __c.end(); }
174
175 // @}
176
177
178 /** @brief buffer type traits
179 *
180 * @{
181 */
182
183 template<typename _Tp, typename _Buffer,
184 typename _Begin
185 = decltype(net::buffer_sequence_begin(std::declval<_Tp&>())),
186 typename _End
187 = decltype(net::buffer_sequence_end(std::declval<_Tp&>()))>
188 using __buffer_sequence = enable_if_t<__and_<
189 __is_value_constructible<_Tp>, is_same<_Begin, _End>,
190 is_convertible<typename iterator_traits<_Begin>::value_type, _Buffer>
191 >::value>;
192
193 template<typename _Tp, typename _Buffer, typename = void>
194 struct __is_buffer_sequence : false_type
195 { };
196
197 template<typename _Tp, typename _Buffer>
198 struct __is_buffer_sequence<_Tp, _Buffer, __buffer_sequence<_Tp, _Buffer>>
199 : true_type
200 { };
201
202 template<typename _Tp>
203 struct is_mutable_buffer_sequence
204 : __is_buffer_sequence<_Tp, mutable_buffer>::type
205 { };
206
207 template<typename _Tp>
208 struct is_const_buffer_sequence
209 : __is_buffer_sequence<_Tp, const_buffer>::type
210 { };
211
212 template<typename _Tp>
213 constexpr bool is_mutable_buffer_sequence_v
214 = is_mutable_buffer_sequence<_Tp>::value;
215
216 template<typename _Tp>
217 constexpr bool is_const_buffer_sequence_v
218 = is_const_buffer_sequence<_Tp>::value;
219
220 template<typename _Tp, typename = void>
221 struct __is_dynamic_buffer_impl : false_type
222 { };
223
224 // Check DynamicBuffer requirements.
225 template<typename _Tp, typename _Up = remove_const_t<_Tp>>
226 auto
227 __dynamic_buffer_reqs(_Up* __x = 0, const _Up* __x1 = 0, size_t __n = 0)
228 -> enable_if_t<__and_<
229 is_move_constructible<_Up>,
230 is_const_buffer_sequence<typename _Tp::const_buffers_type>,
231 is_mutable_buffer_sequence<typename _Tp::mutable_buffers_type>,
232 is_same<decltype(__x1->size()), size_t>,
233 is_same<decltype(__x1->max_size()), size_t>,
234 is_same<decltype(__x1->capacity()), size_t>,
235 is_same<decltype(__x1->data()), typename _Tp::const_buffers_type>,
236 is_same<decltype(__x->prepare(__n)), typename _Tp::mutable_buffers_type>,
237 is_void<decltype(__x->commit(__n), __x->consume(__n), void())>
238 >::value>;
239
240 template<typename _Tp>
241 struct __is_dynamic_buffer_impl<_Tp,
242 decltype(__dynamic_buffer_reqs<_Tp>())>
243 : true_type
244 { };
245
246 template<typename _Tp>
247 struct is_dynamic_buffer : __is_dynamic_buffer_impl<_Tp>::type
248 { };
249
250 template<typename _Tp>
251 constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<_Tp>::value;
252
253 // @}
254
255 /// buffer size
256 template<typename _ConstBufferSequence>
257 size_t
258 buffer_size(const _ConstBufferSequence& __buffers) noexcept
259 {
260 size_t __total_size = 0;
261 auto __i = net::buffer_sequence_begin(__buffers);
262 const auto __end = net::buffer_sequence_end(__buffers);
263 for (; __i != __end; ++__i)
264 __total_size += const_buffer(*__i).size();
265 return __total_size;
266 }
267
268 template<typename _ConstBufferSequence>
269 bool
270 __buffer_empty(const _ConstBufferSequence& __buffers) noexcept
271 {
272 auto __i = net::buffer_sequence_begin(__buffers);
273 const auto __end = net::buffer_sequence_end(__buffers);
274 for (; __i != __end; ++__i)
275 if (const_buffer(*__i).size() != 0)
276 return false;
277 return true;
278 }
279
280 // buffer copy:
281
282 template<typename _MutableBufferSequence, typename _ConstBufferSequence>
283 size_t
284 buffer_copy(const _MutableBufferSequence& __dest,
285 const _ConstBufferSequence& __source,
286 size_t __max_size) noexcept
287 {
288 size_t __total_size = 0;
289 auto __to_i = net::buffer_sequence_begin(__dest);
290 const auto __to_end = net::buffer_sequence_end(__dest);
291 auto __from_i = net::buffer_sequence_begin(__source);
292 const auto __from_end = net::buffer_sequence_end(__source);
293 mutable_buffer __to;
294 const_buffer __from;
295 while (((__from_i != __from_end && __to_i != __to_end)
296 || (__from.size() && __to.size()))
297 && __total_size < __max_size)
298 {
299 if (__from.size() == 0)
300 __from = const_buffer{*__from_i++};
301 if (__to.size() == 0)
302 __to = mutable_buffer{*__to_i++};
303
304 size_t __n = std::min(__from.size(), __to.size());
305 __n = std::min(__n, __max_size - __total_size);
306 std::memcpy(__to.data(), __from.data(), __n);
307 __from = { (const char*)__from.data() + __n, __from.size() - __n };
308 __to = { (char*)__to.data() + __n, __to.size() - __n };
309 __total_size += __n;
310 }
311 return __total_size;
312 }
313
314 template<typename _MutableBufferSequence, typename _ConstBufferSequence>
315 inline size_t
316 buffer_copy(const _MutableBufferSequence& __dest,
317 const _ConstBufferSequence& __source) noexcept
318 { return net::buffer_copy(__dest, __source, size_t{-1}); }
319
320
321 // buffer arithmetic:
322
323 inline mutable_buffer
324 operator+(const mutable_buffer& __b, size_t __n) noexcept
325 {
326 if (__n > __b.size())
327 __n = __b.size();
328 return { static_cast<char*>(__b.data()) + __n, __b.size() - __n };
329 }
330
331 inline mutable_buffer
332 operator+(size_t __n, const mutable_buffer& __b) noexcept
333 { return __b + __n; }
334
335 inline const_buffer
336 operator+(const const_buffer& __b, size_t __n) noexcept
337 {
338 if (__n > __b.size())
339 __n = __b.size();
340 return { static_cast<const char*>(__b.data()) + __n, __b.size() - __n };
341 }
342
343 inline const_buffer
344 operator+(size_t __n, const const_buffer& __b) noexcept
345 { return __b + __n; }
346
347 // buffer creation:
348
349 inline mutable_buffer
350 buffer(void* __p, size_t __n) noexcept
351 { return { __p, __n }; }
352
353 inline const_buffer
354 buffer(const void* __p, size_t __n) noexcept
355 { return { __p, __n }; }
356
357 inline mutable_buffer
358 buffer(const mutable_buffer& __b) noexcept
359 { return __b; }
360
361 inline mutable_buffer
362 buffer(const mutable_buffer& __b, size_t __n) noexcept
363 { return { __b.data(), std::min(__b.size(), __n) }; }
364
365 inline const_buffer
366 buffer(const const_buffer& __b) noexcept
367 { return __b; }
368
369 inline const_buffer
370 buffer(const const_buffer& __b, size_t __n) noexcept
371 { return { __b.data(), std::min(__b.size(), __n) }; }
372
373 template<typename _Tp>
374 inline mutable_buffer
375 __to_mbuf(_Tp* __data, size_t __n)
376 { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
377
378 template<typename _Tp>
379 inline const_buffer
380 __to_cbuf(const _Tp* __data, size_t __n)
381 { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
382
383 template<typename _Tp, size_t _Nm>
384 inline mutable_buffer
385 buffer(_Tp (&__data)[_Nm]) noexcept
386 { return net::__to_mbuf(__data, _Nm); }
387
388 template<typename _Tp, size_t _Nm>
389 inline const_buffer
390 buffer(const _Tp (&__data)[_Nm]) noexcept
391 { return net::__to_cbuf(__data, _Nm); }
392
393 template<typename _Tp, size_t _Nm>
394 inline mutable_buffer
395 buffer(array<_Tp, _Nm>& __data) noexcept
396 { return net::__to_mbuf(__data.data(), _Nm); }
397
398 template<typename _Tp, size_t _Nm>
399 inline const_buffer
400 buffer(array<const _Tp, _Nm>& __data) noexcept
401 { return net::__to_cbuf(__data.data(), __data.size()); }
402
403 template<typename _Tp, size_t _Nm>
404 inline const_buffer
405 buffer(const array<_Tp, _Nm>& __data) noexcept
406 { return net::__to_cbuf(__data.data(), __data.size()); }
407
408 template<typename _Tp, typename _Allocator>
409 inline mutable_buffer
410 buffer(vector<_Tp, _Allocator>& __data) noexcept
411 { return net::__to_mbuf(__data.data(), __data.size()); }
412
413 template<typename _Tp, typename _Allocator>
414 inline const_buffer
415 buffer(const vector<_Tp, _Allocator>& __data) noexcept
416 { return net::__to_cbuf(__data.data(), __data.size()); }
417
418 template<typename _CharT, typename _Traits, typename _Allocator>
419 inline mutable_buffer
420 buffer(basic_string<_CharT, _Traits, _Allocator>& __data) noexcept
421 { return net::__to_mbuf(&__data.front(), __data.size()); }
422
423 template<typename _CharT, typename _Traits, typename _Allocator>
424 inline const_buffer
425 buffer(const basic_string<_CharT, _Traits, _Allocator>& __data) noexcept
426 { return net::__to_cbuf(&__data.front(), __data.size()); }
427
428 template<typename _CharT, typename _Traits>
429 inline const_buffer
430 buffer(basic_string_view<_CharT, _Traits> __data) noexcept
431 { return net::__to_cbuf(__data.data(), __data.size()); }
432
433 template<typename _Tp, size_t _Nm>
434 inline mutable_buffer
435 buffer(_Tp (&__data)[_Nm], size_t __n) noexcept
436 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
437
438 template<typename _Tp, size_t _Nm>
439 inline const_buffer
440 buffer(const _Tp (&__data)[_Nm], size_t __n) noexcept
441 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
442
443 template<typename _Tp, size_t _Nm>
444 inline mutable_buffer
445 buffer(array<_Tp, _Nm>& __data, size_t __n) noexcept
446 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
447
448 template<typename _Tp, size_t _Nm>
449 inline const_buffer
450 buffer(array<const _Tp, _Nm>& __data, size_t __n) noexcept
451 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
452
453 template<typename _Tp, size_t _Nm>
454 inline const_buffer
455 buffer(const array<_Tp, _Nm>& __data, size_t __n) noexcept
456 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
457
458 template<typename _Tp, typename _Allocator>
459 inline mutable_buffer
460 buffer(vector<_Tp, _Allocator>& __data, size_t __n) noexcept
461 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
462
463 template<typename _Tp, typename _Allocator>
464 inline const_buffer
465 buffer(const vector<_Tp, _Allocator>& __data, size_t __n) noexcept
466 { return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
467
468 template<typename _CharT, typename _Traits, typename _Allocator>
469 inline mutable_buffer
470 buffer(basic_string<_CharT, _Traits, _Allocator>& __data,
471 size_t __n) noexcept
472 { return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
473
474 template<typename _CharT, typename _Traits, typename _Allocator>
475 inline const_buffer
476 buffer(const basic_string<_CharT, _Traits, _Allocator>& __data,
477 size_t __n) noexcept
478 { return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
479
480 template<typename _CharT, typename _Traits>
481 inline const_buffer
482 buffer(basic_string_view<_CharT, _Traits> __data, size_t __n) noexcept
483 { return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
484
485
486 template<typename _Sequence>
487 class __dynamic_buffer_base
488 {
489 public:
490 // types:
491 typedef const_buffer const_buffers_type;
492 typedef mutable_buffer mutable_buffers_type;
493
494 // constructors:
495 explicit
496 __dynamic_buffer_base(_Sequence& __seq) noexcept
497 : _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__seq.max_size())
498 { }
499
500 __dynamic_buffer_base(_Sequence& __seq, size_t __maximum_size) noexcept
501 : _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__maximum_size)
502 { __glibcxx_assert(__seq.size() <= __maximum_size); }
503
504 __dynamic_buffer_base(__dynamic_buffer_base&&) = default;
505
506 // members:
507 size_t size() const noexcept { return _M_size; }
508 size_t max_size() const noexcept { return _M_max_size; }
509 size_t capacity() const noexcept { return _M_seq.capacity(); }
510
511 const_buffers_type
512 data() const noexcept
513 { return net::buffer(_M_seq, _M_size); }
514
515 mutable_buffers_type
516 prepare(size_t __n)
517 {
518 if ((_M_size + __n) > _M_max_size)
519 __throw_length_error("dynamic_vector_buffer::prepare");
520
521 _M_seq.resize(_M_size + __n);
522 return buffer(net::buffer(_M_seq) + _M_size, __n);
523 }
524
525 void
526 commit(size_t __n)
527 {
528 _M_size += std::min(__n, _M_seq.size() - _M_size);
529 _M_seq.resize(_M_size);
530 }
531
532 void
533 consume(size_t __n)
534 {
535 size_t __m = std::min(__n, _M_size);
536 _M_seq.erase(_M_seq.begin(), _M_seq.begin() + __m);
537 _M_size -= __m;
538 }
539
540 private:
541 _Sequence& _M_seq;
542 size_t _M_size;
543 const size_t _M_max_size;
544 };
545
546 template<typename _Tp, typename _Allocator>
547 class dynamic_vector_buffer
548 : public __dynamic_buffer_base<vector<_Tp, _Allocator>>
549 {
550 public:
551 using __dynamic_buffer_base<vector<_Tp, _Allocator>>::__dynamic_buffer_base;
552 };
553
554 template<typename _CharT, typename _Traits, typename _Allocator>
555 class dynamic_string_buffer
556 : public __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>
557 {
558 public:
559 using __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>::
560 __dynamic_buffer_base;
561 };
562
563 // dynamic buffer creation:
564
565 template<typename _Tp, typename _Allocator>
566 inline dynamic_vector_buffer<_Tp, _Allocator>
567 dynamic_buffer(vector<_Tp, _Allocator>& __vec) noexcept
568 { return dynamic_vector_buffer<_Tp, _Allocator>{__vec}; }
569
570 template<typename _Tp, typename _Allocator>
571 inline dynamic_vector_buffer<_Tp, _Allocator>
572 dynamic_buffer(vector<_Tp, _Allocator>& __vec, size_t __n) noexcept
573 { return {__vec, __n}; }
574
575 template<typename _CharT, typename _Traits, typename _Allocator>
576 inline dynamic_string_buffer<_CharT, _Traits, _Allocator>
577 dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str) noexcept
578 { return dynamic_string_buffer<_CharT, _Traits, _Allocator>{__str}; }
579
580 template<typename _CharT, typename _Traits, typename _Allocator>
581 inline dynamic_string_buffer<_CharT, _Traits, _Allocator>
582 dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str,
583 size_t __n) noexcept
584 { return {__str, __n}; }
585
586 class transfer_all
587 {
588 public:
589 size_t operator()(const error_code& __ec, size_t) const
590 { return !__ec ? 1500 : 0; }
591 };
592
593 class transfer_at_least
594 {
595 public:
596 explicit transfer_at_least(size_t __m) : _M_minimum(__m) { }
597
598 size_t operator()(const error_code& __ec, size_t __n) const
599 { return !__ec && __n < _M_minimum ? _M_minimum - __n : 0; }
600
601 private:
602 size_t _M_minimum;
603 };
604
605 class transfer_exactly
606 {
607 public:
608 explicit transfer_exactly(size_t __e) : _M_exact(__e) { }
609
610 size_t operator()(const error_code& __ec, size_t __n) const
611 {
612 size_t _Nm = -1;
613 return !__ec && __n < _M_exact ? std::min(_M_exact - __n, _Nm) : 0;
614 }
615
616 private:
617 size_t _M_exact;
618 };
619
620 /** @brief synchronous read operations
621 * @{
622 */
623
624 template<typename _SyncReadStream, typename _MutableBufferSequence,
625 typename _CompletionCondition>
626 enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
627 size_t>
628 read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
629 _CompletionCondition __completion_condition, error_code& __ec)
630 {
631 __ec.clear();
632 auto __i = net::buffer_sequence_begin(__buffers);
633 auto __end = net::buffer_sequence_end(__buffers);
634 mutable_buffer __to;
635 size_t __total = 0;
636 size_t __n;
637 while ((__n = __completion_condition(__ec, __total))
638 && (__i != __end || __to.size()))
639 {
640 if (__to.size() == 0)
641 __to = mutable_buffer(*__i++);
642 __n = __stream.read_some(buffer(__to, __n), __ec);
643 __to = __to + __n;
644 __total += __n;
645 }
646 return __total;
647 }
648
649 template<typename _SyncReadStream, typename _MutableBufferSequence>
650 inline
651 enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
652 size_t>
653 read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers)
654 {
655 error_code __ec;
656 return net::read(__stream, __buffers, transfer_all{}, __ec);
657 }
658
659 template<typename _SyncReadStream, typename _MutableBufferSequence>
660 inline
661 enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
662 size_t>
663 read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
664 error_code& __ec)
665 { return net::read(__stream, __buffers, transfer_all{}, __ec); }
666
667 template<typename _SyncReadStream, typename _MutableBufferSequence,
668 typename _CompletionCondition>
669 inline
670 enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
671 size_t>
672 read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
673 _CompletionCondition __completion_condition)
674 {
675 error_code __ec;
676 return net::read(__stream, __buffers, __completion_condition, __ec);
677 }
678
679
680 template<typename _SyncReadStream, typename _DynamicBuffer,
681 typename _CompletionCondition>
682 enable_if_t<is_dynamic_buffer<decay_t<_DynamicBuffer>>::value, size_t>
683 read(_SyncReadStream& __stream, _DynamicBuffer&& __b,
684 _CompletionCondition __completion_condition, error_code& __ec)
685 {
686 const size_t __limit = 64;
687 __ec.clear();
688 size_t __cap = std::max(__b.capacity() - __b.size(), __limit);
689 size_t __total = 0;
690 size_t __n;
691 while ((__n = __completion_condition(__ec, __total))
692 && __b.size() != __b.max_size())
693 {
694 __n = std::min(__n, __b.max_size() - __b.size());
695 size_t __cap = std::max(__b.capacity() - __b.size(), __limit);
696 mutable_buffer __to = __b.prepare(std::min(__cap, __n));
697 __n = __stream.read_some(__to, __ec);
698 __to = __to + __n;
699 __total += __n;
700 __b.commit(__n);
701 }
702 return __total;
703 }
704
705 template<typename _SyncReadStream, typename _DynamicBuffer>
706 inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
707 read(_SyncReadStream& __stream, _DynamicBuffer&& __b)
708 {
709 error_code __ec;
710 return net::read(__stream, __b, transfer_all{}, __ec);
711 }
712
713 template<typename _SyncReadStream, typename _DynamicBuffer>
714 inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
715 read(_SyncReadStream& __stream, _DynamicBuffer&& __b, error_code& __ec)
716 {
717 return net::read(__stream, __b, transfer_all{}, __ec);
718 }
719
720 template<typename _SyncReadStream, typename _DynamicBuffer,
721 typename _CompletionCondition>
722 inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
723 read(_SyncReadStream& __stream, _DynamicBuffer&& __b,
724 _CompletionCondition __completion_condition)
725 {
726 error_code __ec;
727 return net::read(__stream, __b, __completion_condition, __ec);
728 }
729
730 // @}
731
732 /** @brief asynchronous read operations
733 * @{
734 */
735
736 template<typename _AsyncReadStream, typename _MutableBufferSequence,
737 typename _CompletionCondition, typename _CompletionToken>
738 __deduced_t<_CompletionToken, void(error_code, size_t)>
739 async_read(_AsyncReadStream& __stream,
740 const _MutableBufferSequence& __buffers,
741 _CompletionCondition __completion_condition,
742 _CompletionToken&& __token)
743 {
744 error_code __ec;
745 }
746
747 template<typename _AsyncReadStream, typename _MutableBufferSequence,
748 typename _CompletionToken>
749 inline __deduced_t<_CompletionToken, void(error_code, size_t)>
750 async_read(_AsyncReadStream& __stream,
751 const _MutableBufferSequence& __buffers,
752 _CompletionToken&& __token)
753 {
754 return net::async_read(__stream, __buffers, transfer_all{},
755 std::forward<_CompletionToken>(__token));
756 }
757
758 template<typename _AsyncReadStream, typename _DynamicBuffer,
759 typename _CompletionCondition, typename _CompletionToken>
760 __deduced_t<_CompletionToken, void(error_code, size_t)>
761 async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b,
762 _CompletionCondition __completion_condition,
763 _CompletionToken&& __token)
764 {
765 error_code __ec;
766 }
767
768 template<typename _AsyncReadStream, typename _DynamicBuffer,
769 typename _CompletionToken>
770 inline __deduced_t<_CompletionToken, void(error_code, size_t)>
771 async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b,
772 _CompletionToken&& __token)
773 {
774 return net::async_read(__stream, __b, transfer_all{},
775 std::forward<_CompletionToken>(__token));
776 }
777
778 // @}
779
780#if 0
781 /** @brief synchronous write operations:
782 * @{
783 */
784
785 template<typename _SyncWriteStream, typename _ConstBufferSequence>
786 size_t write(_SyncWriteStream& __stream,
787 const _ConstBufferSequence& __buffers);
788 template<typename _SyncWriteStream, typename _ConstBufferSequence>
789 size_t write(_SyncWriteStream& __stream,
790 const _ConstBufferSequence& __buffers, error_code& __ec);
791 template<typename _SyncWriteStream, typename _ConstBufferSequence,
792 typename _CompletionCondition>
793 size_t write(_SyncWriteStream& __stream,
794 const _ConstBufferSequence& __buffers,
795 _CompletionCondition __completion_condition);
796 template<typename _SyncWriteStream, typename _ConstBufferSequence,
797 typename _CompletionCondition>
798 size_t write(_SyncWriteStream& __stream,
799 const _ConstBufferSequence& __buffers,
800 _CompletionCondition __completion_condition,
801 error_code& __ec);
802
803 template<typename _SyncWriteStream, typename _DynamicBuffer>
804 size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b);
805 template<typename _SyncWriteStream, typename _DynamicBuffer>
806 size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, error_code& __ec);
807 template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition>
808 size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b,
809 _CompletionCondition __completion_condition);
810 template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition>
811 size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b,
812 _CompletionCondition __completion_condition, error_code& __ec);
813
814 // @}
815
816 /** @brief asynchronous write operations
817 * @{
818 */
819
820 template<typename _AsyncWriteStream, typename _ConstBufferSequence,
821 typename _CompletionToken>
822 DEDUCED async_write(_AsyncWriteStream& __stream,
823 const _ConstBufferSequence& __buffers,
824 _CompletionToken&& __token);
825 template<typename _AsyncWriteStream, typename _ConstBufferSequence,
826 typename _CompletionCondition, typename _CompletionToken>
827 DEDUCED async_write(_AsyncWriteStream& __stream,
828 const _ConstBufferSequence& __buffers,
829 _CompletionCondition __completion_condition,
830 _CompletionToken&& __token);
831
832 template<typename _AsyncWriteStream, typename _DynamicBuffer, typename _CompletionToken>
833 DEDUCED async_write(_AsyncWriteStream& __stream,
834 _DynamicBuffer&& __b, _CompletionToken&& __token);
835 template<typename _AsyncWriteStream, typename _DynamicBuffer,
836 typename _CompletionCondition, typename _CompletionToken>
837 DEDUCED async_write(_AsyncWriteStream& __stream,
838 _DynamicBuffer&& __b,
839 _CompletionCondition __completion_condition,
840 _CompletionToken&& __token);
841
842 // @}
843
844 /** @brief synchronous delimited read operations
845 * @{
846 */
847
848 template<typename _SyncReadStream, typename _DynamicBuffer>
849 size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, char __delim);
850 template<typename _SyncReadStream, typename _DynamicBuffer>
851 size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b,
852 char __delim, error_code& __ec);
853 template<typename _SyncReadStream, typename _DynamicBuffer>
854 size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, string_view __delim);
855 template<typename _SyncReadStream, typename _DynamicBuffer>
856 size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b,
857 string_view __delim, error_code& __ec);
858
859 // @}
860
861 /** @brief asynchronous delimited read operations
862 * @{
863 */
864
865 template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken>
866 DEDUCED async_read_until(_AsyncReadStream& __s,
867 _DynamicBuffer&& __b, char __delim,
868 _CompletionToken&& __token);
869 template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken>
870 DEDUCED async_read_until(_AsyncReadStream& __s,
871 _DynamicBuffer&& __b, string_view __delim,
872 _CompletionToken&& __token);
873
874 // @}
875
876#endif
877 /// @}
878
e5989e71
JW
879} // namespace v1
880} // namespace net
881} // namespace experimental
882
e5989e71
JW
883 template<>
884 struct is_error_code_enum<experimental::net::v1::stream_errc>
885 : public true_type {};
886
887_GLIBCXX_END_NAMESPACE_VERSION
e5989e71
JW
888} // namespace std
889
890#endif // C++14
891
892#endif // _GLIBCXX_EXPERIMENTAL_BUFFER