File indexing completed on 2025-01-18 09:28:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP
0012 #define BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/associator.hpp>
0019 #include <boost/asio/detail/handler_cont_helpers.hpp>
0020 #include <boost/asio/detail/handler_type_requirements.hpp>
0021 #include <boost/asio/detail/non_const_lvalue.hpp>
0022 #include <boost/asio/detail/type_traits.hpp>
0023
0024 #include <boost/asio/detail/push_options.hpp>
0025
0026 namespace boost {
0027 namespace asio {
0028
0029 template <typename Stream>
0030 std::size_t buffered_read_stream<Stream>::fill()
0031 {
0032 detail::buffer_resize_guard<detail::buffered_stream_storage>
0033 resize_guard(storage_);
0034 std::size_t previous_size = storage_.size();
0035 storage_.resize(storage_.capacity());
0036 storage_.resize(previous_size + next_layer_.read_some(buffer(
0037 storage_.data() + previous_size,
0038 storage_.size() - previous_size)));
0039 resize_guard.commit();
0040 return storage_.size() - previous_size;
0041 }
0042
0043 template <typename Stream>
0044 std::size_t buffered_read_stream<Stream>::fill(boost::system::error_code& ec)
0045 {
0046 detail::buffer_resize_guard<detail::buffered_stream_storage>
0047 resize_guard(storage_);
0048 std::size_t previous_size = storage_.size();
0049 storage_.resize(storage_.capacity());
0050 storage_.resize(previous_size + next_layer_.read_some(buffer(
0051 storage_.data() + previous_size,
0052 storage_.size() - previous_size),
0053 ec));
0054 resize_guard.commit();
0055 return storage_.size() - previous_size;
0056 }
0057
0058 namespace detail
0059 {
0060 template <typename ReadHandler>
0061 class buffered_fill_handler
0062 {
0063 public:
0064 buffered_fill_handler(detail::buffered_stream_storage& storage,
0065 std::size_t previous_size, ReadHandler& handler)
0066 : storage_(storage),
0067 previous_size_(previous_size),
0068 handler_(static_cast<ReadHandler&&>(handler))
0069 {
0070 }
0071
0072 buffered_fill_handler(const buffered_fill_handler& other)
0073 : storage_(other.storage_),
0074 previous_size_(other.previous_size_),
0075 handler_(other.handler_)
0076 {
0077 }
0078
0079 buffered_fill_handler(buffered_fill_handler&& other)
0080 : storage_(other.storage_),
0081 previous_size_(other.previous_size_),
0082 handler_(static_cast<ReadHandler&&>(other.handler_))
0083 {
0084 }
0085
0086 void operator()(const boost::system::error_code& ec,
0087 const std::size_t bytes_transferred)
0088 {
0089 storage_.resize(previous_size_ + bytes_transferred);
0090 static_cast<ReadHandler&&>(handler_)(ec, bytes_transferred);
0091 }
0092
0093
0094 detail::buffered_stream_storage& storage_;
0095 std::size_t previous_size_;
0096 ReadHandler handler_;
0097 };
0098
0099 template <typename ReadHandler>
0100 inline bool asio_handler_is_continuation(
0101 buffered_fill_handler<ReadHandler>* this_handler)
0102 {
0103 return boost_asio_handler_cont_helpers::is_continuation(
0104 this_handler->handler_);
0105 }
0106
0107 template <typename Stream>
0108 class initiate_async_buffered_fill
0109 {
0110 public:
0111 typedef typename remove_reference_t<
0112 Stream>::lowest_layer_type::executor_type executor_type;
0113
0114 explicit initiate_async_buffered_fill(
0115 remove_reference_t<Stream>& next_layer)
0116 : next_layer_(next_layer)
0117 {
0118 }
0119
0120 executor_type get_executor() const noexcept
0121 {
0122 return next_layer_.lowest_layer().get_executor();
0123 }
0124
0125 template <typename ReadHandler>
0126 void operator()(ReadHandler&& handler,
0127 buffered_stream_storage* storage) const
0128 {
0129
0130
0131 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0132
0133 non_const_lvalue<ReadHandler> handler2(handler);
0134 std::size_t previous_size = storage->size();
0135 storage->resize(storage->capacity());
0136 next_layer_.async_read_some(
0137 buffer(
0138 storage->data() + previous_size,
0139 storage->size() - previous_size),
0140 buffered_fill_handler<decay_t<ReadHandler>>(
0141 *storage, previous_size, handler2.value));
0142 }
0143
0144 private:
0145 remove_reference_t<Stream>& next_layer_;
0146 };
0147 }
0148
0149 #if !defined(GENERATING_DOCUMENTATION)
0150
0151 template <template <typename, typename> class Associator,
0152 typename ReadHandler, typename DefaultCandidate>
0153 struct associator<Associator,
0154 detail::buffered_fill_handler<ReadHandler>,
0155 DefaultCandidate>
0156 : Associator<ReadHandler, DefaultCandidate>
0157 {
0158 static typename Associator<ReadHandler, DefaultCandidate>::type get(
0159 const detail::buffered_fill_handler<ReadHandler>& h) noexcept
0160 {
0161 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0162 }
0163
0164 static auto get(const detail::buffered_fill_handler<ReadHandler>& h,
0165 const DefaultCandidate& c) noexcept
0166 -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0167 {
0168 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0169 }
0170 };
0171
0172 #endif
0173
0174 template <typename Stream>
0175 template <
0176 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0177 std::size_t)) ReadHandler>
0178 inline auto buffered_read_stream<Stream>::async_fill(ReadHandler&& handler)
0179 -> decltype(
0180 async_initiate<ReadHandler,
0181 void (boost::system::error_code, std::size_t)>(
0182 declval<detail::initiate_async_buffered_fill<Stream>>(),
0183 handler, declval<detail::buffered_stream_storage*>()))
0184 {
0185 return async_initiate<ReadHandler,
0186 void (boost::system::error_code, std::size_t)>(
0187 detail::initiate_async_buffered_fill<Stream>(next_layer_),
0188 handler, &storage_);
0189 }
0190
0191 template <typename Stream>
0192 template <typename MutableBufferSequence>
0193 std::size_t buffered_read_stream<Stream>::read_some(
0194 const MutableBufferSequence& buffers)
0195 {
0196 using boost::asio::buffer_size;
0197 if (buffer_size(buffers) == 0)
0198 return 0;
0199
0200 if (storage_.empty())
0201 this->fill();
0202
0203 return this->copy(buffers);
0204 }
0205
0206 template <typename Stream>
0207 template <typename MutableBufferSequence>
0208 std::size_t buffered_read_stream<Stream>::read_some(
0209 const MutableBufferSequence& buffers, boost::system::error_code& ec)
0210 {
0211 ec = boost::system::error_code();
0212
0213 using boost::asio::buffer_size;
0214 if (buffer_size(buffers) == 0)
0215 return 0;
0216
0217 if (storage_.empty() && !this->fill(ec))
0218 return 0;
0219
0220 return this->copy(buffers);
0221 }
0222
0223 namespace detail
0224 {
0225 template <typename MutableBufferSequence, typename ReadHandler>
0226 class buffered_read_some_handler
0227 {
0228 public:
0229 buffered_read_some_handler(detail::buffered_stream_storage& storage,
0230 const MutableBufferSequence& buffers, ReadHandler& handler)
0231 : storage_(storage),
0232 buffers_(buffers),
0233 handler_(static_cast<ReadHandler&&>(handler))
0234 {
0235 }
0236
0237 buffered_read_some_handler(const buffered_read_some_handler& other)
0238 : storage_(other.storage_),
0239 buffers_(other.buffers_),
0240 handler_(other.handler_)
0241 {
0242 }
0243
0244 buffered_read_some_handler(buffered_read_some_handler&& other)
0245 : storage_(other.storage_),
0246 buffers_(other.buffers_),
0247 handler_(static_cast<ReadHandler&&>(other.handler_))
0248 {
0249 }
0250
0251 void operator()(const boost::system::error_code& ec, std::size_t)
0252 {
0253 if (ec || storage_.empty())
0254 {
0255 const std::size_t length = 0;
0256 static_cast<ReadHandler&&>(handler_)(ec, length);
0257 }
0258 else
0259 {
0260 const std::size_t bytes_copied = boost::asio::buffer_copy(
0261 buffers_, storage_.data(), storage_.size());
0262 storage_.consume(bytes_copied);
0263 static_cast<ReadHandler&&>(handler_)(ec, bytes_copied);
0264 }
0265 }
0266
0267
0268 detail::buffered_stream_storage& storage_;
0269 MutableBufferSequence buffers_;
0270 ReadHandler handler_;
0271 };
0272
0273 template <typename MutableBufferSequence, typename ReadHandler>
0274 inline bool asio_handler_is_continuation(
0275 buffered_read_some_handler<
0276 MutableBufferSequence, ReadHandler>* this_handler)
0277 {
0278 return boost_asio_handler_cont_helpers::is_continuation(
0279 this_handler->handler_);
0280 }
0281
0282 template <typename Stream>
0283 class initiate_async_buffered_read_some
0284 {
0285 public:
0286 typedef typename remove_reference_t<
0287 Stream>::lowest_layer_type::executor_type executor_type;
0288
0289 explicit initiate_async_buffered_read_some(
0290 remove_reference_t<Stream>& next_layer)
0291 : next_layer_(next_layer)
0292 {
0293 }
0294
0295 executor_type get_executor() const noexcept
0296 {
0297 return next_layer_.lowest_layer().get_executor();
0298 }
0299
0300 template <typename ReadHandler, typename MutableBufferSequence>
0301 void operator()(ReadHandler&& handler,
0302 buffered_stream_storage* storage,
0303 const MutableBufferSequence& buffers) const
0304 {
0305
0306
0307 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0308
0309 using boost::asio::buffer_size;
0310 non_const_lvalue<ReadHandler> handler2(handler);
0311 if (buffer_size(buffers) == 0 || !storage->empty())
0312 {
0313 next_layer_.async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
0314 buffered_read_some_handler<MutableBufferSequence,
0315 decay_t<ReadHandler>>(
0316 *storage, buffers, handler2.value));
0317 }
0318 else
0319 {
0320 initiate_async_buffered_fill<Stream>(this->next_layer_)(
0321 buffered_read_some_handler<MutableBufferSequence,
0322 decay_t<ReadHandler>>(
0323 *storage, buffers, handler2.value),
0324 storage);
0325 }
0326 }
0327
0328 private:
0329 remove_reference_t<Stream>& next_layer_;
0330 };
0331 }
0332
0333 #if !defined(GENERATING_DOCUMENTATION)
0334
0335 template <template <typename, typename> class Associator,
0336 typename MutableBufferSequence, typename ReadHandler,
0337 typename DefaultCandidate>
0338 struct associator<Associator,
0339 detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
0340 DefaultCandidate>
0341 : Associator<ReadHandler, DefaultCandidate>
0342 {
0343 static typename Associator<ReadHandler, DefaultCandidate>::type get(
0344 const detail::buffered_read_some_handler<
0345 MutableBufferSequence, ReadHandler>& h) noexcept
0346 {
0347 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0348 }
0349
0350 static auto get(
0351 const detail::buffered_read_some_handler<
0352 MutableBufferSequence, ReadHandler>& h,
0353 const DefaultCandidate& c) noexcept
0354 -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0355 {
0356 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0357 }
0358 };
0359
0360 #endif
0361
0362 template <typename Stream>
0363 template <typename MutableBufferSequence,
0364 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0365 std::size_t)) ReadHandler>
0366 inline auto buffered_read_stream<Stream>::async_read_some(
0367 const MutableBufferSequence& buffers, ReadHandler&& handler)
0368 -> decltype(
0369 async_initiate<ReadHandler,
0370 void (boost::system::error_code, std::size_t)>(
0371 declval<detail::initiate_async_buffered_read_some<Stream>>(),
0372 handler, declval<detail::buffered_stream_storage*>(), buffers))
0373 {
0374 return async_initiate<ReadHandler,
0375 void (boost::system::error_code, std::size_t)>(
0376 detail::initiate_async_buffered_read_some<Stream>(next_layer_),
0377 handler, &storage_, buffers);
0378 }
0379
0380 template <typename Stream>
0381 template <typename MutableBufferSequence>
0382 std::size_t buffered_read_stream<Stream>::peek(
0383 const MutableBufferSequence& buffers)
0384 {
0385 if (storage_.empty())
0386 this->fill();
0387 return this->peek_copy(buffers);
0388 }
0389
0390 template <typename Stream>
0391 template <typename MutableBufferSequence>
0392 std::size_t buffered_read_stream<Stream>::peek(
0393 const MutableBufferSequence& buffers, boost::system::error_code& ec)
0394 {
0395 ec = boost::system::error_code();
0396 if (storage_.empty() && !this->fill(ec))
0397 return 0;
0398 return this->peek_copy(buffers);
0399 }
0400
0401 }
0402 }
0403
0404 #include <boost/asio/detail/pop_options.hpp>
0405
0406 #endif