Add support for 32-bit hppa targets in muldi3 expander
[official-gcc.git] / libstdc++-v3 / include / experimental / buffer
blob945dcb54d9f994a5fd2f7ab69c1f4daa16e70abe
1 // <experimental/buffer> -*- C++ -*-
3 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
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.
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.
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.
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/>.
25 /** @file experimental/buffer
26  *  This is a TS C++ Library header.
27  *  @ingroup networking-ts
28  */
30 #ifndef _GLIBCXX_EXPERIMENTAL_BUFFER
31 #define _GLIBCXX_EXPERIMENTAL_BUFFER 1
33 #pragma GCC system_header
35 #if __cplusplus >= 201402L
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>
45 namespace std _GLIBCXX_VISIBILITY(default)
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 namespace experimental
50 namespace net
52 inline namespace v1
55   /** @addtogroup networking-ts
56    *  @{
57    */
59   enum class stream_errc {    // TODO decide values
60     eof = 1,
61     not_found = 2
62   };
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"; }
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       }
79       virtual void __message(int) { } // TODO dual ABI XXX
80     };
81     static __cat __c;
82     return __c;
83   }
85   inline error_code
86   make_error_code(stream_errc __e) noexcept
87   { return error_code(static_cast<int>(__e), stream_category()); }
89   inline error_condition
90   make_error_condition(stream_errc __e) noexcept
91   { return error_condition(static_cast<int>(__e), stream_category()); }
93   class mutable_buffer
94   {
95   public:
96     // constructors:
97     mutable_buffer() noexcept : _M_data(), _M_size() { }
99     mutable_buffer(void* __p, size_t __n) noexcept
100     : _M_data(__p), _M_size(__n) { }
102     // members:
103     void* data() const noexcept { return _M_data; }
104     size_t size() const noexcept { return _M_size; }
106   private:
107     void*       _M_data;
108     size_t      _M_size;
109   };
111   class const_buffer
112   {
113   public:
114     // constructors:
115     const_buffer() noexcept : _M_data(), _M_size() { }
117     const_buffer(const void* __p, size_t __n) noexcept
118     : _M_data(__p), _M_size(__n) { }
120     const_buffer(const mutable_buffer& __b) noexcept
121     : _M_data(__b.data()), _M_size(__b.size()) { }
123     // members:
124     const void* data() const noexcept { return _M_data; }
125     size_t size() const noexcept { return _M_size; }
127   private:
128     const void* _M_data;
129     size_t      _M_size;
130   };
133   /** @brief buffer sequence access
134    *
135    * Uniform access to types that meet the BufferSequence requirements.
136    * @{
137    */
139   inline const mutable_buffer*
140   buffer_sequence_begin(const mutable_buffer& __b)
141   { return std::addressof(__b); }
143   inline const const_buffer*
144   buffer_sequence_begin(const const_buffer& __b)
145   { return std::addressof(__b); }
147   inline const mutable_buffer*
148   buffer_sequence_end(const mutable_buffer& __b)
149   { return std::addressof(__b) + 1; }
151   inline const const_buffer*
152   buffer_sequence_end(const const_buffer& __b)
153   { return std::addressof(__b) + 1; }
155   template<typename _Cont>
156     auto
157     buffer_sequence_begin(_Cont& __c) -> decltype(__c.begin())
158     { return __c.begin(); }
160   template<typename _Cont>
161     auto
162     buffer_sequence_begin(const _Cont& __c) -> decltype(__c.begin())
163     { return __c.begin(); }
165   template<typename _Cont>
166     auto
167     buffer_sequence_end(_Cont& __c) -> decltype(__c.end())
168     { return __c.end(); }
170   template<typename _Cont>
171     auto
172     buffer_sequence_end(const _Cont& __c) -> decltype(__c.end())
173     { return __c.end(); }
175   /// @}
178   /** @brief buffer type traits
179    *
180    * @{
181    */
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>;
193   template<typename _Tp, typename _Buffer, typename = void>
194     struct __is_buffer_sequence : false_type
195     { };
197   template<typename _Tp, typename _Buffer>
198     struct __is_buffer_sequence<_Tp, _Buffer, __buffer_sequence<_Tp, _Buffer>>
199     : true_type
200     { };
202   template<typename _Tp>
203     struct is_mutable_buffer_sequence
204     : __is_buffer_sequence<_Tp, mutable_buffer>::type
205     { };
207   template<typename _Tp>
208     struct is_const_buffer_sequence
209     : __is_buffer_sequence<_Tp, const_buffer>::type
210     { };
212   template<typename _Tp>
213     constexpr bool is_mutable_buffer_sequence_v
214       = is_mutable_buffer_sequence<_Tp>::value;
216   template<typename _Tp>
217     constexpr bool is_const_buffer_sequence_v
218       = is_const_buffer_sequence<_Tp>::value;
220   template<typename _Tp, typename = void>
221     struct __is_dynamic_buffer_impl : false_type
222     { };
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>;
240   template<typename _Tp>
241     struct __is_dynamic_buffer_impl<_Tp,
242                                     decltype(__dynamic_buffer_reqs<_Tp>())>
243     : true_type
244     { };
246   template<typename _Tp>
247     struct is_dynamic_buffer : __is_dynamic_buffer_impl<_Tp>::type
248     { };
250   template<typename _Tp>
251     constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<_Tp>::value;
253   /// @}
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     }
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     }
280   // buffer copy:
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++};
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     }
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)); }
321   // buffer arithmetic:
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   }
331   inline mutable_buffer
332   operator+(size_t __n, const mutable_buffer& __b) noexcept
333   { return __b + __n; }
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   }
343   inline const_buffer
344   operator+(size_t __n, const const_buffer& __b) noexcept
345   { return __b + __n; }
347   // buffer creation:
349   inline mutable_buffer
350   buffer(void* __p, size_t __n) noexcept
351   { return { __p, __n }; }
353   inline const_buffer
354   buffer(const void* __p, size_t __n) noexcept
355   { return { __p, __n }; }
357   inline mutable_buffer
358   buffer(const mutable_buffer& __b) noexcept
359   { return __b; }
361   inline mutable_buffer
362   buffer(const mutable_buffer& __b, size_t __n) noexcept
363   { return { __b.data(), std::min(__b.size(), __n) }; }
365   inline const_buffer
366   buffer(const const_buffer& __b) noexcept
367   { return __b; }
369   inline const_buffer
370   buffer(const const_buffer& __b, size_t __n) noexcept
371   { return { __b.data(), std::min(__b.size(), __n) }; }
373   template<typename _Tp>
374     inline mutable_buffer
375     __to_mbuf(_Tp* __data, size_t __n)
376     { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
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) }; }
383   template<typename _Tp, size_t _Nm>
384     inline mutable_buffer
385     buffer(_Tp (&__data)[_Nm]) noexcept
386     { return net::__to_mbuf(__data, _Nm); }
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); }
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); }
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()); }
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()); }
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()); }
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()); }
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()); }
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()); }
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()); }
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)); }
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)); }
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)); }
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)); }
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)); }
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)); }
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)); }
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)); }
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)); }
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)); }
486   template<typename _Sequence>
487     class __dynamic_buffer_base
488     {
489     public:
490       // types:
491       using const_buffers_type = const_buffer;
492       using mutable_buffers_type = mutable_buffer;
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       { }
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); }
504       __dynamic_buffer_base(__dynamic_buffer_base&&) = default;
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(); }
511       const_buffers_type
512       data() const noexcept
513       { return net::buffer(_M_seq, _M_size); }
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");
521         _M_seq.resize(_M_size + __n);
522         return buffer(net::buffer(_M_seq) + _M_size, __n);
523       }
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       }
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       }
540     private:
541       _Sequence&        _M_seq;
542       size_t            _M_size;
543       const size_t      _M_max_size;
544     };
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     };
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     };
563   // dynamic buffer creation:
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}; }
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}; }
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}; }
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}; }
586   class transfer_all
587   {
588   public:
589     size_t operator()(const error_code& __ec, size_t) const
590     { return !__ec ? 1500 : 0; }
591   };
593   class transfer_at_least
594   {
595   public:
596     explicit transfer_at_least(size_t __m) : _M_minimum(__m) { }
598     size_t operator()(const error_code& __ec, size_t __n) const
599     { return !__ec  && __n < _M_minimum ? _M_minimum - __n : 0; }
601   private:
602     size_t _M_minimum;
603   };
605   class transfer_exactly
606   {
607   public:
608     explicit transfer_exactly(size_t __e) : _M_exact(__e) { }
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     }
616   private:
617     size_t _M_exact;
618   };
620   /** @brief synchronous read operations
621    * @{
622    */
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     }
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     }
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); }
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     }
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     }
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     }
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     }
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     }
730   /// @}
732   /** @brief asynchronous read operations
733    * @{
734    */
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     }
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     }
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     }
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     }
778   /// @}
780 #if 0
781   /** @brief synchronous write operations:
782    * @{
783    */
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);
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);
814   /// @}
816   /** @brief asynchronous write operations
817    * @{
818    */
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);
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);
842   /// @}
844   /** @brief synchronous delimited read operations
845    * @{
846    */
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);
859   /// @}
861   /** @brief asynchronous delimited read operations
862    * @{
863    */
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);
874   /// @}
876 #endif
877   /// @}
879 } // namespace v1
880 } // namespace net
881 } // namespace experimental
883   template<>
884     struct is_error_code_enum<experimental::net::v1::stream_errc>
885     : public true_type {};
887 _GLIBCXX_END_NAMESPACE_VERSION
888 } // namespace std
890 #endif // C++14
892 #endif // _GLIBCXX_EXPERIMENTAL_BUFFER