buffers_cat.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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_CAT_HPP
  10. #define BOOST_BEAST_IMPL_BUFFERS_CAT_HPP
  11. #include <boost/beast/core/detail/tuple.hpp>
  12. #include <boost/beast/core/detail/variant.hpp>
  13. #include <boost/asio/buffer.hpp>
  14. #include <cstdint>
  15. #include <iterator>
  16. #include <new>
  17. #include <stdexcept>
  18. #include <utility>
  19. namespace boost {
  20. namespace beast {
  21. template<class Buffer>
  22. class buffers_cat_view<Buffer>
  23. {
  24. Buffer buffer_;
  25. public:
  26. using value_type = buffers_type<Buffer>;
  27. using const_iterator = buffers_iterator_type<Buffer>;
  28. explicit
  29. buffers_cat_view(Buffer const& buffer)
  30. : buffer_(buffer)
  31. {
  32. }
  33. const_iterator
  34. begin() const
  35. {
  36. return net::buffer_sequence_begin(buffer_);
  37. }
  38. const_iterator
  39. end() const
  40. {
  41. return net::buffer_sequence_end(buffer_);
  42. }
  43. };
  44. #if defined(_MSC_VER) && ! defined(__clang__)
  45. # define BOOST_BEAST_UNREACHABLE() __assume(false)
  46. #else
  47. # define BOOST_BEAST_UNREACHABLE() __builtin_unreachable()
  48. #endif
  49. #ifdef BOOST_BEAST_TESTS
  50. #define BOOST_BEAST_LOGIC_ERROR(s) \
  51. { \
  52. BOOST_THROW_EXCEPTION(std::logic_error((s))); \
  53. BOOST_BEAST_UNREACHABLE(); \
  54. }
  55. #define BOOST_BEAST_LOGIC_ERROR_RETURN(s, v) \
  56. { \
  57. BOOST_THROW_EXCEPTION(std::logic_error((s))); \
  58. return v; \
  59. }
  60. #else
  61. #define BOOST_BEAST_LOGIC_ERROR(s) \
  62. { \
  63. BOOST_ASSERT_MSG(false, s); \
  64. BOOST_BEAST_UNREACHABLE(); \
  65. }
  66. #define BOOST_BEAST_LOGIC_ERROR_RETURN(s, v) \
  67. { \
  68. BOOST_ASSERT_MSG(false, s); \
  69. return v; \
  70. }
  71. #endif
  72. namespace detail {
  73. struct buffers_cat_view_iterator_base
  74. {
  75. struct past_end
  76. {
  77. char unused = 0; // make g++8 happy
  78. net::mutable_buffer
  79. operator*() const
  80. {
  81. BOOST_BEAST_LOGIC_ERROR_RETURN(
  82. "Dereferencing a one-past-the-end iterator", {});
  83. }
  84. operator bool() const noexcept
  85. {
  86. return true;
  87. }
  88. };
  89. };
  90. } // detail
  91. template<class... Bn>
  92. class buffers_cat_view<Bn...>::const_iterator
  93. : private detail::buffers_cat_view_iterator_base
  94. {
  95. // VFALCO The logic to skip empty sequences fails
  96. // if there is just one buffer in the list.
  97. static_assert(sizeof...(Bn) >= 2,
  98. "A minimum of two sequences are required");
  99. detail::tuple<Bn...> const* bn_ = nullptr;
  100. detail::variant<
  101. buffers_iterator_type<Bn>..., past_end> it_{};
  102. friend class buffers_cat_view<Bn...>;
  103. template<std::size_t I>
  104. using C = std::integral_constant<std::size_t, I>;
  105. public:
  106. using value_type = typename
  107. buffers_cat_view<Bn...>::value_type;
  108. using pointer = value_type const*;
  109. using reference = value_type;
  110. using difference_type = std::ptrdiff_t;
  111. using iterator_category =
  112. std::bidirectional_iterator_tag;
  113. const_iterator() = default;
  114. const_iterator(const_iterator const& other) = default;
  115. const_iterator& operator=(
  116. const_iterator const& other) = default;
  117. bool
  118. operator==(const_iterator const& other) const;
  119. bool
  120. operator!=(const_iterator const& other) const
  121. {
  122. return ! (*this == other);
  123. }
  124. reference
  125. operator*() const;
  126. pointer
  127. operator->() const = delete;
  128. const_iterator&
  129. operator++();
  130. const_iterator
  131. operator++(int);
  132. const_iterator&
  133. operator--();
  134. const_iterator
  135. operator--(int);
  136. private:
  137. const_iterator(
  138. detail::tuple<Bn...> const& bn,
  139. std::true_type);
  140. const_iterator(
  141. detail::tuple<Bn...> const& bn,
  142. std::false_type);
  143. struct dereference
  144. {
  145. const_iterator const& self;
  146. reference
  147. operator()(mp11::mp_size_t<0>)
  148. {
  149. BOOST_BEAST_LOGIC_ERROR_RETURN(
  150. "Dereferencing a default-constructed iterator", {});
  151. }
  152. template<class I>
  153. reference operator()(I)
  154. {
  155. return *self.it_.template get<I::value>();
  156. }
  157. };
  158. struct increment
  159. {
  160. const_iterator& self;
  161. void
  162. operator()(mp11::mp_size_t<0>)
  163. {
  164. BOOST_BEAST_LOGIC_ERROR(
  165. "Incrementing a default-constructed iterator");
  166. }
  167. template<std::size_t I>
  168. void
  169. operator()(mp11::mp_size_t<I>)
  170. {
  171. ++self.it_.template get<I>();
  172. next(mp11::mp_size_t<I>{});
  173. }
  174. template<std::size_t I>
  175. void
  176. next(mp11::mp_size_t<I>)
  177. {
  178. auto& it = self.it_.template get<I>();
  179. for(;;)
  180. {
  181. if (it == net::buffer_sequence_end(
  182. detail::get<I-1>(*self.bn_)))
  183. break;
  184. if(net::const_buffer(*it).size() > 0)
  185. return;
  186. ++it;
  187. }
  188. self.it_.template emplace<I+1>(
  189. net::buffer_sequence_begin(
  190. detail::get<I>(*self.bn_)));
  191. next(mp11::mp_size_t<I+1>{});
  192. }
  193. void
  194. operator()(mp11::mp_size_t<sizeof...(Bn)>)
  195. {
  196. auto constexpr I = sizeof...(Bn);
  197. ++self.it_.template get<I>();
  198. next(mp11::mp_size_t<I>{});
  199. }
  200. void
  201. next(mp11::mp_size_t<sizeof...(Bn)>)
  202. {
  203. auto constexpr I = sizeof...(Bn);
  204. auto& it = self.it_.template get<I>();
  205. for(;;)
  206. {
  207. if (it == net::buffer_sequence_end(
  208. detail::get<I-1>(*self.bn_)))
  209. break;
  210. if(net::const_buffer(*it).size() > 0)
  211. return;
  212. ++it;
  213. }
  214. // end
  215. self.it_.template emplace<I+1>();
  216. }
  217. void
  218. operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
  219. {
  220. BOOST_BEAST_LOGIC_ERROR(
  221. "Incrementing a one-past-the-end iterator");
  222. }
  223. };
  224. struct decrement
  225. {
  226. const_iterator& self;
  227. void
  228. operator()(mp11::mp_size_t<0>)
  229. {
  230. BOOST_BEAST_LOGIC_ERROR(
  231. "Decrementing a default-constructed iterator");
  232. }
  233. void
  234. operator()(mp11::mp_size_t<1>)
  235. {
  236. auto constexpr I = 1;
  237. auto& it = self.it_.template get<I>();
  238. for(;;)
  239. {
  240. if(it == net::buffer_sequence_begin(
  241. detail::get<I-1>(*self.bn_)))
  242. {
  243. BOOST_BEAST_LOGIC_ERROR(
  244. "Decrementing an iterator to the beginning");
  245. }
  246. --it;
  247. if(net::const_buffer(*it).size() > 0)
  248. return;
  249. }
  250. }
  251. template<std::size_t I>
  252. void
  253. operator()(mp11::mp_size_t<I>)
  254. {
  255. auto& it = self.it_.template get<I>();
  256. for(;;)
  257. {
  258. if(it == net::buffer_sequence_begin(
  259. detail::get<I-1>(*self.bn_)))
  260. break;
  261. --it;
  262. if(net::const_buffer(*it).size() > 0)
  263. return;
  264. }
  265. self.it_.template emplace<I-1>(
  266. net::buffer_sequence_end(
  267. detail::get<I-2>(*self.bn_)));
  268. (*this)(mp11::mp_size_t<I-1>{});
  269. }
  270. void
  271. operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
  272. {
  273. auto constexpr I = sizeof...(Bn)+1;
  274. self.it_.template emplace<I-1>(
  275. net::buffer_sequence_end(
  276. detail::get<I-2>(*self.bn_)));
  277. (*this)(mp11::mp_size_t<I-1>{});
  278. }
  279. };
  280. };
  281. //------------------------------------------------------------------------------
  282. template<class... Bn>
  283. buffers_cat_view<Bn...>::
  284. const_iterator::
  285. const_iterator(
  286. detail::tuple<Bn...> const& bn,
  287. std::true_type)
  288. : bn_(&bn)
  289. {
  290. // one past the end
  291. it_.template emplace<sizeof...(Bn)+1>();
  292. }
  293. template<class... Bn>
  294. buffers_cat_view<Bn...>::
  295. const_iterator::
  296. const_iterator(
  297. detail::tuple<Bn...> const& bn,
  298. std::false_type)
  299. : bn_(&bn)
  300. {
  301. it_.template emplace<1>(
  302. net::buffer_sequence_begin(
  303. detail::get<0>(*bn_)));
  304. increment{*this}.next(
  305. mp11::mp_size_t<1>{});
  306. }
  307. template<class... Bn>
  308. bool
  309. buffers_cat_view<Bn...>::
  310. const_iterator::
  311. operator==(const_iterator const& other) const
  312. {
  313. return bn_ == other.bn_ && it_ == other.it_;
  314. }
  315. template<class... Bn>
  316. auto
  317. buffers_cat_view<Bn...>::
  318. const_iterator::
  319. operator*() const ->
  320. reference
  321. {
  322. return mp11::mp_with_index<
  323. sizeof...(Bn) + 2>(
  324. it_.index(),
  325. dereference{*this});
  326. }
  327. template<class... Bn>
  328. auto
  329. buffers_cat_view<Bn...>::
  330. const_iterator::
  331. operator++() ->
  332. const_iterator&
  333. {
  334. mp11::mp_with_index<
  335. sizeof...(Bn) + 2>(
  336. it_.index(),
  337. increment{*this});
  338. return *this;
  339. }
  340. template<class... Bn>
  341. auto
  342. buffers_cat_view<Bn...>::
  343. const_iterator::
  344. operator++(int) ->
  345. const_iterator
  346. {
  347. auto temp = *this;
  348. ++(*this);
  349. return temp;
  350. }
  351. template<class... Bn>
  352. auto
  353. buffers_cat_view<Bn...>::
  354. const_iterator::
  355. operator--() ->
  356. const_iterator&
  357. {
  358. mp11::mp_with_index<
  359. sizeof...(Bn) + 2>(
  360. it_.index(),
  361. decrement{*this});
  362. return *this;
  363. }
  364. template<class... Bn>
  365. auto
  366. buffers_cat_view<Bn...>::
  367. const_iterator::
  368. operator--(int) ->
  369. const_iterator
  370. {
  371. auto temp = *this;
  372. --(*this);
  373. return temp;
  374. }
  375. //------------------------------------------------------------------------------
  376. template<class... Bn>
  377. buffers_cat_view<Bn...>::
  378. buffers_cat_view(Bn const&... bn)
  379. : bn_(bn...)
  380. {
  381. }
  382. template<class... Bn>
  383. auto
  384. buffers_cat_view<Bn...>::begin() const ->
  385. const_iterator
  386. {
  387. return const_iterator{bn_, std::false_type{}};
  388. }
  389. template<class... Bn>
  390. auto
  391. buffers_cat_view<Bn...>::end() const->
  392. const_iterator
  393. {
  394. return const_iterator{bn_, std::true_type{}};
  395. }
  396. } // beast
  397. } // boost
  398. #endif