buffers_adaptor.hpp 13 KB

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