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