Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // detail/consuming_buffers.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_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<BOOST_ASIO_MUTABLE_BUFFER>
0202 {
0203 public:
0204   explicit consuming_buffers(const mutable_buffer& buffer)
0205     : consuming_single_buffer<BOOST_ASIO_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<BOOST_ASIO_CONST_BUFFER>
0213 {
0214 public:
0215   explicit consuming_buffers(const mutable_buffer& buffer)
0216     : consuming_single_buffer<BOOST_ASIO_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<BOOST_ASIO_CONST_BUFFER>
0224 {
0225 public:
0226   explicit consuming_buffers(const const_buffer& buffer)
0227     : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
0228   {
0229   }
0230 };
0231 
0232 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0233 
0234 template <>
0235 class consuming_buffers<mutable_buffer,
0236     mutable_buffers_1, const mutable_buffer*>
0237   : public consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>
0238 {
0239 public:
0240   explicit consuming_buffers(const mutable_buffers_1& buffer)
0241     : consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>(buffer)
0242   {
0243   }
0244 };
0245 
0246 template <>
0247 class consuming_buffers<const_buffer, mutable_buffers_1, const mutable_buffer*>
0248   : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
0249 {
0250 public:
0251   explicit consuming_buffers(const mutable_buffers_1& buffer)
0252     : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
0253   {
0254   }
0255 };
0256 
0257 template <>
0258 class consuming_buffers<const_buffer, const_buffers_1, const const_buffer*>
0259   : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
0260 {
0261 public:
0262   explicit consuming_buffers(const const_buffers_1& buffer)
0263     : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
0264   {
0265   }
0266 };
0267 
0268 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0269 
0270 template <>
0271 class consuming_buffers<mutable_buffer,
0272     mutable_registered_buffer, const mutable_buffer*>
0273   : public consuming_single_buffer<mutable_registered_buffer>
0274 {
0275 public:
0276   explicit consuming_buffers(const mutable_registered_buffer& buffer)
0277     : consuming_single_buffer<mutable_registered_buffer>(buffer)
0278   {
0279   }
0280 };
0281 
0282 template <>
0283 class consuming_buffers<const_buffer,
0284     mutable_registered_buffer, const mutable_buffer*>
0285   : public consuming_single_buffer<mutable_registered_buffer>
0286 {
0287 public:
0288   explicit consuming_buffers(const mutable_registered_buffer& buffer)
0289     : consuming_single_buffer<mutable_registered_buffer>(buffer)
0290   {
0291   }
0292 };
0293 
0294 template <>
0295 class consuming_buffers<const_buffer,
0296     const_registered_buffer, const const_buffer*>
0297   : public consuming_single_buffer<const_registered_buffer>
0298 {
0299 public:
0300   explicit consuming_buffers(const const_registered_buffer& buffer)
0301     : consuming_single_buffer<const_registered_buffer>(buffer)
0302   {
0303   }
0304 };
0305 
0306 template <typename Buffer, typename Elem>
0307 class consuming_buffers<Buffer, boost::array<Elem, 2>,
0308     typename boost::array<Elem, 2>::const_iterator>
0309 {
0310 public:
0311   // Construct to represent the entire list of buffers.
0312   explicit consuming_buffers(const boost::array<Elem, 2>& buffers)
0313     : buffers_(buffers),
0314       total_consumed_(0)
0315   {
0316   }
0317 
0318   // Determine if we are at the end of the buffers.
0319   bool empty() const
0320   {
0321     return total_consumed_ >=
0322       Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
0323   }
0324 
0325   // Get the buffer for a single transfer, with a size.
0326   boost::array<Buffer, 2> prepare(std::size_t max_size)
0327   {
0328     boost::array<Buffer, 2> result = {{
0329       Buffer(buffers_[0]), Buffer(buffers_[1]) }};
0330     std::size_t buffer0_size = result[0].size();
0331     result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
0332     result[1] = boost::asio::buffer(
0333         result[1] + (total_consumed_ < buffer0_size
0334           ? 0 : total_consumed_ - buffer0_size),
0335         max_size - result[0].size());
0336     return result;
0337   }
0338 
0339   // Consume the specified number of bytes from the buffers.
0340   void consume(std::size_t size)
0341   {
0342     total_consumed_ += size;
0343   }
0344 
0345   // Get the total number of bytes consumed from the buffers.
0346   std::size_t total_consumed() const
0347   {
0348     return total_consumed_;
0349   }
0350 
0351 private:
0352   boost::array<Elem, 2> buffers_;
0353   std::size_t total_consumed_;
0354 };
0355 
0356 template <typename Buffer, typename Elem>
0357 class consuming_buffers<Buffer, std::array<Elem, 2>,
0358     typename std::array<Elem, 2>::const_iterator>
0359 {
0360 public:
0361   // Construct to represent the entire list of buffers.
0362   explicit consuming_buffers(const std::array<Elem, 2>& buffers)
0363     : buffers_(buffers),
0364       total_consumed_(0)
0365   {
0366   }
0367 
0368   // Determine if we are at the end of the buffers.
0369   bool empty() const
0370   {
0371     return total_consumed_ >=
0372       Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
0373   }
0374 
0375   // Get the buffer for a single transfer, with a size.
0376   std::array<Buffer, 2> prepare(std::size_t max_size)
0377   {
0378     std::array<Buffer, 2> result = {{
0379       Buffer(buffers_[0]), Buffer(buffers_[1]) }};
0380     std::size_t buffer0_size = result[0].size();
0381     result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
0382     result[1] = boost::asio::buffer(
0383         result[1] + (total_consumed_ < buffer0_size
0384           ? 0 : total_consumed_ - buffer0_size),
0385         max_size - result[0].size());
0386     return result;
0387   }
0388 
0389   // Consume the specified number of bytes from the buffers.
0390   void consume(std::size_t size)
0391   {
0392     total_consumed_ += size;
0393   }
0394 
0395   // Get the total number of bytes consumed from the buffers.
0396   std::size_t total_consumed() const
0397   {
0398     return total_consumed_;
0399   }
0400 
0401 private:
0402   std::array<Elem, 2> buffers_;
0403   std::size_t total_consumed_;
0404 };
0405 
0406 // Specialisation for null_buffers to ensure that the null_buffers type is
0407 // always passed through to the underlying read or write operation.
0408 template <typename Buffer>
0409 class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>
0410   : public boost::asio::null_buffers
0411 {
0412 public:
0413   consuming_buffers(const null_buffers&)
0414   {
0415     // No-op.
0416   }
0417 
0418   bool empty()
0419   {
0420     return false;
0421   }
0422 
0423   null_buffers prepare(std::size_t)
0424   {
0425     return null_buffers();
0426   }
0427 
0428   void consume(std::size_t)
0429   {
0430     // No-op.
0431   }
0432 
0433   std::size_t total_consumed() const
0434   {
0435     return 0;
0436   }
0437 };
0438 
0439 } // namespace detail
0440 } // namespace asio
0441 } // namespace boost
0442 
0443 #include <boost/asio/detail/pop_options.hpp>
0444 
0445 #endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP