Clementine
buffer_sequence_adapter.hpp
1 //
2 // detail/buffer_sequence_adapter.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
12 #define ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 #include "asio/buffer.hpp"
20 #include "asio/detail/array_fwd.hpp"
21 #include "asio/detail/socket_types.hpp"
22 
23 #include "asio/detail/push_options.hpp"
24 
25 namespace asio {
26 namespace detail {
27 
29 {
30 #if defined(ASIO_WINDOWS_RUNTIME)
31 public:
32  // The maximum number of buffers to support in a single operation.
33  enum { max_buffers = 1 };
34 
35 protected:
36  typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;
37 
38  ASIO_DECL static void init_native_buffer(
39  native_buffer_type& buf,
40  const asio::mutable_buffer& buffer);
41 
42  ASIO_DECL static void init_native_buffer(
43  native_buffer_type& buf,
44  const asio::const_buffer& buffer);
45 #elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)
46 public:
47  // The maximum number of buffers to support in a single operation.
48  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
49 
50 protected:
51  typedef WSABUF native_buffer_type;
52 
53  static void init_native_buffer(WSABUF& buf,
54  const asio::mutable_buffer& buffer)
55  {
56  buf.buf = static_cast<char*>(buffer.data());
57  buf.len = static_cast<ULONG>(buffer.size());
58  }
59 
60  static void init_native_buffer(WSABUF& buf,
61  const asio::const_buffer& buffer)
62  {
63  buf.buf = const_cast<char*>(static_cast<const char*>(buffer.data()));
64  buf.len = static_cast<ULONG>(buffer.size());
65  }
66 #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
67 public:
68  // The maximum number of buffers to support in a single operation.
69  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
70 
71 protected:
72  typedef iovec native_buffer_type;
73 
74  static void init_iov_base(void*& base, void* addr)
75  {
76  base = addr;
77  }
78 
79  template <typename T>
80  static void init_iov_base(T& base, void* addr)
81  {
82  base = static_cast<T>(addr);
83  }
84 
85  static void init_native_buffer(iovec& iov,
86  const asio::mutable_buffer& buffer)
87  {
88  init_iov_base(iov.iov_base, buffer.data());
89  iov.iov_len = buffer.size();
90  }
91 
92  static void init_native_buffer(iovec& iov,
93  const asio::const_buffer& buffer)
94  {
95  init_iov_base(iov.iov_base, const_cast<void*>(buffer.data()));
96  iov.iov_len = buffer.size();
97  }
98 #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
99 };
100 
101 // Helper class to translate buffers into the native buffer representation.
102 template <typename Buffer, typename Buffers>
105 {
106 public:
107  enum { is_single_buffer = false };
108 
109  explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
110  : count_(0), total_buffer_size_(0)
111  {
112  buffer_sequence_adapter::init(
113  asio::buffer_sequence_begin(buffer_sequence),
114  asio::buffer_sequence_end(buffer_sequence));
115  }
116 
117  native_buffer_type* buffers()
118  {
119  return buffers_;
120  }
121 
122  std::size_t count() const
123  {
124  return count_;
125  }
126 
127  std::size_t total_size() const
128  {
129  return total_buffer_size_;
130  }
131 
132  bool all_empty() const
133  {
134  return total_buffer_size_ == 0;
135  }
136 
137  static bool all_empty(const Buffers& buffer_sequence)
138  {
139  return buffer_sequence_adapter::all_empty(
140  asio::buffer_sequence_begin(buffer_sequence),
141  asio::buffer_sequence_end(buffer_sequence));
142  }
143 
144  static void validate(const Buffers& buffer_sequence)
145  {
146  buffer_sequence_adapter::validate(
147  asio::buffer_sequence_begin(buffer_sequence),
148  asio::buffer_sequence_end(buffer_sequence));
149  }
150 
151  static Buffer first(const Buffers& buffer_sequence)
152  {
153  return buffer_sequence_adapter::first(
154  asio::buffer_sequence_begin(buffer_sequence),
155  asio::buffer_sequence_end(buffer_sequence));
156  }
157 
158  enum { linearisation_storage_size = 8192 };
159 
160  static Buffer linearise(const Buffers& buffer_sequence,
161  const asio::mutable_buffer& storage)
162  {
163  return buffer_sequence_adapter::linearise(
164  asio::buffer_sequence_begin(buffer_sequence),
165  asio::buffer_sequence_end(buffer_sequence), storage);
166  }
167 
168 private:
169  template <typename Iterator>
170  void init(Iterator begin, Iterator end)
171  {
172  Iterator iter = begin;
173  for (; iter != end && count_ < max_buffers; ++iter, ++count_)
174  {
175  Buffer buffer(*iter);
176  init_native_buffer(buffers_[count_], buffer);
177  total_buffer_size_ += buffer.size();
178  }
179  }
180 
181  template <typename Iterator>
182  static bool all_empty(Iterator begin, Iterator end)
183  {
184  Iterator iter = begin;
185  std::size_t i = 0;
186  for (; iter != end && i < max_buffers; ++iter, ++i)
187  if (Buffer(*iter).size() > 0)
188  return false;
189  return true;
190  }
191 
192  template <typename Iterator>
193  static void validate(Iterator begin, Iterator end)
194  {
195  Iterator iter = begin;
196  for (; iter != end; ++iter)
197  {
198  Buffer buffer(*iter);
199  buffer.data();
200  }
201  }
202 
203  template <typename Iterator>
204  static Buffer first(Iterator begin, Iterator end)
205  {
206  Iterator iter = begin;
207  for (; iter != end; ++iter)
208  {
209  Buffer buffer(*iter);
210  if (buffer.size() != 0)
211  return buffer;
212  }
213  return Buffer();
214  }
215 
216  template <typename Iterator>
217  static Buffer linearise(Iterator begin, Iterator end,
218  const asio::mutable_buffer& storage)
219  {
220  asio::mutable_buffer unused_storage = storage;
221  Iterator iter = begin;
222  while (iter != end && unused_storage.size() != 0)
223  {
224  Buffer buffer(*iter);
225  ++iter;
226  if (buffer.size() == 0)
227  continue;
228  if (unused_storage.size() == storage.size())
229  {
230  if (iter == end)
231  return buffer;
232  if (buffer.size() >= unused_storage.size())
233  return buffer;
234  }
235  unused_storage += asio::buffer_copy(unused_storage, buffer);
236  }
237  return Buffer(storage.data(), storage.size() - unused_storage.size());
238  }
239 
240  native_buffer_type buffers_[max_buffers];
241  std::size_t count_;
242  std::size_t total_buffer_size_;
243 };
244 
245 template <typename Buffer>
248 {
249 public:
250  enum { is_single_buffer = true };
251 
252  explicit buffer_sequence_adapter(
254  {
255  init_native_buffer(buffer_, Buffer(buffer_sequence));
256  total_buffer_size_ = buffer_sequence.size();
257  }
258 
259  native_buffer_type* buffers()
260  {
261  return &buffer_;
262  }
263 
264  std::size_t count() const
265  {
266  return 1;
267  }
268 
269  std::size_t total_size() const
270  {
271  return total_buffer_size_;
272  }
273 
274  bool all_empty() const
275  {
276  return total_buffer_size_ == 0;
277  }
278 
279  static bool all_empty(const asio::mutable_buffer& buffer_sequence)
280  {
281  return buffer_sequence.size() == 0;
282  }
283 
284  static void validate(const asio::mutable_buffer& buffer_sequence)
285  {
286  buffer_sequence.data();
287  }
288 
289  static Buffer first(const asio::mutable_buffer& buffer_sequence)
290  {
291  return Buffer(buffer_sequence);
292  }
293 
294  enum { linearisation_storage_size = 1 };
295 
296  static Buffer linearise(const asio::mutable_buffer& buffer_sequence,
297  const Buffer&)
298  {
299  return Buffer(buffer_sequence);
300  }
301 
302 private:
303  native_buffer_type buffer_;
304  std::size_t total_buffer_size_;
305 };
306 
307 template <typename Buffer>
310 {
311 public:
312  enum { is_single_buffer = true };
313 
314  explicit buffer_sequence_adapter(
316  {
317  init_native_buffer(buffer_, Buffer(buffer_sequence));
318  total_buffer_size_ = buffer_sequence.size();
319  }
320 
321  native_buffer_type* buffers()
322  {
323  return &buffer_;
324  }
325 
326  std::size_t count() const
327  {
328  return 1;
329  }
330 
331  std::size_t total_size() const
332  {
333  return total_buffer_size_;
334  }
335 
336  bool all_empty() const
337  {
338  return total_buffer_size_ == 0;
339  }
340 
341  static bool all_empty(const asio::const_buffer& buffer_sequence)
342  {
343  return buffer_sequence.size() == 0;
344  }
345 
346  static void validate(const asio::const_buffer& buffer_sequence)
347  {
348  buffer_sequence.data();
349  }
350 
351  static Buffer first(const asio::const_buffer& buffer_sequence)
352  {
353  return Buffer(buffer_sequence);
354  }
355 
356  enum { linearisation_storage_size = 1 };
357 
358  static Buffer linearise(const asio::const_buffer& buffer_sequence,
359  const Buffer&)
360  {
361  return Buffer(buffer_sequence);
362  }
363 
364 private:
365  native_buffer_type buffer_;
366  std::size_t total_buffer_size_;
367 };
368 
369 #if !defined(ASIO_NO_DEPRECATED)
370 
371 template <typename Buffer>
374 {
375 public:
376  enum { is_single_buffer = true };
377 
378  explicit buffer_sequence_adapter(
380  {
381  init_native_buffer(buffer_, Buffer(buffer_sequence));
382  total_buffer_size_ = buffer_sequence.size();
383  }
384 
385  native_buffer_type* buffers()
386  {
387  return &buffer_;
388  }
389 
390  std::size_t count() const
391  {
392  return 1;
393  }
394 
395  std::size_t total_size() const
396  {
397  return total_buffer_size_;
398  }
399 
400  bool all_empty() const
401  {
402  return total_buffer_size_ == 0;
403  }
404 
405  static bool all_empty(const asio::mutable_buffers_1& buffer_sequence)
406  {
407  return buffer_sequence.size() == 0;
408  }
409 
410  static void validate(const asio::mutable_buffers_1& buffer_sequence)
411  {
412  buffer_sequence.data();
413  }
414 
415  static Buffer first(const asio::mutable_buffers_1& buffer_sequence)
416  {
417  return Buffer(buffer_sequence);
418  }
419 
420  enum { linearisation_storage_size = 1 };
421 
422  static Buffer linearise(const asio::mutable_buffers_1& buffer_sequence,
423  const Buffer&)
424  {
425  return Buffer(buffer_sequence);
426  }
427 
428 private:
429  native_buffer_type buffer_;
430  std::size_t total_buffer_size_;
431 };
432 
433 template <typename Buffer>
436 {
437 public:
438  enum { is_single_buffer = true };
439 
440  explicit buffer_sequence_adapter(
442  {
443  init_native_buffer(buffer_, Buffer(buffer_sequence));
444  total_buffer_size_ = buffer_sequence.size();
445  }
446 
447  native_buffer_type* buffers()
448  {
449  return &buffer_;
450  }
451 
452  std::size_t count() const
453  {
454  return 1;
455  }
456 
457  std::size_t total_size() const
458  {
459  return total_buffer_size_;
460  }
461 
462  bool all_empty() const
463  {
464  return total_buffer_size_ == 0;
465  }
466 
467  static bool all_empty(const asio::const_buffers_1& buffer_sequence)
468  {
469  return buffer_sequence.size() == 0;
470  }
471 
472  static void validate(const asio::const_buffers_1& buffer_sequence)
473  {
474  buffer_sequence.data();
475  }
476 
477  static Buffer first(const asio::const_buffers_1& buffer_sequence)
478  {
479  return Buffer(buffer_sequence);
480  }
481 
482  enum { linearisation_storage_size = 1 };
483 
484  static Buffer linearise(const asio::const_buffers_1& buffer_sequence,
485  const Buffer&)
486  {
487  return Buffer(buffer_sequence);
488  }
489 
490 private:
491  native_buffer_type buffer_;
492  std::size_t total_buffer_size_;
493 };
494 
495 #endif // !defined(ASIO_NO_DEPRECATED)
496 
497 template <typename Buffer, typename Elem>
498 class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
500 {
501 public:
502  enum { is_single_buffer = false };
503 
504  explicit buffer_sequence_adapter(
506  {
507  init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
508  init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
509  total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
510  }
511 
512  native_buffer_type* buffers()
513  {
514  return buffers_;
515  }
516 
517  std::size_t count() const
518  {
519  return 2;
520  }
521 
522  std::size_t total_size() const
523  {
524  return total_buffer_size_;
525  }
526 
527  bool all_empty() const
528  {
529  return total_buffer_size_ == 0;
530  }
531 
532  static bool all_empty(const boost::array<Elem, 2>& buffer_sequence)
533  {
534  return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
535  }
536 
537  static void validate(const boost::array<Elem, 2>& buffer_sequence)
538  {
539  buffer_sequence[0].data();
540  buffer_sequence[1].data();
541  }
542 
543  static Buffer first(const boost::array<Elem, 2>& buffer_sequence)
544  {
545  return Buffer(buffer_sequence[0].size() != 0
546  ? buffer_sequence[0] : buffer_sequence[1]);
547  }
548 
549  enum { linearisation_storage_size = 8192 };
550 
551  static Buffer linearise(const boost::array<Elem, 2>& buffer_sequence,
552  const asio::mutable_buffer& storage)
553  {
554  if (buffer_sequence[0].size() == 0)
555  return Buffer(buffer_sequence[1]);
556  if (buffer_sequence[1].size() == 0)
557  return Buffer(buffer_sequence[0]);
558  return Buffer(storage.data(),
559  asio::buffer_copy(storage, buffer_sequence));
560  }
561 
562 private:
563  native_buffer_type buffers_[2];
564  std::size_t total_buffer_size_;
565 };
566 
567 #if defined(ASIO_HAS_STD_ARRAY)
568 
569 template <typename Buffer, typename Elem>
570 class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
572 {
573 public:
574  enum { is_single_buffer = false };
575 
576  explicit buffer_sequence_adapter(
577  const std::array<Elem, 2>& buffer_sequence)
578  {
579  init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
580  init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
581  total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
582  }
583 
584  native_buffer_type* buffers()
585  {
586  return buffers_;
587  }
588 
589  std::size_t count() const
590  {
591  return 2;
592  }
593 
594  std::size_t total_size() const
595  {
596  return total_buffer_size_;
597  }
598 
599  bool all_empty() const
600  {
601  return total_buffer_size_ == 0;
602  }
603 
604  static bool all_empty(const std::array<Elem, 2>& buffer_sequence)
605  {
606  return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
607  }
608 
609  static void validate(const std::array<Elem, 2>& buffer_sequence)
610  {
611  buffer_sequence[0].data();
612  buffer_sequence[1].data();
613  }
614 
615  static Buffer first(const std::array<Elem, 2>& buffer_sequence)
616  {
617  return Buffer(buffer_sequence[0].size() != 0
618  ? buffer_sequence[0] : buffer_sequence[1]);
619  }
620 
621  enum { linearisation_storage_size = 8192 };
622 
623  static Buffer linearise(const std::array<Elem, 2>& buffer_sequence,
624  const asio::mutable_buffer& storage)
625  {
626  if (buffer_sequence[0].size() == 0)
627  return Buffer(buffer_sequence[1]);
628  if (buffer_sequence[1].size() == 0)
629  return Buffer(buffer_sequence[0]);
630  return Buffer(storage.data(),
631  asio::buffer_copy(storage, buffer_sequence));
632  }
633 
634 private:
635  native_buffer_type buffers_[2];
636  std::size_t total_buffer_size_;
637 };
638 
639 #endif // defined(ASIO_HAS_STD_ARRAY)
640 
641 } // namespace detail
642 } // namespace asio
643 
644 #include "asio/detail/pop_options.hpp"
645 
646 #if defined(ASIO_HEADER_ONLY)
647 # include "asio/detail/impl/buffer_sequence_adapter.ipp"
648 #endif // defined(ASIO_HEADER_ONLY)
649 
650 #endif // ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
const void * data() const ASIO_NOEXCEPT
Get a pointer to the beginning of the memory range.
Definition: buffer.hpp:269
Definition: array_fwd.hpp:20
Holds a buffer that cannot be modified.
Definition: buffer.hpp:226
Definition: buffer.cpp:590
(Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so that it meets the requiremen...
Definition: buffer.hpp:306
std::size_t size() const ASIO_NOEXCEPT
Get the size of the memory range.
Definition: buffer.hpp:279
Definition: chrono.h:284
ASIO_MUTABLE_BUFFER buffer(const mutable_buffer &b) ASIO_NOEXCEPT
Create a new modifiable buffer from an existing buffer.
Definition: buffer.hpp:909
Definition: buffer_sequence_adapter.hpp:103
Holds a buffer that can be modified.
Definition: buffer.hpp:92
std::size_t buffer_copy(const MutableBufferSequence &target, const ConstBufferSequence &source) ASIO_NOEXCEPT
Copies bytes from a source buffer sequence to a target buffer sequence.
Definition: buffer.hpp:2363
const mutable_buffer * buffer_sequence_begin(const MutableBuffer &b, typename enable_if< is_convertible< const MutableBuffer *, const mutable_buffer *>::value >::type *=0) ASIO_NOEXCEPT
Get an iterator to the first element in a buffer sequence.
Definition: buffer.hpp:388
void * data() const ASIO_NOEXCEPT
Get a pointer to the beginning of the memory range.
Definition: buffer.hpp:125
Definition: buffer_sequence_adapter.hpp:28
std::size_t size() const ASIO_NOEXCEPT
Get the size of the memory range.
Definition: buffer.hpp:135
const mutable_buffer * buffer_sequence_end(const MutableBuffer &b, typename enable_if< is_convertible< const MutableBuffer *, const mutable_buffer *>::value >::type *=0) ASIO_NOEXCEPT
Get an iterator to one past the end element in a buffer sequence.
Definition: buffer.hpp:465
Definition: any_io_executor.hpp:28
(Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that it meets the requirements...
Definition: buffer.hpp:162
Definition: array_fwd.hpp:23