buffer_sequence_adapter.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. //
  2. // detail/buffer_sequence_adapter.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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. #ifndef BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
  11. #define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/buffer.hpp>
  17. #include <boost/asio/detail/array_fwd.hpp>
  18. #include <boost/asio/detail/socket_types.hpp>
  19. #include <boost/asio/detail/push_options.hpp>
  20. namespace boost {
  21. namespace asio {
  22. namespace detail {
  23. class buffer_sequence_adapter_base
  24. {
  25. #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
  26. public:
  27. // The maximum number of buffers to support in a single operation.
  28. enum { max_buffers = 1 };
  29. protected:
  30. typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;
  31. BOOST_ASIO_DECL static void init_native_buffer(
  32. native_buffer_type& buf,
  33. const boost::asio::mutable_buffer& buffer);
  34. BOOST_ASIO_DECL static void init_native_buffer(
  35. native_buffer_type& buf,
  36. const boost::asio::const_buffer& buffer);
  37. #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  38. public:
  39. // The maximum number of buffers to support in a single operation.
  40. enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
  41. protected:
  42. typedef WSABUF native_buffer_type;
  43. static void init_native_buffer(WSABUF& buf,
  44. const boost::asio::mutable_buffer& buffer)
  45. {
  46. buf.buf = static_cast<char*>(buffer.data());
  47. buf.len = static_cast<ULONG>(buffer.size());
  48. }
  49. static void init_native_buffer(WSABUF& buf,
  50. const boost::asio::const_buffer& buffer)
  51. {
  52. buf.buf = const_cast<char*>(static_cast<const char*>(buffer.data()));
  53. buf.len = static_cast<ULONG>(buffer.size());
  54. }
  55. #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  56. public:
  57. // The maximum number of buffers to support in a single operation.
  58. enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
  59. protected:
  60. typedef iovec native_buffer_type;
  61. static void init_iov_base(void*& base, void* addr)
  62. {
  63. base = addr;
  64. }
  65. template <typename T>
  66. static void init_iov_base(T& base, void* addr)
  67. {
  68. base = static_cast<T>(addr);
  69. }
  70. static void init_native_buffer(iovec& iov,
  71. const boost::asio::mutable_buffer& buffer)
  72. {
  73. init_iov_base(iov.iov_base, buffer.data());
  74. iov.iov_len = buffer.size();
  75. }
  76. static void init_native_buffer(iovec& iov,
  77. const boost::asio::const_buffer& buffer)
  78. {
  79. init_iov_base(iov.iov_base, const_cast<void*>(buffer.data()));
  80. iov.iov_len = buffer.size();
  81. }
  82. #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  83. };
  84. // Helper class to translate buffers into the native buffer representation.
  85. template <typename Buffer, typename Buffers>
  86. class buffer_sequence_adapter
  87. : buffer_sequence_adapter_base
  88. {
  89. public:
  90. explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
  91. : count_(0), total_buffer_size_(0)
  92. {
  93. buffer_sequence_adapter::init(
  94. boost::asio::buffer_sequence_begin(buffer_sequence),
  95. boost::asio::buffer_sequence_end(buffer_sequence));
  96. }
  97. native_buffer_type* buffers()
  98. {
  99. return buffers_;
  100. }
  101. std::size_t count() const
  102. {
  103. return count_;
  104. }
  105. std::size_t total_size() const
  106. {
  107. return total_buffer_size_;
  108. }
  109. bool all_empty() const
  110. {
  111. return total_buffer_size_ == 0;
  112. }
  113. static bool all_empty(const Buffers& buffer_sequence)
  114. {
  115. return buffer_sequence_adapter::all_empty(
  116. boost::asio::buffer_sequence_begin(buffer_sequence),
  117. boost::asio::buffer_sequence_end(buffer_sequence));
  118. }
  119. static void validate(const Buffers& buffer_sequence)
  120. {
  121. buffer_sequence_adapter::validate(
  122. boost::asio::buffer_sequence_begin(buffer_sequence),
  123. boost::asio::buffer_sequence_end(buffer_sequence));
  124. }
  125. static Buffer first(const Buffers& buffer_sequence)
  126. {
  127. return buffer_sequence_adapter::first(
  128. boost::asio::buffer_sequence_begin(buffer_sequence),
  129. boost::asio::buffer_sequence_end(buffer_sequence));
  130. }
  131. private:
  132. template <typename Iterator>
  133. void init(Iterator begin, Iterator end)
  134. {
  135. Iterator iter = begin;
  136. for (; iter != end && count_ < max_buffers; ++iter, ++count_)
  137. {
  138. Buffer buffer(*iter);
  139. init_native_buffer(buffers_[count_], buffer);
  140. total_buffer_size_ += buffer.size();
  141. }
  142. }
  143. template <typename Iterator>
  144. static bool all_empty(Iterator begin, Iterator end)
  145. {
  146. Iterator iter = begin;
  147. std::size_t i = 0;
  148. for (; iter != end && i < max_buffers; ++iter, ++i)
  149. if (Buffer(*iter).size() > 0)
  150. return false;
  151. return true;
  152. }
  153. template <typename Iterator>
  154. static void validate(Iterator begin, Iterator end)
  155. {
  156. Iterator iter = begin;
  157. for (; iter != end; ++iter)
  158. {
  159. Buffer buffer(*iter);
  160. buffer.data();
  161. }
  162. }
  163. template <typename Iterator>
  164. static Buffer first(Iterator begin, Iterator end)
  165. {
  166. Iterator iter = begin;
  167. for (; iter != end; ++iter)
  168. {
  169. Buffer buffer(*iter);
  170. if (buffer.size() != 0)
  171. return buffer;
  172. }
  173. return Buffer();
  174. }
  175. native_buffer_type buffers_[max_buffers];
  176. std::size_t count_;
  177. std::size_t total_buffer_size_;
  178. };
  179. template <typename Buffer>
  180. class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffer>
  181. : buffer_sequence_adapter_base
  182. {
  183. public:
  184. explicit buffer_sequence_adapter(
  185. const boost::asio::mutable_buffer& buffer_sequence)
  186. {
  187. init_native_buffer(buffer_, Buffer(buffer_sequence));
  188. total_buffer_size_ = buffer_sequence.size();
  189. }
  190. native_buffer_type* buffers()
  191. {
  192. return &buffer_;
  193. }
  194. std::size_t count() const
  195. {
  196. return 1;
  197. }
  198. std::size_t total_size() const
  199. {
  200. return total_buffer_size_;
  201. }
  202. bool all_empty() const
  203. {
  204. return total_buffer_size_ == 0;
  205. }
  206. static bool all_empty(const boost::asio::mutable_buffer& buffer_sequence)
  207. {
  208. return buffer_sequence.size() == 0;
  209. }
  210. static void validate(const boost::asio::mutable_buffer& buffer_sequence)
  211. {
  212. buffer_sequence.data();
  213. }
  214. static Buffer first(const boost::asio::mutable_buffer& buffer_sequence)
  215. {
  216. return Buffer(buffer_sequence);
  217. }
  218. private:
  219. native_buffer_type buffer_;
  220. std::size_t total_buffer_size_;
  221. };
  222. template <typename Buffer>
  223. class buffer_sequence_adapter<Buffer, boost::asio::const_buffer>
  224. : buffer_sequence_adapter_base
  225. {
  226. public:
  227. explicit buffer_sequence_adapter(
  228. const boost::asio::const_buffer& buffer_sequence)
  229. {
  230. init_native_buffer(buffer_, Buffer(buffer_sequence));
  231. total_buffer_size_ = buffer_sequence.size();
  232. }
  233. native_buffer_type* buffers()
  234. {
  235. return &buffer_;
  236. }
  237. std::size_t count() const
  238. {
  239. return 1;
  240. }
  241. std::size_t total_size() const
  242. {
  243. return total_buffer_size_;
  244. }
  245. bool all_empty() const
  246. {
  247. return total_buffer_size_ == 0;
  248. }
  249. static bool all_empty(const boost::asio::const_buffer& buffer_sequence)
  250. {
  251. return buffer_sequence.size() == 0;
  252. }
  253. static void validate(const boost::asio::const_buffer& buffer_sequence)
  254. {
  255. buffer_sequence.data();
  256. }
  257. static Buffer first(const boost::asio::const_buffer& buffer_sequence)
  258. {
  259. return Buffer(buffer_sequence);
  260. }
  261. private:
  262. native_buffer_type buffer_;
  263. std::size_t total_buffer_size_;
  264. };
  265. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  266. template <typename Buffer>
  267. class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1>
  268. : buffer_sequence_adapter_base
  269. {
  270. public:
  271. explicit buffer_sequence_adapter(
  272. const boost::asio::mutable_buffers_1& buffer_sequence)
  273. {
  274. init_native_buffer(buffer_, Buffer(buffer_sequence));
  275. total_buffer_size_ = buffer_sequence.size();
  276. }
  277. native_buffer_type* buffers()
  278. {
  279. return &buffer_;
  280. }
  281. std::size_t count() const
  282. {
  283. return 1;
  284. }
  285. std::size_t total_size() const
  286. {
  287. return total_buffer_size_;
  288. }
  289. bool all_empty() const
  290. {
  291. return total_buffer_size_ == 0;
  292. }
  293. static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence)
  294. {
  295. return buffer_sequence.size() == 0;
  296. }
  297. static void validate(const boost::asio::mutable_buffers_1& buffer_sequence)
  298. {
  299. buffer_sequence.data();
  300. }
  301. static Buffer first(const boost::asio::mutable_buffers_1& buffer_sequence)
  302. {
  303. return Buffer(buffer_sequence);
  304. }
  305. private:
  306. native_buffer_type buffer_;
  307. std::size_t total_buffer_size_;
  308. };
  309. template <typename Buffer>
  310. class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1>
  311. : buffer_sequence_adapter_base
  312. {
  313. public:
  314. explicit buffer_sequence_adapter(
  315. const boost::asio::const_buffers_1& buffer_sequence)
  316. {
  317. init_native_buffer(buffer_, Buffer(buffer_sequence));
  318. total_buffer_size_ = buffer_sequence.size();
  319. }
  320. native_buffer_type* buffers()
  321. {
  322. return &buffer_;
  323. }
  324. std::size_t count() const
  325. {
  326. return 1;
  327. }
  328. std::size_t total_size() const
  329. {
  330. return total_buffer_size_;
  331. }
  332. bool all_empty() const
  333. {
  334. return total_buffer_size_ == 0;
  335. }
  336. static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence)
  337. {
  338. return buffer_sequence.size() == 0;
  339. }
  340. static void validate(const boost::asio::const_buffers_1& buffer_sequence)
  341. {
  342. buffer_sequence.data();
  343. }
  344. static Buffer first(const boost::asio::const_buffers_1& buffer_sequence)
  345. {
  346. return Buffer(buffer_sequence);
  347. }
  348. private:
  349. native_buffer_type buffer_;
  350. std::size_t total_buffer_size_;
  351. };
  352. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  353. template <typename Buffer, typename Elem>
  354. class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
  355. : buffer_sequence_adapter_base
  356. {
  357. public:
  358. explicit buffer_sequence_adapter(
  359. const boost::array<Elem, 2>& buffer_sequence)
  360. {
  361. init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
  362. init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
  363. total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
  364. }
  365. native_buffer_type* buffers()
  366. {
  367. return buffers_;
  368. }
  369. std::size_t count() const
  370. {
  371. return 2;
  372. }
  373. std::size_t total_size() const
  374. {
  375. return total_buffer_size_;
  376. }
  377. bool all_empty() const
  378. {
  379. return total_buffer_size_ == 0;
  380. }
  381. static bool all_empty(const boost::array<Elem, 2>& buffer_sequence)
  382. {
  383. return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
  384. }
  385. static void validate(const boost::array<Elem, 2>& buffer_sequence)
  386. {
  387. buffer_sequence[0].data();
  388. buffer_sequence[1].data();
  389. }
  390. static Buffer first(const boost::array<Elem, 2>& buffer_sequence)
  391. {
  392. return Buffer(buffer_sequence[0].size() != 0
  393. ? buffer_sequence[0] : buffer_sequence[1]);
  394. }
  395. private:
  396. native_buffer_type buffers_[2];
  397. std::size_t total_buffer_size_;
  398. };
  399. #if defined(BOOST_ASIO_HAS_STD_ARRAY)
  400. template <typename Buffer, typename Elem>
  401. class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
  402. : buffer_sequence_adapter_base
  403. {
  404. public:
  405. explicit buffer_sequence_adapter(
  406. const std::array<Elem, 2>& buffer_sequence)
  407. {
  408. init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
  409. init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
  410. total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
  411. }
  412. native_buffer_type* buffers()
  413. {
  414. return buffers_;
  415. }
  416. std::size_t count() const
  417. {
  418. return 2;
  419. }
  420. std::size_t total_size() const
  421. {
  422. return total_buffer_size_;
  423. }
  424. bool all_empty() const
  425. {
  426. return total_buffer_size_ == 0;
  427. }
  428. static bool all_empty(const std::array<Elem, 2>& buffer_sequence)
  429. {
  430. return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
  431. }
  432. static void validate(const std::array<Elem, 2>& buffer_sequence)
  433. {
  434. buffer_sequence[0].data();
  435. buffer_sequence[1].data();
  436. }
  437. static Buffer first(const std::array<Elem, 2>& buffer_sequence)
  438. {
  439. return Buffer(buffer_sequence[0].size() != 0
  440. ? buffer_sequence[0] : buffer_sequence[1]);
  441. }
  442. private:
  443. native_buffer_type buffers_[2];
  444. std::size_t total_buffer_size_;
  445. };
  446. #endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
  447. } // namespace detail
  448. } // namespace asio
  449. } // namespace boost
  450. #include <boost/asio/detail/pop_options.hpp>
  451. #if defined(BOOST_ASIO_HEADER_ONLY)
  452. # include <boost/asio/detail/impl/buffer_sequence_adapter.ipp>
  453. #endif // defined(BOOST_ASIO_HEADER_ONLY)
  454. #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP