Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:43:03

0001 //
0002 // detail/buffer_sequence_adapter.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_BUFFER_SEQUENCE_ADAPTER_HPP
0012 #define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_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 <boost/asio/buffer.hpp>
0020 #include <boost/asio/detail/array_fwd.hpp>
0021 #include <boost/asio/detail/socket_types.hpp>
0022 #include <boost/asio/registered_buffer.hpp>
0023 
0024 #include <boost/asio/detail/push_options.hpp>
0025 
0026 namespace boost {
0027 namespace asio {
0028 namespace detail {
0029 
0030 class buffer_sequence_adapter_base
0031 {
0032 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0033 public:
0034   // The maximum number of buffers to support in a single operation.
0035   enum { max_buffers = 1 };
0036 
0037 protected:
0038   typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;
0039 
0040   BOOST_ASIO_DECL static void init_native_buffer(
0041       native_buffer_type& buf,
0042       const boost::asio::mutable_buffer& buffer);
0043 
0044   BOOST_ASIO_DECL static void init_native_buffer(
0045       native_buffer_type& buf,
0046       const boost::asio::const_buffer& buffer);
0047 #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0048 public:
0049   // The maximum number of buffers to support in a single operation.
0050   enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
0051 
0052 protected:
0053   typedef WSABUF native_buffer_type;
0054 
0055   static void init_native_buffer(WSABUF& buf,
0056       const boost::asio::mutable_buffer& buffer)
0057   {
0058     buf.buf = static_cast<char*>(buffer.data());
0059     buf.len = static_cast<ULONG>(buffer.size());
0060   }
0061 
0062   static void init_native_buffer(WSABUF& buf,
0063       const boost::asio::const_buffer& buffer)
0064   {
0065     buf.buf = const_cast<char*>(static_cast<const char*>(buffer.data()));
0066     buf.len = static_cast<ULONG>(buffer.size());
0067   }
0068 #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0069 public:
0070   // The maximum number of buffers to support in a single operation.
0071   enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
0072 
0073 protected:
0074   typedef iovec native_buffer_type;
0075 
0076   static void init_iov_base(void*& base, void* addr)
0077   {
0078     base = addr;
0079   }
0080 
0081   template <typename T>
0082   static void init_iov_base(T& base, void* addr)
0083   {
0084     base = static_cast<T>(addr);
0085   }
0086 
0087   static void init_native_buffer(iovec& iov,
0088       const boost::asio::mutable_buffer& buffer)
0089   {
0090     init_iov_base(iov.iov_base, buffer.data());
0091     iov.iov_len = buffer.size();
0092   }
0093 
0094   static void init_native_buffer(iovec& iov,
0095       const boost::asio::const_buffer& buffer)
0096   {
0097     init_iov_base(iov.iov_base, const_cast<void*>(buffer.data()));
0098     iov.iov_len = buffer.size();
0099   }
0100 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0101 };
0102 
0103 // Helper class to translate buffers into the native buffer representation.
0104 template <typename Buffer, typename Buffers>
0105 class buffer_sequence_adapter
0106   : buffer_sequence_adapter_base
0107 {
0108 public:
0109   enum { is_single_buffer = false };
0110   enum { is_registered_buffer = false };
0111 
0112   explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
0113     : count_(0), total_buffer_size_(0)
0114   {
0115     buffer_sequence_adapter::init(
0116         boost::asio::buffer_sequence_begin(buffer_sequence),
0117         boost::asio::buffer_sequence_end(buffer_sequence));
0118   }
0119 
0120   native_buffer_type* buffers()
0121   {
0122     return buffers_;
0123   }
0124 
0125   std::size_t count() const
0126   {
0127     return count_;
0128   }
0129 
0130   std::size_t total_size() const
0131   {
0132     return total_buffer_size_;
0133   }
0134 
0135   registered_buffer_id registered_id() const
0136   {
0137     return registered_buffer_id();
0138   }
0139 
0140   bool all_empty() const
0141   {
0142     return total_buffer_size_ == 0;
0143   }
0144 
0145   static bool all_empty(const Buffers& buffer_sequence)
0146   {
0147     return buffer_sequence_adapter::all_empty(
0148         boost::asio::buffer_sequence_begin(buffer_sequence),
0149         boost::asio::buffer_sequence_end(buffer_sequence));
0150   }
0151 
0152   static void validate(const Buffers& buffer_sequence)
0153   {
0154     buffer_sequence_adapter::validate(
0155         boost::asio::buffer_sequence_begin(buffer_sequence),
0156         boost::asio::buffer_sequence_end(buffer_sequence));
0157   }
0158 
0159   static Buffer first(const Buffers& buffer_sequence)
0160   {
0161     return buffer_sequence_adapter::first(
0162         boost::asio::buffer_sequence_begin(buffer_sequence),
0163         boost::asio::buffer_sequence_end(buffer_sequence));
0164   }
0165 
0166   enum { linearisation_storage_size = 8192 };
0167 
0168   static Buffer linearise(const Buffers& buffer_sequence,
0169       const boost::asio::mutable_buffer& storage)
0170   {
0171     return buffer_sequence_adapter::linearise(
0172         boost::asio::buffer_sequence_begin(buffer_sequence),
0173         boost::asio::buffer_sequence_end(buffer_sequence), storage);
0174   }
0175 
0176 private:
0177   template <typename Iterator>
0178   void init(Iterator begin, Iterator end)
0179   {
0180     Iterator iter = begin;
0181     for (; iter != end && count_ < max_buffers; ++iter, ++count_)
0182     {
0183       Buffer buffer(*iter);
0184       init_native_buffer(buffers_[count_], buffer);
0185       total_buffer_size_ += buffer.size();
0186     }
0187   }
0188 
0189   template <typename Iterator>
0190   static bool all_empty(Iterator begin, Iterator end)
0191   {
0192     Iterator iter = begin;
0193     std::size_t i = 0;
0194     for (; iter != end && i < max_buffers; ++iter, ++i)
0195       if (Buffer(*iter).size() > 0)
0196         return false;
0197     return true;
0198   }
0199 
0200   template <typename Iterator>
0201   static void validate(Iterator begin, Iterator end)
0202   {
0203     Iterator iter = begin;
0204     for (; iter != end; ++iter)
0205     {
0206       Buffer buffer(*iter);
0207       buffer.data();
0208     }
0209   }
0210 
0211   template <typename Iterator>
0212   static Buffer first(Iterator begin, Iterator end)
0213   {
0214     Iterator iter = begin;
0215     for (; iter != end; ++iter)
0216     {
0217       Buffer buffer(*iter);
0218       if (buffer.size() != 0)
0219         return buffer;
0220     }
0221     return Buffer();
0222   }
0223 
0224   template <typename Iterator>
0225   static Buffer linearise(Iterator begin, Iterator end,
0226       const boost::asio::mutable_buffer& storage)
0227   {
0228     boost::asio::mutable_buffer unused_storage = storage;
0229     Iterator iter = begin;
0230     while (iter != end && unused_storage.size() != 0)
0231     {
0232       Buffer buffer(*iter);
0233       ++iter;
0234       if (buffer.size() == 0)
0235         continue;
0236       if (unused_storage.size() == storage.size())
0237       {
0238         if (iter == end)
0239           return buffer;
0240         if (buffer.size() >= unused_storage.size())
0241           return buffer;
0242       }
0243       unused_storage += boost::asio::buffer_copy(unused_storage, buffer);
0244     }
0245     return Buffer(storage.data(), storage.size() - unused_storage.size());
0246   }
0247 
0248   native_buffer_type buffers_[max_buffers];
0249   std::size_t count_;
0250   std::size_t total_buffer_size_;
0251 };
0252 
0253 template <typename Buffer>
0254 class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffer>
0255   : buffer_sequence_adapter_base
0256 {
0257 public:
0258   enum { is_single_buffer = true };
0259   enum { is_registered_buffer = false };
0260 
0261   explicit buffer_sequence_adapter(
0262       const boost::asio::mutable_buffer& buffer_sequence)
0263   {
0264     init_native_buffer(buffer_, Buffer(buffer_sequence));
0265     total_buffer_size_ = buffer_sequence.size();
0266   }
0267 
0268   native_buffer_type* buffers()
0269   {
0270     return &buffer_;
0271   }
0272 
0273   std::size_t count() const
0274   {
0275     return 1;
0276   }
0277 
0278   std::size_t total_size() const
0279   {
0280     return total_buffer_size_;
0281   }
0282 
0283   registered_buffer_id registered_id() const
0284   {
0285     return registered_buffer_id();
0286   }
0287 
0288   bool all_empty() const
0289   {
0290     return total_buffer_size_ == 0;
0291   }
0292 
0293   static bool all_empty(const boost::asio::mutable_buffer& buffer_sequence)
0294   {
0295     return buffer_sequence.size() == 0;
0296   }
0297 
0298   static void validate(const boost::asio::mutable_buffer& buffer_sequence)
0299   {
0300     buffer_sequence.data();
0301   }
0302 
0303   static Buffer first(const boost::asio::mutable_buffer& buffer_sequence)
0304   {
0305     return Buffer(buffer_sequence);
0306   }
0307 
0308   enum { linearisation_storage_size = 1 };
0309 
0310   static Buffer linearise(const boost::asio::mutable_buffer& buffer_sequence,
0311       const Buffer&)
0312   {
0313     return Buffer(buffer_sequence);
0314   }
0315 
0316 private:
0317   native_buffer_type buffer_;
0318   std::size_t total_buffer_size_;
0319 };
0320 
0321 template <typename Buffer>
0322 class buffer_sequence_adapter<Buffer, boost::asio::const_buffer>
0323   : buffer_sequence_adapter_base
0324 {
0325 public:
0326   enum { is_single_buffer = true };
0327   enum { is_registered_buffer = false };
0328 
0329   explicit buffer_sequence_adapter(
0330       const boost::asio::const_buffer& buffer_sequence)
0331   {
0332     init_native_buffer(buffer_, Buffer(buffer_sequence));
0333     total_buffer_size_ = buffer_sequence.size();
0334   }
0335 
0336   native_buffer_type* buffers()
0337   {
0338     return &buffer_;
0339   }
0340 
0341   std::size_t count() const
0342   {
0343     return 1;
0344   }
0345 
0346   std::size_t total_size() const
0347   {
0348     return total_buffer_size_;
0349   }
0350 
0351   registered_buffer_id registered_id() const
0352   {
0353     return registered_buffer_id();
0354   }
0355 
0356   bool all_empty() const
0357   {
0358     return total_buffer_size_ == 0;
0359   }
0360 
0361   static bool all_empty(const boost::asio::const_buffer& buffer_sequence)
0362   {
0363     return buffer_sequence.size() == 0;
0364   }
0365 
0366   static void validate(const boost::asio::const_buffer& buffer_sequence)
0367   {
0368     buffer_sequence.data();
0369   }
0370 
0371   static Buffer first(const boost::asio::const_buffer& buffer_sequence)
0372   {
0373     return Buffer(buffer_sequence);
0374   }
0375 
0376   enum { linearisation_storage_size = 1 };
0377 
0378   static Buffer linearise(const boost::asio::const_buffer& buffer_sequence,
0379       const Buffer&)
0380   {
0381     return Buffer(buffer_sequence);
0382   }
0383 
0384 private:
0385   native_buffer_type buffer_;
0386   std::size_t total_buffer_size_;
0387 };
0388 
0389 template <typename Buffer>
0390 class buffer_sequence_adapter<Buffer, boost::asio::mutable_registered_buffer>
0391   : buffer_sequence_adapter_base
0392 {
0393 public:
0394   enum { is_single_buffer = true };
0395   enum { is_registered_buffer = true };
0396 
0397   explicit buffer_sequence_adapter(
0398       const boost::asio::mutable_registered_buffer& buffer_sequence)
0399   {
0400     init_native_buffer(buffer_, buffer_sequence.buffer());
0401     total_buffer_size_ = buffer_sequence.size();
0402     registered_id_ = buffer_sequence.id();
0403   }
0404 
0405   native_buffer_type* buffers()
0406   {
0407     return &buffer_;
0408   }
0409 
0410   std::size_t count() const
0411   {
0412     return 1;
0413   }
0414 
0415   std::size_t total_size() const
0416   {
0417     return total_buffer_size_;
0418   }
0419 
0420   registered_buffer_id registered_id() const
0421   {
0422     return registered_id_;
0423   }
0424 
0425   bool all_empty() const
0426   {
0427     return total_buffer_size_ == 0;
0428   }
0429 
0430   static bool all_empty(
0431       const boost::asio::mutable_registered_buffer& buffer_sequence)
0432   {
0433     return buffer_sequence.size() == 0;
0434   }
0435 
0436   static void validate(
0437       const boost::asio::mutable_registered_buffer& buffer_sequence)
0438   {
0439     buffer_sequence.data();
0440   }
0441 
0442   static Buffer first(
0443       const boost::asio::mutable_registered_buffer& buffer_sequence)
0444   {
0445     return Buffer(buffer_sequence.buffer());
0446   }
0447 
0448   enum { linearisation_storage_size = 1 };
0449 
0450   static Buffer linearise(
0451       const boost::asio::mutable_registered_buffer& buffer_sequence,
0452       const Buffer&)
0453   {
0454     return Buffer(buffer_sequence.buffer());
0455   }
0456 
0457 private:
0458   native_buffer_type buffer_;
0459   std::size_t total_buffer_size_;
0460   registered_buffer_id registered_id_;
0461 };
0462 
0463 template <typename Buffer>
0464 class buffer_sequence_adapter<Buffer, boost::asio::const_registered_buffer>
0465   : buffer_sequence_adapter_base
0466 {
0467 public:
0468   enum { is_single_buffer = true };
0469   enum { is_registered_buffer = true };
0470 
0471   explicit buffer_sequence_adapter(
0472       const boost::asio::const_registered_buffer& buffer_sequence)
0473   {
0474     init_native_buffer(buffer_, buffer_sequence.buffer());
0475     total_buffer_size_ = buffer_sequence.size();
0476     registered_id_ = buffer_sequence.id();
0477   }
0478 
0479   native_buffer_type* buffers()
0480   {
0481     return &buffer_;
0482   }
0483 
0484   std::size_t count() const
0485   {
0486     return 1;
0487   }
0488 
0489   std::size_t total_size() const
0490   {
0491     return total_buffer_size_;
0492   }
0493 
0494   registered_buffer_id registered_id() const
0495   {
0496     return registered_id_;
0497   }
0498 
0499   bool all_empty() const
0500   {
0501     return total_buffer_size_ == 0;
0502   }
0503 
0504   static bool all_empty(
0505       const boost::asio::const_registered_buffer& buffer_sequence)
0506   {
0507     return buffer_sequence.size() == 0;
0508   }
0509 
0510   static void validate(
0511       const boost::asio::const_registered_buffer& buffer_sequence)
0512   {
0513     buffer_sequence.data();
0514   }
0515 
0516   static Buffer first(
0517       const boost::asio::const_registered_buffer& buffer_sequence)
0518   {
0519     return Buffer(buffer_sequence.buffer());
0520   }
0521 
0522   enum { linearisation_storage_size = 1 };
0523 
0524   static Buffer linearise(
0525       const boost::asio::const_registered_buffer& buffer_sequence,
0526       const Buffer&)
0527   {
0528     return Buffer(buffer_sequence.buffer());
0529   }
0530 
0531 private:
0532   native_buffer_type buffer_;
0533   std::size_t total_buffer_size_;
0534   registered_buffer_id registered_id_;
0535 };
0536 
0537 template <typename Buffer, typename Elem>
0538 class buffer_sequence_adapter<Buffer, boost::array<Elem, 2>>
0539   : buffer_sequence_adapter_base
0540 {
0541 public:
0542   enum { is_single_buffer = false };
0543   enum { is_registered_buffer = false };
0544 
0545   explicit buffer_sequence_adapter(
0546       const boost::array<Elem, 2>& buffer_sequence)
0547   {
0548     init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
0549     init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
0550     total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
0551   }
0552 
0553   native_buffer_type* buffers()
0554   {
0555     return buffers_;
0556   }
0557 
0558   std::size_t count() const
0559   {
0560     return 2;
0561   }
0562 
0563   std::size_t total_size() const
0564   {
0565     return total_buffer_size_;
0566   }
0567 
0568   registered_buffer_id registered_id() const
0569   {
0570     return registered_buffer_id();
0571   }
0572 
0573   bool all_empty() const
0574   {
0575     return total_buffer_size_ == 0;
0576   }
0577 
0578   static bool all_empty(const boost::array<Elem, 2>& buffer_sequence)
0579   {
0580     return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
0581   }
0582 
0583   static void validate(const boost::array<Elem, 2>& buffer_sequence)
0584   {
0585     buffer_sequence[0].data();
0586     buffer_sequence[1].data();
0587   }
0588 
0589   static Buffer first(const boost::array<Elem, 2>& buffer_sequence)
0590   {
0591     return Buffer(buffer_sequence[0].size() != 0
0592         ? buffer_sequence[0] : buffer_sequence[1]);
0593   }
0594 
0595   enum { linearisation_storage_size = 8192 };
0596 
0597   static Buffer linearise(const boost::array<Elem, 2>& buffer_sequence,
0598       const boost::asio::mutable_buffer& storage)
0599   {
0600     if (buffer_sequence[0].size() == 0)
0601       return Buffer(buffer_sequence[1]);
0602     if (buffer_sequence[1].size() == 0)
0603       return Buffer(buffer_sequence[0]);
0604     return Buffer(storage.data(),
0605         boost::asio::buffer_copy(storage, buffer_sequence));
0606   }
0607 
0608 private:
0609   native_buffer_type buffers_[2];
0610   std::size_t total_buffer_size_;
0611 };
0612 
0613 template <typename Buffer, typename Elem>
0614 class buffer_sequence_adapter<Buffer, std::array<Elem, 2>>
0615   : buffer_sequence_adapter_base
0616 {
0617 public:
0618   enum { is_single_buffer = false };
0619   enum { is_registered_buffer = false };
0620 
0621   explicit buffer_sequence_adapter(
0622       const std::array<Elem, 2>& buffer_sequence)
0623   {
0624     init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
0625     init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
0626     total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
0627   }
0628 
0629   native_buffer_type* buffers()
0630   {
0631     return buffers_;
0632   }
0633 
0634   std::size_t count() const
0635   {
0636     return 2;
0637   }
0638 
0639   std::size_t total_size() const
0640   {
0641     return total_buffer_size_;
0642   }
0643 
0644   registered_buffer_id registered_id() const
0645   {
0646     return registered_buffer_id();
0647   }
0648 
0649   bool all_empty() const
0650   {
0651     return total_buffer_size_ == 0;
0652   }
0653 
0654   static bool all_empty(const std::array<Elem, 2>& buffer_sequence)
0655   {
0656     return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
0657   }
0658 
0659   static void validate(const std::array<Elem, 2>& buffer_sequence)
0660   {
0661     buffer_sequence[0].data();
0662     buffer_sequence[1].data();
0663   }
0664 
0665   static Buffer first(const std::array<Elem, 2>& buffer_sequence)
0666   {
0667     return Buffer(buffer_sequence[0].size() != 0
0668         ? buffer_sequence[0] : buffer_sequence[1]);
0669   }
0670 
0671   enum { linearisation_storage_size = 8192 };
0672 
0673   static Buffer linearise(const std::array<Elem, 2>& buffer_sequence,
0674       const boost::asio::mutable_buffer& storage)
0675   {
0676     if (buffer_sequence[0].size() == 0)
0677       return Buffer(buffer_sequence[1]);
0678     if (buffer_sequence[1].size() == 0)
0679       return Buffer(buffer_sequence[0]);
0680     return Buffer(storage.data(),
0681         boost::asio::buffer_copy(storage, buffer_sequence));
0682   }
0683 
0684 private:
0685   native_buffer_type buffers_[2];
0686   std::size_t total_buffer_size_;
0687 };
0688 
0689 } // namespace detail
0690 } // namespace asio
0691 } // namespace boost
0692 
0693 #include <boost/asio/detail/pop_options.hpp>
0694 
0695 #if defined(BOOST_ASIO_HEADER_ONLY)
0696 # include <boost/asio/detail/impl/buffer_sequence_adapter.ipp>
0697 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0698 
0699 #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP