File indexing completed on 2025-09-17 08:24:08
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 #else
0056 # define BOOST_BEAST_UNREACHABLE() __builtin_unreachable()
0057 #endif
0058
0059 #ifdef BOOST_BEAST_TESTS
0060
0061 #define BOOST_BEAST_LOGIC_ERROR(s) \
0062 { \
0063 BOOST_THROW_EXCEPTION(std::logic_error((s))); \
0064 }
0065
0066 #define BOOST_BEAST_LOGIC_ERROR_RETURN(s, v) \
0067 { \
0068 BOOST_THROW_EXCEPTION(std::logic_error((s))); \
0069 }
0070
0071 #else
0072
0073 #define BOOST_BEAST_LOGIC_ERROR(s) \
0074 { \
0075 BOOST_ASSERT_MSG(false, s); \
0076 BOOST_BEAST_UNREACHABLE(); \
0077 }
0078
0079 #define BOOST_BEAST_LOGIC_ERROR_RETURN(s, v) \
0080 { \
0081 BOOST_ASSERT_MSG(false, s); \
0082 return v; \
0083 }
0084
0085 #endif
0086
0087 namespace detail {
0088
0089 struct buffers_cat_view_iterator_base
0090 {
0091 struct past_end
0092 {
0093 char unused = 0;
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 reference
0177 operator()(mp11::mp_size_t<0>)
0178 {
0179 BOOST_BEAST_LOGIC_ERROR_RETURN(
0180 "Dereferencing a default-constructed iterator", {});
0181 }
0182
0183 reference
0184 operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
0185 {
0186 BOOST_BEAST_LOGIC_ERROR_RETURN(
0187 "Dereferencing a one-past-the-end iterator", {});
0188 }
0189
0190 template<class I>
0191 reference operator()(I)
0192 {
0193 return *self.it_.template get<I::value>();
0194 }
0195 };
0196
0197 struct increment
0198 {
0199 const_iterator& self;
0200
0201 void
0202 operator()(mp11::mp_size_t<0>)
0203 {
0204 BOOST_BEAST_LOGIC_ERROR(
0205 "Incrementing a default-constructed iterator");
0206 }
0207
0208 template<std::size_t I>
0209 void
0210 operator()(mp11::mp_size_t<I>)
0211 {
0212 ++self.it_.template get<I>();
0213 next(mp11::mp_size_t<I>{});
0214 }
0215
0216 template<std::size_t I>
0217 void
0218 next(mp11::mp_size_t<I>)
0219 {
0220 auto& it = self.it_.template get<I>();
0221 for(;;)
0222 {
0223 if (it == net::buffer_sequence_end(
0224 detail::get<I-1>(*self.bn_)))
0225 break;
0226 if(net::const_buffer(*it).size() > 0)
0227 return;
0228 ++it;
0229 }
0230 self.it_.template emplace<I+1>(
0231 net::buffer_sequence_begin(
0232 detail::get<I>(*self.bn_)));
0233 next(mp11::mp_size_t<I+1>{});
0234 }
0235
0236 void
0237 operator()(mp11::mp_size_t<sizeof...(Bn)>)
0238 {
0239 auto constexpr I = sizeof...(Bn);
0240 ++self.it_.template get<I>();
0241 next(mp11::mp_size_t<I>{});
0242 }
0243
0244 void
0245 next(mp11::mp_size_t<sizeof...(Bn)>)
0246 {
0247 auto constexpr I = sizeof...(Bn);
0248 auto& it = self.it_.template get<I>();
0249 for(;;)
0250 {
0251 if (it == net::buffer_sequence_end(
0252 detail::get<I-1>(*self.bn_)))
0253 break;
0254 if(net::const_buffer(*it).size() > 0)
0255 return;
0256 ++it;
0257 }
0258
0259 self.it_.template emplace<I+1>();
0260 }
0261
0262 void
0263 operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
0264 {
0265 BOOST_BEAST_LOGIC_ERROR(
0266 "Incrementing a one-past-the-end iterator");
0267 }
0268 };
0269
0270 struct decrement
0271 {
0272 const_iterator& self;
0273
0274 void
0275 operator()(mp11::mp_size_t<0>)
0276 {
0277 BOOST_BEAST_LOGIC_ERROR(
0278 "Decrementing a default-constructed iterator");
0279 }
0280
0281 void
0282 operator()(mp11::mp_size_t<1>)
0283 {
0284 auto constexpr I = 1;
0285
0286 auto& it = self.it_.template get<I>();
0287 for(;;)
0288 {
0289 if(it == net::buffer_sequence_begin(
0290 detail::get<I-1>(*self.bn_)))
0291 {
0292 BOOST_BEAST_LOGIC_ERROR(
0293 "Decrementing an iterator to the beginning");
0294 }
0295 --it;
0296 if(net::const_buffer(*it).size() > 0)
0297 return;
0298 }
0299 }
0300
0301 template<std::size_t I>
0302 void
0303 operator()(mp11::mp_size_t<I>)
0304 {
0305 auto& it = self.it_.template get<I>();
0306 for(;;)
0307 {
0308 if(it == net::buffer_sequence_begin(
0309 detail::get<I-1>(*self.bn_)))
0310 break;
0311 --it;
0312 if(net::const_buffer(*it).size() > 0)
0313 return;
0314 }
0315 self.it_.template emplace<I-1>(
0316 net::buffer_sequence_end(
0317 detail::get<I-2>(*self.bn_)));
0318 (*this)(mp11::mp_size_t<I-1>{});
0319 }
0320
0321 void
0322 operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
0323 {
0324 auto constexpr I = sizeof...(Bn)+1;
0325 self.it_.template emplace<I-1>(
0326 net::buffer_sequence_end(
0327 detail::get<I-2>(*self.bn_)));
0328 (*this)(mp11::mp_size_t<I-1>{});
0329 }
0330 };
0331 };
0332
0333
0334
0335 template<class... Bn>
0336 buffers_cat_view<Bn...>::
0337 const_iterator::
0338 const_iterator(
0339 detail::tuple<Bn...> const& bn,
0340 std::true_type)
0341 : bn_(&bn)
0342 {
0343
0344 it_.template emplace<sizeof...(Bn)+1>();
0345 }
0346
0347 template<class... Bn>
0348 buffers_cat_view<Bn...>::
0349 const_iterator::
0350 const_iterator(
0351 detail::tuple<Bn...> const& bn,
0352 std::false_type)
0353 : bn_(&bn)
0354 {
0355 it_.template emplace<1>(
0356 net::buffer_sequence_begin(
0357 detail::get<0>(*bn_)));
0358 increment{*this}.next(
0359 mp11::mp_size_t<1>{});
0360 }
0361
0362 template<class... Bn>
0363 bool
0364 buffers_cat_view<Bn...>::
0365 const_iterator::
0366 operator==(const_iterator const& other) const
0367 {
0368 return bn_ == other.bn_ && it_ == other.it_;
0369 }
0370
0371 template<class... Bn>
0372 auto
0373 buffers_cat_view<Bn...>::
0374 const_iterator::
0375 operator*() const ->
0376 reference
0377 {
0378 return mp11::mp_with_index<
0379 sizeof...(Bn) + 2>(
0380 it_.index(),
0381 dereference{*this});
0382 }
0383
0384 template<class... Bn>
0385 auto
0386 buffers_cat_view<Bn...>::
0387 const_iterator::
0388 operator++() ->
0389 const_iterator&
0390 {
0391 mp11::mp_with_index<
0392 sizeof...(Bn) + 2>(
0393 it_.index(),
0394 increment{*this});
0395 return *this;
0396 }
0397
0398 template<class... Bn>
0399 auto
0400 buffers_cat_view<Bn...>::
0401 const_iterator::
0402 operator++(int) ->
0403 const_iterator
0404 {
0405 auto temp = *this;
0406 ++(*this);
0407 return temp;
0408 }
0409
0410 template<class... Bn>
0411 auto
0412 buffers_cat_view<Bn...>::
0413 const_iterator::
0414 operator--() ->
0415 const_iterator&
0416 {
0417 mp11::mp_with_index<
0418 sizeof...(Bn) + 2>(
0419 it_.index(),
0420 decrement{*this});
0421 return *this;
0422 }
0423
0424 template<class... Bn>
0425 auto
0426 buffers_cat_view<Bn...>::
0427 const_iterator::
0428 operator--(int) ->
0429 const_iterator
0430 {
0431 auto temp = *this;
0432 --(*this);
0433 return temp;
0434 }
0435
0436
0437
0438 template<class... Bn>
0439 buffers_cat_view<Bn...>::
0440 buffers_cat_view(Bn const&... bn)
0441 : bn_(bn...)
0442 {
0443 }
0444
0445
0446 template<class... Bn>
0447 auto
0448 buffers_cat_view<Bn...>::begin() const ->
0449 const_iterator
0450 {
0451 return const_iterator{bn_, std::false_type{}};
0452 }
0453
0454 template<class... Bn>
0455 auto
0456 buffers_cat_view<Bn...>::end() const->
0457 const_iterator
0458 {
0459 return const_iterator{bn_, std::true_type{}};
0460 }
0461
0462 }
0463 }
0464
0465 #endif