buffers_cat.hpp 10 KB

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