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