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