File indexing completed on 2025-12-16 09:43:03
0001
0002
0003
0004
0005
0006
0007
0008
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
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
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
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
0069 public:
0070
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
0101 };
0102
0103
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 }
0690 }
0691 }
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
0698
0699 #endif