File indexing completed on 2025-01-18 09:29:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_IMPL_BUFFERS_CAT_HPP
0011 #define BOOST_BEAST_IMPL_BUFFERS_CAT_HPP
0012
0013 #include <boost/beast/core/detail/tuple.hpp>
0014 #include <boost/beast/core/detail/variant.hpp>
0015 #include <boost/asio/buffer.hpp>
0016 #include <cstdint>
0017 #include <iterator>
0018 #include <new>
0019 #include <stdexcept>
0020 #include <utility>
0021
0022 namespace boost {
0023 namespace beast {
0024
0025 template<class Buffer>
0026 class buffers_cat_view<Buffer>
0027 {
0028 Buffer buffer_;
0029 public:
0030 using value_type = buffers_type<Buffer>;
0031
0032 using const_iterator = buffers_iterator_type<Buffer>;
0033
0034 explicit
0035 buffers_cat_view(Buffer const& buffer)
0036 : buffer_(buffer)
0037 {
0038 }
0039
0040 const_iterator
0041 begin() const
0042 {
0043 return net::buffer_sequence_begin(buffer_);
0044 }
0045
0046 const_iterator
0047 end() const
0048 {
0049 return net::buffer_sequence_end(buffer_);
0050 }
0051 };
0052
0053 #if defined(_MSC_VER) && ! defined(__clang__)
0054 # define BOOST_BEAST_UNREACHABLE() __assume(false)
0055 # define BOOST_BEAST_UNREACHABLE_RETURN(v) return v
0056 #else
0057 # define BOOST_BEAST_UNREACHABLE() __builtin_unreachable()
0058 # define BOOST_BEAST_UNREACHABLE_RETURN(v) \
0059 do { __builtin_unreachable(); return v; } while(false)
0060 #endif
0061
0062 #ifdef BOOST_BEAST_TESTS
0063
0064 #define BOOST_BEAST_LOGIC_ERROR(s) \
0065 { \
0066 BOOST_THROW_EXCEPTION(std::logic_error((s))); \
0067 BOOST_BEAST_UNREACHABLE(); \
0068 }
0069
0070 #else
0071
0072 #define BOOST_BEAST_LOGIC_ERROR(s) \
0073 { \
0074 BOOST_ASSERT_MSG(false, s); \
0075 BOOST_BEAST_UNREACHABLE(); \
0076 }
0077
0078 #endif
0079
0080 namespace detail {
0081
0082 struct buffers_cat_view_iterator_base
0083 {
0084 struct past_end
0085 {
0086 char unused = 0;
0087
0088 BOOST_NORETURN net::mutable_buffer
0089 operator*() const
0090 {
0091 BOOST_BEAST_LOGIC_ERROR(
0092 "Dereferencing a one-past-the-end iterator");
0093 }
0094
0095 operator bool() const noexcept
0096 {
0097 return true;
0098 }
0099 };
0100 };
0101
0102 }
0103
0104 template<class... Bn>
0105 class buffers_cat_view<Bn...>::const_iterator
0106 : private detail::buffers_cat_view_iterator_base
0107 {
0108
0109
0110 static_assert(sizeof...(Bn) >= 2,
0111 "A minimum of two sequences are required");
0112
0113 detail::tuple<Bn...> const* bn_ = nullptr;
0114 detail::variant<
0115 buffers_iterator_type<Bn>..., past_end> it_{};
0116
0117 friend class buffers_cat_view<Bn...>;
0118
0119 template<std::size_t I>
0120 using C = std::integral_constant<std::size_t, I>;
0121
0122 public:
0123 using value_type = typename
0124 buffers_cat_view<Bn...>::value_type;
0125 using pointer = value_type const*;
0126 using reference = value_type;
0127 using difference_type = std::ptrdiff_t;
0128 using iterator_category =
0129 std::bidirectional_iterator_tag;
0130
0131 const_iterator() = default;
0132 const_iterator(const_iterator const& other) = default;
0133 const_iterator& operator=(
0134 const_iterator const& other) = default;
0135
0136 bool
0137 operator==(const_iterator const& other) const;
0138
0139 bool
0140 operator!=(const_iterator const& other) const
0141 {
0142 return ! (*this == other);
0143 }
0144
0145 reference
0146 operator*() const;
0147
0148 pointer
0149 operator->() const = delete;
0150
0151 const_iterator&
0152 operator++();
0153
0154 const_iterator
0155 operator++(int);
0156
0157 const_iterator&
0158 operator--();
0159
0160 const_iterator
0161 operator--(int);
0162
0163 private:
0164 const_iterator(
0165 detail::tuple<Bn...> const& bn,
0166 std::true_type);
0167
0168 const_iterator(
0169 detail::tuple<Bn...> const& bn,
0170 std::false_type);
0171
0172 struct dereference
0173 {
0174 const_iterator const& self;
0175
0176 BOOST_NORETURN reference
0177 operator()(mp11::mp_size_t<0>)
0178 {
0179 BOOST_BEAST_LOGIC_ERROR(
0180 "Dereferencing a default-constructed iterator");
0181 }
0182
0183 template<class I>
0184 reference operator()(I)
0185 {
0186 return *self.it_.template get<I::value>();
0187 }
0188 };
0189
0190 struct increment
0191 {
0192 const_iterator& self;
0193
0194 void
0195 operator()(mp11::mp_size_t<0>)
0196 {
0197 BOOST_BEAST_LOGIC_ERROR(
0198 "Incrementing a default-constructed iterator");
0199 }
0200
0201 template<std::size_t I>
0202 void
0203 operator()(mp11::mp_size_t<I>)
0204 {
0205 ++self.it_.template get<I>();
0206 next(mp11::mp_size_t<I>{});
0207 }
0208
0209 template<std::size_t I>
0210 void
0211 next(mp11::mp_size_t<I>)
0212 {
0213 auto& it = self.it_.template get<I>();
0214 for(;;)
0215 {
0216 if (it == net::buffer_sequence_end(
0217 detail::get<I-1>(*self.bn_)))
0218 break;
0219 if(net::const_buffer(*it).size() > 0)
0220 return;
0221 ++it;
0222 }
0223 self.it_.template emplace<I+1>(
0224 net::buffer_sequence_begin(
0225 detail::get<I>(*self.bn_)));
0226 next(mp11::mp_size_t<I+1>{});
0227 }
0228
0229 void
0230 operator()(mp11::mp_size_t<sizeof...(Bn)>)
0231 {
0232 auto constexpr I = sizeof...(Bn);
0233 ++self.it_.template get<I>();
0234 next(mp11::mp_size_t<I>{});
0235 }
0236
0237 void
0238 next(mp11::mp_size_t<sizeof...(Bn)>)
0239 {
0240 auto constexpr I = sizeof...(Bn);
0241 auto& it = self.it_.template get<I>();
0242 for(;;)
0243 {
0244 if (it == net::buffer_sequence_end(
0245 detail::get<I-1>(*self.bn_)))
0246 break;
0247 if(net::const_buffer(*it).size() > 0)
0248 return;
0249 ++it;
0250 }
0251
0252 self.it_.template emplace<I+1>();
0253 }
0254
0255 void
0256 operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
0257 {
0258 BOOST_BEAST_LOGIC_ERROR(
0259 "Incrementing a one-past-the-end iterator");
0260 }
0261 };
0262
0263 struct decrement
0264 {
0265 const_iterator& self;
0266
0267 void
0268 operator()(mp11::mp_size_t<0>)
0269 {
0270 BOOST_BEAST_LOGIC_ERROR(
0271 "Decrementing a default-constructed iterator");
0272 }
0273
0274 void
0275 operator()(mp11::mp_size_t<1>)
0276 {
0277 auto constexpr I = 1;
0278
0279 auto& it = self.it_.template get<I>();
0280 for(;;)
0281 {
0282 if(it == net::buffer_sequence_begin(
0283 detail::get<I-1>(*self.bn_)))
0284 {
0285 BOOST_BEAST_LOGIC_ERROR(
0286 "Decrementing an iterator to the beginning");
0287 }
0288 --it;
0289 if(net::const_buffer(*it).size() > 0)
0290 return;
0291 }
0292 }
0293
0294 template<std::size_t I>
0295 void
0296 operator()(mp11::mp_size_t<I>)
0297 {
0298 auto& it = self.it_.template get<I>();
0299 for(;;)
0300 {
0301 if(it == net::buffer_sequence_begin(
0302 detail::get<I-1>(*self.bn_)))
0303 break;
0304 --it;
0305 if(net::const_buffer(*it).size() > 0)
0306 return;
0307 }
0308 self.it_.template emplace<I-1>(
0309 net::buffer_sequence_end(
0310 detail::get<I-2>(*self.bn_)));
0311 (*this)(mp11::mp_size_t<I-1>{});
0312 }
0313
0314 void
0315 operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
0316 {
0317 auto constexpr I = sizeof...(Bn)+1;
0318 self.it_.template emplace<I-1>(
0319 net::buffer_sequence_end(
0320 detail::get<I-2>(*self.bn_)));
0321 (*this)(mp11::mp_size_t<I-1>{});
0322 }
0323 };
0324 };
0325
0326
0327
0328 template<class... Bn>
0329 buffers_cat_view<Bn...>::
0330 const_iterator::
0331 const_iterator(
0332 detail::tuple<Bn...> const& bn,
0333 std::true_type)
0334 : bn_(&bn)
0335 {
0336
0337 it_.template emplace<sizeof...(Bn)+1>();
0338 }
0339
0340 template<class... Bn>
0341 buffers_cat_view<Bn...>::
0342 const_iterator::
0343 const_iterator(
0344 detail::tuple<Bn...> const& bn,
0345 std::false_type)
0346 : bn_(&bn)
0347 {
0348 it_.template emplace<1>(
0349 net::buffer_sequence_begin(
0350 detail::get<0>(*bn_)));
0351 increment{*this}.next(
0352 mp11::mp_size_t<1>{});
0353 }
0354
0355 template<class... Bn>
0356 bool
0357 buffers_cat_view<Bn...>::
0358 const_iterator::
0359 operator==(const_iterator const& other) const
0360 {
0361 return bn_ == other.bn_ && it_ == other.it_;
0362 }
0363
0364 template<class... Bn>
0365 auto
0366 buffers_cat_view<Bn...>::
0367 const_iterator::
0368 operator*() const ->
0369 reference
0370 {
0371 return mp11::mp_with_index<
0372 sizeof...(Bn) + 2>(
0373 it_.index(),
0374 dereference{*this});
0375 }
0376
0377 template<class... Bn>
0378 auto
0379 buffers_cat_view<Bn...>::
0380 const_iterator::
0381 operator++() ->
0382 const_iterator&
0383 {
0384 mp11::mp_with_index<
0385 sizeof...(Bn) + 2>(
0386 it_.index(),
0387 increment{*this});
0388 return *this;
0389 }
0390
0391 template<class... Bn>
0392 auto
0393 buffers_cat_view<Bn...>::
0394 const_iterator::
0395 operator++(int) ->
0396 const_iterator
0397 {
0398 auto temp = *this;
0399 ++(*this);
0400 return temp;
0401 }
0402
0403 template<class... Bn>
0404 auto
0405 buffers_cat_view<Bn...>::
0406 const_iterator::
0407 operator--() ->
0408 const_iterator&
0409 {
0410 mp11::mp_with_index<
0411 sizeof...(Bn) + 2>(
0412 it_.index(),
0413 decrement{*this});
0414 return *this;
0415 }
0416
0417 template<class... Bn>
0418 auto
0419 buffers_cat_view<Bn...>::
0420 const_iterator::
0421 operator--(int) ->
0422 const_iterator
0423 {
0424 auto temp = *this;
0425 --(*this);
0426 return temp;
0427 }
0428
0429
0430
0431 template<class... Bn>
0432 buffers_cat_view<Bn...>::
0433 buffers_cat_view(Bn const&... bn)
0434 : bn_(bn...)
0435 {
0436 }
0437
0438
0439 template<class... Bn>
0440 auto
0441 buffers_cat_view<Bn...>::begin() const ->
0442 const_iterator
0443 {
0444 return const_iterator{bn_, std::false_type{}};
0445 }
0446
0447 template<class... Bn>
0448 auto
0449 buffers_cat_view<Bn...>::end() const->
0450 const_iterator
0451 {
0452 return const_iterator{bn_, std::true_type{}};
0453 }
0454
0455 }
0456 }
0457
0458 #endif