Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

893 lines
28KB

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