Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:28:46

0001 //
0002 // detail/consuming_buffers.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 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_DETAIL_CONSUMING_BUFFERS_HPP
0012 #define BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_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/detail/config.hpp>
0019 #include <cstddef>
0020 #include <boost/asio/buffer.hpp>
0021 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0022 #include <boost/asio/detail/limits.hpp>
0023 #include <boost/asio/registered_buffer.hpp>
0024 
0025 #include <boost/asio/detail/push_options.hpp>
0026 
0027 namespace boost {
0028 namespace asio {
0029 namespace detail {
0030 
0031 // Helper template to determine the maximum number of prepared buffers.
0032 template <typename Buffers>
0033 struct prepared_buffers_max
0034 {
0035   enum { value = buffer_sequence_adapter_base::max_buffers };
0036 };
0037 
0038 template <typename Elem, std::size_t N>
0039 struct prepared_buffers_max<boost::array<Elem, N>>
0040 {
0041   enum { value = N };
0042 };
0043 
0044 template <typename Elem, std::size_t N>
0045 struct prepared_buffers_max<std::array<Elem, N>>
0046 {
0047   enum { value = N };
0048 };
0049 
0050 // A buffer sequence used to represent a subsequence of the buffers.
0051 template <typename Buffer, std::size_t MaxBuffers>
0052 struct prepared_buffers
0053 {
0054   typedef Buffer value_type;
0055   typedef const Buffer* const_iterator;
0056 
0057   enum { max_buffers = MaxBuffers < 16 ? MaxBuffers : 16 };
0058 
0059   prepared_buffers() : count(0) {}
0060   const_iterator begin() const { return elems; }
0061   const_iterator end() const { return elems + count; }
0062 
0063   Buffer elems[max_buffers];
0064   std::size_t count;
0065 };
0066 
0067 // A proxy for a sub-range in a list of buffers.
0068 template <typename Buffer, typename Buffers, typename Buffer_Iterator>
0069 class consuming_buffers
0070 {
0071 public:
0072   typedef prepared_buffers<Buffer, prepared_buffers_max<Buffers>::value>
0073     prepared_buffers_type;
0074 
0075   // Construct to represent the entire list of buffers.
0076   explicit consuming_buffers(const Buffers& buffers)
0077     : buffers_(buffers),
0078       total_consumed_(0),
0079       next_elem_(0),
0080       next_elem_offset_(0)
0081   {
0082     using boost::asio::buffer_size;
0083     total_size_ = buffer_size(buffers);
0084   }
0085 
0086   // Determine if we are at the end of the buffers.
0087   bool empty() const
0088   {
0089     return total_consumed_ >= total_size_;
0090   }
0091 
0092   // Get the buffer for a single transfer, with a size.
0093   prepared_buffers_type prepare(std::size_t max_size)
0094   {
0095     prepared_buffers_type result;
0096 
0097     Buffer_Iterator next = boost::asio::buffer_sequence_begin(buffers_);
0098     Buffer_Iterator end = boost::asio::buffer_sequence_end(buffers_);
0099 
0100     std::advance(next, next_elem_);
0101     std::size_t elem_offset = next_elem_offset_;
0102     while (next != end && max_size > 0 && (result.count) < result.max_buffers)
0103     {
0104       Buffer next_buf = Buffer(*next) + elem_offset;
0105       result.elems[result.count] = boost::asio::buffer(next_buf, max_size);
0106       max_size -= result.elems[result.count].size();
0107       elem_offset = 0;
0108       if (result.elems[result.count].size() > 0)
0109         ++result.count;
0110       ++next;
0111     }
0112 
0113     return result;
0114   }
0115 
0116   // Consume the specified number of bytes from the buffers.
0117   void consume(std::size_t size)
0118   {
0119     total_consumed_ += size;
0120 
0121     Buffer_Iterator next = boost::asio::buffer_sequence_begin(buffers_);
0122     Buffer_Iterator end = boost::asio::buffer_sequence_end(buffers_);
0123 
0124     std::advance(next, next_elem_);
0125     while (next != end && size > 0)
0126     {
0127       Buffer next_buf = Buffer(*next) + next_elem_offset_;
0128       if (size < next_buf.size())
0129       {
0130         next_elem_offset_ += size;
0131         size = 0;
0132       }
0133       else
0134       {
0135         size -= next_buf.size();
0136         next_elem_offset_ = 0;
0137         ++next_elem_;
0138         ++next;
0139       }
0140     }
0141   }
0142 
0143   // Get the total number of bytes consumed from the buffers.
0144   std::size_t total_consumed() const
0145   {
0146     return total_consumed_;
0147   }
0148 
0149 private:
0150   Buffers buffers_;
0151   std::size_t total_size_;
0152   std::size_t total_consumed_;
0153   std::size_t next_elem_;
0154   std::size_t next_elem_offset_;
0155 };
0156 
0157 // Base class of all consuming_buffers specialisations for single buffers.
0158 template <typename Buffer>
0159 class consuming_single_buffer
0160 {
0161 public:
0162   // Construct to represent the entire list of buffers.
0163   template <typename Buffer1>
0164   explicit consuming_single_buffer(const Buffer1& buffer)
0165     : buffer_(buffer),
0166       total_consumed_(0)
0167   {
0168   }
0169 
0170   // Determine if we are at the end of the buffers.
0171   bool empty() const
0172   {
0173     return total_consumed_ >= buffer_.size();
0174   }
0175 
0176   // Get the buffer for a single transfer, with a size.
0177   Buffer prepare(std::size_t max_size)
0178   {
0179     return boost::asio::buffer(buffer_ + total_consumed_, max_size);
0180   }
0181 
0182   // Consume the specified number of bytes from the buffers.
0183   void consume(std::size_t size)
0184   {
0185     total_consumed_ += size;
0186   }
0187 
0188   // Get the total number of bytes consumed from the buffers.
0189   std::size_t total_consumed() const
0190   {
0191     return total_consumed_;
0192   }
0193 
0194 private:
0195   Buffer buffer_;
0196   std::size_t total_consumed_;
0197 };
0198 
0199 template <>
0200 class consuming_buffers<mutable_buffer, mutable_buffer, const mutable_buffer*>
0201   : public consuming_single_buffer<mutable_buffer>
0202 {
0203 public:
0204   explicit consuming_buffers(const mutable_buffer& buffer)
0205     : consuming_single_buffer<mutable_buffer>(buffer)
0206   {
0207   }
0208 };
0209 
0210 template <>
0211 class consuming_buffers<const_buffer, mutable_buffer, const mutable_buffer*>
0212   : public consuming_single_buffer<const_buffer>
0213 {
0214 public:
0215   explicit consuming_buffers(const mutable_buffer& buffer)
0216     : consuming_single_buffer<const_buffer>(buffer)
0217   {
0218   }
0219 };
0220 
0221 template <>
0222 class consuming_buffers<const_buffer, const_buffer, const const_buffer*>
0223   : public consuming_single_buffer<const_buffer>
0224 {
0225 public:
0226   explicit consuming_buffers(const const_buffer& buffer)
0227     : consuming_single_buffer<const_buffer>(buffer)
0228   {
0229   }
0230 };
0231 
0232 template <>
0233 class consuming_buffers<mutable_buffer,
0234     mutable_registered_buffer, const mutable_buffer*>
0235   : public consuming_single_buffer<mutable_registered_buffer>
0236 {
0237 public:
0238   explicit consuming_buffers(const mutable_registered_buffer& buffer)
0239     : consuming_single_buffer<mutable_registered_buffer>(buffer)
0240   {
0241   }
0242 };
0243 
0244 template <>
0245 class consuming_buffers<const_buffer,
0246     mutable_registered_buffer, const mutable_buffer*>
0247   : public consuming_single_buffer<mutable_registered_buffer>
0248 {
0249 public:
0250   explicit consuming_buffers(const mutable_registered_buffer& buffer)
0251     : consuming_single_buffer<mutable_registered_buffer>(buffer)
0252   {
0253   }
0254 };
0255 
0256 template <>
0257 class consuming_buffers<const_buffer,
0258     const_registered_buffer, const const_buffer*>
0259   : public consuming_single_buffer<const_registered_buffer>
0260 {
0261 public:
0262   explicit consuming_buffers(const const_registered_buffer& buffer)
0263     : consuming_single_buffer<const_registered_buffer>(buffer)
0264   {
0265   }
0266 };
0267 
0268 template <typename Buffer, typename Elem>
0269 class consuming_buffers<Buffer, boost::array<Elem, 2>,
0270     typename boost::array<Elem, 2>::const_iterator>
0271 {
0272 public:
0273   // Construct to represent the entire list of buffers.
0274   explicit consuming_buffers(const boost::array<Elem, 2>& buffers)
0275     : buffers_(buffers),
0276       total_consumed_(0)
0277   {
0278   }
0279 
0280   // Determine if we are at the end of the buffers.
0281   bool empty() const
0282   {
0283     return total_consumed_ >=
0284       Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
0285   }
0286 
0287   // Get the buffer for a single transfer, with a size.
0288   boost::array<Buffer, 2> prepare(std::size_t max_size)
0289   {
0290     boost::array<Buffer, 2> result = {{
0291       Buffer(buffers_[0]), Buffer(buffers_[1]) }};
0292     std::size_t buffer0_size = result[0].size();
0293     result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
0294     result[1] = boost::asio::buffer(
0295         result[1] + (total_consumed_ < buffer0_size
0296           ? 0 : total_consumed_ - buffer0_size),
0297         max_size - result[0].size());
0298     return result;
0299   }
0300 
0301   // Consume the specified number of bytes from the buffers.
0302   void consume(std::size_t size)
0303   {
0304     total_consumed_ += size;
0305   }
0306 
0307   // Get the total number of bytes consumed from the buffers.
0308   std::size_t total_consumed() const
0309   {
0310     return total_consumed_;
0311   }
0312 
0313 private:
0314   boost::array<Elem, 2> buffers_;
0315   std::size_t total_consumed_;
0316 };
0317 
0318 template <typename Buffer, typename Elem>
0319 class consuming_buffers<Buffer, std::array<Elem, 2>,
0320     typename std::array<Elem, 2>::const_iterator>
0321 {
0322 public:
0323   // Construct to represent the entire list of buffers.
0324   explicit consuming_buffers(const std::array<Elem, 2>& buffers)
0325     : buffers_(buffers),
0326       total_consumed_(0)
0327   {
0328   }
0329 
0330   // Determine if we are at the end of the buffers.
0331   bool empty() const
0332   {
0333     return total_consumed_ >=
0334       Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
0335   }
0336 
0337   // Get the buffer for a single transfer, with a size.
0338   std::array<Buffer, 2> prepare(std::size_t max_size)
0339   {
0340     std::array<Buffer, 2> result = {{
0341       Buffer(buffers_[0]), Buffer(buffers_[1]) }};
0342     std::size_t buffer0_size = result[0].size();
0343     result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
0344     result[1] = boost::asio::buffer(
0345         result[1] + (total_consumed_ < buffer0_size
0346           ? 0 : total_consumed_ - buffer0_size),
0347         max_size - result[0].size());
0348     return result;
0349   }
0350 
0351   // Consume the specified number of bytes from the buffers.
0352   void consume(std::size_t size)
0353   {
0354     total_consumed_ += size;
0355   }
0356 
0357   // Get the total number of bytes consumed from the buffers.
0358   std::size_t total_consumed() const
0359   {
0360     return total_consumed_;
0361   }
0362 
0363 private:
0364   std::array<Elem, 2> buffers_;
0365   std::size_t total_consumed_;
0366 };
0367 
0368 // Specialisation for null_buffers to ensure that the null_buffers type is
0369 // always passed through to the underlying read or write operation.
0370 template <typename Buffer>
0371 class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>
0372   : public boost::asio::null_buffers
0373 {
0374 public:
0375   consuming_buffers(const null_buffers&)
0376   {
0377     // No-op.
0378   }
0379 
0380   bool empty()
0381   {
0382     return false;
0383   }
0384 
0385   null_buffers prepare(std::size_t)
0386   {
0387     return null_buffers();
0388   }
0389 
0390   void consume(std::size_t)
0391   {
0392     // No-op.
0393   }
0394 
0395   std::size_t total_consumed() const
0396   {
0397     return 0;
0398   }
0399 };
0400 
0401 } // namespace detail
0402 } // namespace asio
0403 } // namespace boost
0404 
0405 #include <boost/asio/detail/pop_options.hpp>
0406 
0407 #endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP