Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:54

0001 //
0002 // impl/buffered_read_stream.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // defined(_MSC_VER) && (_MSC_VER >= 1200)
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   //private:
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       // If you get an error on the following line it means that your handler
0130       // does not meet the documented type requirements for a ReadHandler.
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 } // namespace detail
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 // !defined(GENERATING_DOCUMENTATION)
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   //private:
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       // If you get an error on the following line it means that your handler
0306       // does not meet the documented type requirements for a ReadHandler.
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 } // namespace detail
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 // !defined(GENERATING_DOCUMENTATION)
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 } // namespace asio
0402 } // namespace boost
0403 
0404 #include <boost/asio/detail/pop_options.hpp>
0405 
0406 #endif // BOOST_ASIO_IMPL_BUFFERED_READ_STREAM_HPP