Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 08:09:02

0001 //
0002 // impl/read_at.hpp
0003 // ~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 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_READ_AT_HPP
0012 #define BOOST_ASIO_IMPL_READ_AT_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <algorithm>
0019 #include <boost/asio/associator.hpp>
0020 #include <boost/asio/buffer.hpp>
0021 #include <boost/asio/detail/array_fwd.hpp>
0022 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0023 #include <boost/asio/detail/base_from_completion_cond.hpp>
0024 #include <boost/asio/detail/bind_handler.hpp>
0025 #include <boost/asio/detail/consuming_buffers.hpp>
0026 #include <boost/asio/detail/dependent_type.hpp>
0027 #include <boost/asio/detail/handler_cont_helpers.hpp>
0028 #include <boost/asio/detail/handler_tracking.hpp>
0029 #include <boost/asio/detail/handler_type_requirements.hpp>
0030 #include <boost/asio/detail/non_const_lvalue.hpp>
0031 #include <boost/asio/detail/throw_error.hpp>
0032 #include <boost/asio/error.hpp>
0033 
0034 #include <boost/asio/detail/push_options.hpp>
0035 
0036 namespace boost {
0037 namespace asio {
0038 
0039 namespace detail
0040 {
0041   template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
0042       typename MutableBufferIterator, typename CompletionCondition>
0043   std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
0044       uint64_t offset, const MutableBufferSequence& buffers,
0045       const MutableBufferIterator&, CompletionCondition completion_condition,
0046       boost::system::error_code& ec)
0047   {
0048     ec = boost::system::error_code();
0049     boost::asio::detail::consuming_buffers<mutable_buffer,
0050         MutableBufferSequence, MutableBufferIterator> tmp(buffers);
0051     while (!tmp.empty())
0052     {
0053       if (std::size_t max_size = detail::adapt_completion_condition_result(
0054             completion_condition(ec, tmp.total_consumed())))
0055       {
0056         tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
0057               tmp.prepare(max_size), ec));
0058       }
0059       else
0060         break;
0061     }
0062     return tmp.total_consumed();
0063   }
0064 } // namespace detail
0065 
0066 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
0067     typename CompletionCondition>
0068 std::size_t read_at(SyncRandomAccessReadDevice& d,
0069     uint64_t offset, const MutableBufferSequence& buffers,
0070     CompletionCondition completion_condition, boost::system::error_code& ec,
0071     constraint_t<
0072       is_completion_condition<CompletionCondition>::value
0073     >)
0074 {
0075   return detail::read_at_buffer_sequence(d, offset, buffers,
0076       boost::asio::buffer_sequence_begin(buffers),
0077       static_cast<CompletionCondition&&>(completion_condition), ec);
0078 }
0079 
0080 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
0081 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0082     uint64_t offset, const MutableBufferSequence& buffers)
0083 {
0084   boost::system::error_code ec;
0085   std::size_t bytes_transferred = read_at(
0086       d, offset, buffers, transfer_all(), ec);
0087   boost::asio::detail::throw_error(ec, "read_at");
0088   return bytes_transferred;
0089 }
0090 
0091 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
0092 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0093     uint64_t offset, const MutableBufferSequence& buffers,
0094     boost::system::error_code& ec)
0095 {
0096   return read_at(d, offset, buffers, transfer_all(), ec);
0097 }
0098 
0099 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
0100     typename CompletionCondition>
0101 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0102     uint64_t offset, const MutableBufferSequence& buffers,
0103     CompletionCondition completion_condition,
0104     constraint_t<
0105       is_completion_condition<CompletionCondition>::value
0106     >)
0107 {
0108   boost::system::error_code ec;
0109   std::size_t bytes_transferred = read_at(d, offset, buffers,
0110       static_cast<CompletionCondition&&>(completion_condition), ec);
0111   boost::asio::detail::throw_error(ec, "read_at");
0112   return bytes_transferred;
0113 }
0114 
0115 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0116 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0117 
0118 template <typename SyncRandomAccessReadDevice, typename Allocator,
0119     typename CompletionCondition>
0120 std::size_t read_at(SyncRandomAccessReadDevice& d,
0121     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0122     CompletionCondition completion_condition, boost::system::error_code& ec,
0123     constraint_t<
0124       is_completion_condition<CompletionCondition>::value
0125     >)
0126 {
0127   ec = boost::system::error_code();
0128   std::size_t total_transferred = 0;
0129   std::size_t max_size = detail::adapt_completion_condition_result(
0130         completion_condition(ec, total_transferred));
0131   std::size_t bytes_available = read_size_helper(b, max_size);
0132   while (bytes_available > 0)
0133   {
0134     std::size_t bytes_transferred = d.read_some_at(
0135         offset + total_transferred, b.prepare(bytes_available), ec);
0136     b.commit(bytes_transferred);
0137     total_transferred += bytes_transferred;
0138     max_size = detail::adapt_completion_condition_result(
0139           completion_condition(ec, total_transferred));
0140     bytes_available = read_size_helper(b, max_size);
0141   }
0142   return total_transferred;
0143 }
0144 
0145 template <typename SyncRandomAccessReadDevice, typename Allocator>
0146 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0147     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
0148 {
0149   boost::system::error_code ec;
0150   std::size_t bytes_transferred = read_at(
0151       d, offset, b, transfer_all(), ec);
0152   boost::asio::detail::throw_error(ec, "read_at");
0153   return bytes_transferred;
0154 }
0155 
0156 template <typename SyncRandomAccessReadDevice, typename Allocator>
0157 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0158     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0159     boost::system::error_code& ec)
0160 {
0161   return read_at(d, offset, b, transfer_all(), ec);
0162 }
0163 
0164 template <typename SyncRandomAccessReadDevice, typename Allocator,
0165     typename CompletionCondition>
0166 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0167     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0168     CompletionCondition completion_condition,
0169     constraint_t<
0170       is_completion_condition<CompletionCondition>::value
0171     >)
0172 {
0173   boost::system::error_code ec;
0174   std::size_t bytes_transferred = read_at(d, offset, b,
0175       static_cast<CompletionCondition&&>(completion_condition), ec);
0176   boost::asio::detail::throw_error(ec, "read_at");
0177   return bytes_transferred;
0178 }
0179 
0180 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0181 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0182 
0183 namespace detail
0184 {
0185   template <typename AsyncRandomAccessReadDevice,
0186       typename MutableBufferSequence, typename MutableBufferIterator,
0187       typename CompletionCondition, typename ReadHandler>
0188   class read_at_op
0189     : public base_from_cancellation_state<ReadHandler>,
0190       base_from_completion_cond<CompletionCondition>
0191   {
0192   public:
0193     read_at_op(AsyncRandomAccessReadDevice& device,
0194         uint64_t offset, const MutableBufferSequence& buffers,
0195         CompletionCondition& completion_condition, ReadHandler& handler)
0196       : base_from_cancellation_state<ReadHandler>(
0197           handler, enable_partial_cancellation()),
0198         base_from_completion_cond<CompletionCondition>(completion_condition),
0199         device_(device),
0200         offset_(offset),
0201         buffers_(buffers),
0202         start_(0),
0203         handler_(static_cast<ReadHandler&&>(handler))
0204     {
0205     }
0206 
0207     read_at_op(const read_at_op& other)
0208       : base_from_cancellation_state<ReadHandler>(other),
0209         base_from_completion_cond<CompletionCondition>(other),
0210         device_(other.device_),
0211         offset_(other.offset_),
0212         buffers_(other.buffers_),
0213         start_(other.start_),
0214         handler_(other.handler_)
0215     {
0216     }
0217 
0218     read_at_op(read_at_op&& other)
0219       : base_from_cancellation_state<ReadHandler>(
0220           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0221         base_from_completion_cond<CompletionCondition>(
0222           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0223         device_(other.device_),
0224         offset_(other.offset_),
0225         buffers_(static_cast<buffers_type&&>(other.buffers_)),
0226         start_(other.start_),
0227         handler_(static_cast<ReadHandler&&>(other.handler_))
0228     {
0229     }
0230 
0231     void operator()(boost::system::error_code ec,
0232         std::size_t bytes_transferred, int start = 0)
0233     {
0234       std::size_t max_size;
0235       switch (start_ = start)
0236       {
0237         case 1:
0238         max_size = this->check_for_completion(ec, buffers_.total_consumed());
0239         for (;;)
0240         {
0241           {
0242             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
0243             device_.async_read_some_at(
0244                 offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
0245                 static_cast<read_at_op&&>(*this));
0246           }
0247           return; default:
0248           buffers_.consume(bytes_transferred);
0249           if ((!ec && bytes_transferred == 0) || buffers_.empty())
0250             break;
0251           max_size = this->check_for_completion(ec, buffers_.total_consumed());
0252           if (max_size == 0)
0253             break;
0254           if (this->cancelled() != cancellation_type::none)
0255           {
0256             ec = boost::asio::error::operation_aborted;
0257             break;
0258           }
0259         }
0260 
0261         static_cast<ReadHandler&&>(handler_)(
0262             static_cast<const boost::system::error_code&>(ec),
0263             static_cast<const std::size_t&>(buffers_.total_consumed()));
0264       }
0265     }
0266 
0267   //private:
0268     typedef boost::asio::detail::consuming_buffers<mutable_buffer,
0269         MutableBufferSequence, MutableBufferIterator> buffers_type;
0270 
0271     AsyncRandomAccessReadDevice& device_;
0272     uint64_t offset_;
0273     buffers_type buffers_;
0274     int start_;
0275     ReadHandler handler_;
0276   };
0277 
0278   template <typename AsyncRandomAccessReadDevice,
0279       typename MutableBufferSequence, typename MutableBufferIterator,
0280       typename CompletionCondition, typename ReadHandler>
0281   inline bool asio_handler_is_continuation(
0282       read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
0283         MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
0284   {
0285     return this_handler->start_ == 0 ? true
0286       : boost_asio_handler_cont_helpers::is_continuation(
0287           this_handler->handler_);
0288   }
0289 
0290   template <typename AsyncRandomAccessReadDevice,
0291       typename MutableBufferSequence, typename MutableBufferIterator,
0292       typename CompletionCondition, typename ReadHandler>
0293   inline void start_read_at_op(AsyncRandomAccessReadDevice& d,
0294       uint64_t offset, const MutableBufferSequence& buffers,
0295       const MutableBufferIterator&, CompletionCondition& completion_condition,
0296       ReadHandler& handler)
0297   {
0298     detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
0299       MutableBufferIterator, CompletionCondition, ReadHandler>(
0300         d, offset, buffers, completion_condition, handler)(
0301           boost::system::error_code(), 0, 1);
0302   }
0303 
0304   template <typename AsyncRandomAccessReadDevice>
0305   class initiate_async_read_at
0306   {
0307   public:
0308     typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
0309 
0310     explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device)
0311       : device_(device)
0312     {
0313     }
0314 
0315     executor_type get_executor() const noexcept
0316     {
0317       return device_.get_executor();
0318     }
0319 
0320     template <typename ReadHandler, typename MutableBufferSequence,
0321         typename CompletionCondition>
0322     void operator()(ReadHandler&& handler,
0323         uint64_t offset, const MutableBufferSequence& buffers,
0324         CompletionCondition&& completion_cond) const
0325     {
0326       // If you get an error on the following line it means that your handler
0327       // does not meet the documented type requirements for a ReadHandler.
0328       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0329 
0330       non_const_lvalue<ReadHandler> handler2(handler);
0331       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0332       start_read_at_op(device_, offset, buffers,
0333           boost::asio::buffer_sequence_begin(buffers),
0334           completion_cond2.value, handler2.value);
0335     }
0336 
0337   private:
0338     AsyncRandomAccessReadDevice& device_;
0339   };
0340 } // namespace detail
0341 
0342 #if !defined(GENERATING_DOCUMENTATION)
0343 
0344 template <template <typename, typename> class Associator,
0345     typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
0346     typename MutableBufferIterator, typename CompletionCondition,
0347     typename ReadHandler, typename DefaultCandidate>
0348 struct associator<Associator,
0349     detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
0350       MutableBufferIterator, CompletionCondition, ReadHandler>,
0351     DefaultCandidate>
0352   : Associator<ReadHandler, DefaultCandidate>
0353 {
0354   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0355       const detail::read_at_op<AsyncRandomAccessReadDevice,
0356         MutableBufferSequence, MutableBufferIterator,
0357         CompletionCondition, ReadHandler>& h) noexcept
0358   {
0359     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0360   }
0361 
0362   static auto get(
0363       const detail::read_at_op<AsyncRandomAccessReadDevice,
0364         MutableBufferSequence, MutableBufferIterator,
0365         CompletionCondition, ReadHandler>& h,
0366       const DefaultCandidate& c) noexcept
0367     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0368   {
0369     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0370   }
0371 };
0372 
0373 #endif // !defined(GENERATING_DOCUMENTATION)
0374 
0375 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0376 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0377 
0378 namespace detail
0379 {
0380   template <typename AsyncRandomAccessReadDevice, typename Allocator,
0381       typename CompletionCondition, typename ReadHandler>
0382   class read_at_streambuf_op
0383     : public base_from_cancellation_state<ReadHandler>,
0384       base_from_completion_cond<CompletionCondition>
0385   {
0386   public:
0387     read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
0388         uint64_t offset, basic_streambuf<Allocator>& streambuf,
0389         CompletionCondition& completion_condition, ReadHandler& handler)
0390       : base_from_cancellation_state<ReadHandler>(
0391           handler, enable_partial_cancellation()),
0392         base_from_completion_cond<CompletionCondition>(completion_condition),
0393         device_(device),
0394         offset_(offset),
0395         streambuf_(streambuf),
0396         start_(0),
0397         total_transferred_(0),
0398         handler_(static_cast<ReadHandler&&>(handler))
0399     {
0400     }
0401 
0402     read_at_streambuf_op(const read_at_streambuf_op& other)
0403       : base_from_cancellation_state<ReadHandler>(other),
0404         base_from_completion_cond<CompletionCondition>(other),
0405         device_(other.device_),
0406         offset_(other.offset_),
0407         streambuf_(other.streambuf_),
0408         start_(other.start_),
0409         total_transferred_(other.total_transferred_),
0410         handler_(other.handler_)
0411     {
0412     }
0413 
0414     read_at_streambuf_op(read_at_streambuf_op&& other)
0415       : base_from_cancellation_state<ReadHandler>(
0416           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0417         base_from_completion_cond<CompletionCondition>(
0418           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0419         device_(other.device_),
0420         offset_(other.offset_),
0421         streambuf_(other.streambuf_),
0422         start_(other.start_),
0423         total_transferred_(other.total_transferred_),
0424         handler_(static_cast<ReadHandler&&>(other.handler_))
0425     {
0426     }
0427 
0428     void operator()(boost::system::error_code ec,
0429         std::size_t bytes_transferred, int start = 0)
0430     {
0431       std::size_t max_size, bytes_available;
0432       switch (start_ = start)
0433       {
0434         case 1:
0435         max_size = this->check_for_completion(ec, total_transferred_);
0436         bytes_available = read_size_helper(streambuf_, max_size);
0437         for (;;)
0438         {
0439           {
0440             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
0441             device_.async_read_some_at(offset_ + total_transferred_,
0442                 streambuf_.prepare(bytes_available),
0443                 static_cast<read_at_streambuf_op&&>(*this));
0444           }
0445           return; default:
0446           total_transferred_ += bytes_transferred;
0447           streambuf_.commit(bytes_transferred);
0448           max_size = this->check_for_completion(ec, total_transferred_);
0449           bytes_available = read_size_helper(streambuf_, max_size);
0450           if ((!ec && bytes_transferred == 0) || bytes_available == 0)
0451             break;
0452           if (this->cancelled() != cancellation_type::none)
0453           {
0454             ec = boost::asio::error::operation_aborted;
0455             break;
0456           }
0457         }
0458 
0459         static_cast<ReadHandler&&>(handler_)(
0460             static_cast<const boost::system::error_code&>(ec),
0461             static_cast<const std::size_t&>(total_transferred_));
0462       }
0463     }
0464 
0465   //private:
0466     AsyncRandomAccessReadDevice& device_;
0467     uint64_t offset_;
0468     boost::asio::basic_streambuf<Allocator>& streambuf_;
0469     int start_;
0470     std::size_t total_transferred_;
0471     ReadHandler handler_;
0472   };
0473 
0474   template <typename AsyncRandomAccessReadDevice, typename Allocator,
0475       typename CompletionCondition, typename ReadHandler>
0476   inline bool asio_handler_is_continuation(
0477       read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
0478         CompletionCondition, ReadHandler>* this_handler)
0479   {
0480     return this_handler->start_ == 0 ? true
0481       : boost_asio_handler_cont_helpers::is_continuation(
0482           this_handler->handler_);
0483   }
0484 
0485   template <typename AsyncRandomAccessReadDevice>
0486   class initiate_async_read_at_streambuf
0487   {
0488   public:
0489     typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
0490 
0491     explicit initiate_async_read_at_streambuf(
0492         AsyncRandomAccessReadDevice& device)
0493       : device_(device)
0494     {
0495     }
0496 
0497     executor_type get_executor() const noexcept
0498     {
0499       return device_.get_executor();
0500     }
0501 
0502     template <typename ReadHandler,
0503         typename Allocator, typename CompletionCondition>
0504     void operator()(ReadHandler&& handler,
0505         uint64_t offset, basic_streambuf<Allocator>* b,
0506         CompletionCondition&& completion_cond) const
0507     {
0508       // If you get an error on the following line it means that your handler
0509       // does not meet the documented type requirements for a ReadHandler.
0510       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0511 
0512       non_const_lvalue<ReadHandler> handler2(handler);
0513       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0514       read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
0515         CompletionCondition, decay_t<ReadHandler>>(
0516           device_, offset, *b, completion_cond2.value, handler2.value)(
0517             boost::system::error_code(), 0, 1);
0518     }
0519 
0520   private:
0521     AsyncRandomAccessReadDevice& device_;
0522   };
0523 } // namespace detail
0524 
0525 #if !defined(GENERATING_DOCUMENTATION)
0526 
0527 template <template <typename, typename> class Associator,
0528     typename AsyncRandomAccessReadDevice, typename Executor,
0529     typename CompletionCondition, typename ReadHandler,
0530     typename DefaultCandidate>
0531 struct associator<Associator,
0532     detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
0533       Executor, CompletionCondition, ReadHandler>,
0534     DefaultCandidate>
0535   : Associator<ReadHandler, DefaultCandidate>
0536 {
0537   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0538       const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
0539         Executor, CompletionCondition, ReadHandler>& h) noexcept
0540   {
0541     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0542   }
0543 
0544   static auto get(
0545       const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
0546         Executor, CompletionCondition, ReadHandler>& h,
0547       const DefaultCandidate& c) noexcept
0548     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0549   {
0550     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0551   }
0552 };
0553 
0554 #endif // !defined(GENERATING_DOCUMENTATION)
0555 
0556 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0557 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0558 
0559 } // namespace asio
0560 } // namespace boost
0561 
0562 #include <boost/asio/detail/pop_options.hpp>
0563 
0564 #endif // BOOST_ASIO_IMPL_READ_AT_HPP