buffer_wrap.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.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 __ASIO2_BUFFER_WRAP_HPP__
  11. #define __ASIO2_BUFFER_WRAP_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <cstddef>
  16. #include <limits>
  17. #include <memory>
  18. #include <type_traits>
  19. #include <asio2/external/asio.hpp>
  20. namespace asio2
  21. {
  22. namespace detail
  23. {
  24. static std::size_t constexpr min_size = 512;
  25. template<class, class = std::void_t<>>
  26. struct buffer_has_limit : std::false_type {};
  27. template<class T>
  28. struct buffer_has_limit<T, std::void_t<decltype(T(std::size_t(0)))>> : std::true_type {};
  29. template<class, class = std::void_t<>>
  30. struct buffer_has_max_size : std::false_type {};
  31. template<class T>
  32. struct buffer_has_max_size<T, std::void_t<decltype(std::declval<T>().max_size())>> : std::true_type {};
  33. //template<typename T>
  34. //struct buffer_has_limit
  35. //{
  36. //private:
  37. // template<typename U>
  38. // static auto check(bool) -> decltype(U(std::size_t(0)), std::true_type());
  39. // template<typename U>
  40. // static std::false_type check(...);
  41. //public:
  42. // static constexpr bool value = std::is_same_v<decltype(check<T>(true)), std::true_type>;
  43. //};
  44. //template<typename T>
  45. //struct buffer_has_max_size
  46. //{
  47. //private:
  48. // template<typename U>
  49. // static auto check(bool) -> decltype(std::declval<U>().max_size(), std::true_type());
  50. // template<typename U>
  51. // static std::false_type check(...);
  52. //public:
  53. // static constexpr bool value = std::is_same_v<decltype(check<T>(true)), std::true_type>;
  54. //};
  55. // send callback indirect
  56. struct callback_helper
  57. {
  58. template<class F>
  59. typename std::enable_if_t<std::is_same_v<decltype(std::declval<F>()(
  60. std::size_t(0)), std::true_type()), std::true_type>>
  61. static inline call(F& f, std::size_t bytes_sent)
  62. {
  63. f(bytes_sent);
  64. }
  65. template<class F>
  66. typename std::enable_if_t<std::is_same_v<decltype(std::declval<F>()(),
  67. std::true_type()), std::true_type>>
  68. static inline call(F& f, std::size_t)
  69. {
  70. f();
  71. }
  72. };
  73. struct empty_buffer
  74. {
  75. using size_type = std::size_t;
  76. inline size_type size () const noexcept { return 0; }
  77. inline size_type max_size() const noexcept { return 0; }
  78. inline size_type capacity() const noexcept { return 0; }
  79. inline auto data () noexcept { return asio::buffer(asio::const_buffer ()); }
  80. inline auto prepare (size_type) noexcept { return asio::buffer(asio::mutable_buffer()); }
  81. inline void commit (size_type) noexcept {}
  82. inline void consume (size_type) noexcept {}
  83. };
  84. template<class B>
  85. struct proxy_buffer
  86. {
  87. using size_type = std::size_t;
  88. proxy_buffer() noexcept {}
  89. proxy_buffer(size_type) noexcept {}
  90. inline size_type size () const noexcept { return b_->size ( ); }
  91. inline size_type max_size() const noexcept { return b_->max_size( ); }
  92. inline size_type capacity() const noexcept { return b_->capacity( ); }
  93. inline auto data () noexcept { return b_->data ( ); }
  94. inline auto prepare (size_type n) noexcept { return b_->prepare (n); }
  95. inline void commit (size_type n) noexcept { b_->commit (n); }
  96. inline void consume (size_type n) noexcept { b_->consume (n); }
  97. inline void bind_buffer(B* b) { b_ = b; }
  98. B* b_ = nullptr;
  99. };
  100. }
  101. template<class buffer_t, bool has_limit = detail::buffer_has_limit<buffer_t>::value>
  102. class buffer_wrap;
  103. template<class buffer_t>
  104. class buffer_wrap<buffer_t, true> : public buffer_t
  105. {
  106. public:
  107. using buffer_type = buffer_t;
  108. using buffer_t::buffer_t;
  109. using size_type = std::size_t;
  110. buffer_wrap() = default;
  111. ~buffer_wrap() = default;
  112. buffer_wrap(size_type max) : buffer_t(max) {}
  113. buffer_wrap(size_type pre, size_type max) : buffer_t(max), pre_(pre)
  114. {
  115. buffer_t::prepare(this->pre_);
  116. }
  117. buffer_wrap(buffer_wrap&& other) = default;
  118. buffer_wrap(buffer_wrap const& other) = default;
  119. buffer_wrap& operator=(buffer_wrap&& other) = default;
  120. buffer_wrap& operator=(buffer_wrap const& other) = default;
  121. inline buffer_t & base() noexcept { return (*this); }
  122. inline buffer_t const& base() const noexcept { return (*this); }
  123. inline size_type pre_size() const noexcept { return this->pre_; }
  124. inline size_type max_size() const noexcept
  125. {
  126. if constexpr (detail::buffer_has_max_size<buffer_t>::value)
  127. return buffer_t::max_size();
  128. else
  129. return (std::numeric_limits<size_type>::max)();
  130. }
  131. inline buffer_wrap& pre_size(size_type size) noexcept { this->pre_ = size; return (*this); }
  132. inline buffer_wrap& max_size(size_type ) noexcept { return (*this); }
  133. inline std::string_view data_view() noexcept
  134. {
  135. auto databuf = this->data();
  136. return std::string_view{ reinterpret_cast<
  137. std::string_view::const_pointer>(databuf.data()), databuf.size() };
  138. }
  139. protected:
  140. size_type pre_ = detail::min_size;
  141. };
  142. template<class buffer_t>
  143. class buffer_wrap<buffer_t, false> : public buffer_t
  144. {
  145. public:
  146. using buffer_type = buffer_t;
  147. using buffer_t::buffer_t;
  148. using size_type = std::size_t;
  149. buffer_wrap() = default;
  150. ~buffer_wrap() = default;
  151. buffer_wrap(size_type max) : buffer_t(), max_(max) {}
  152. buffer_wrap(size_type pre, size_type max) : buffer_t(), pre_(pre), max_(max)
  153. {
  154. buffer_t::prepare(this->pre_);
  155. }
  156. buffer_wrap(buffer_wrap&& other) = default;
  157. buffer_wrap(buffer_wrap const& other) = default;
  158. buffer_wrap& operator=(buffer_wrap&& other) = default;
  159. buffer_wrap& operator=(buffer_wrap const& other) = default;
  160. inline buffer_t & base() noexcept { return (*this); }
  161. inline buffer_t const& base() const noexcept { return (*this); }
  162. inline size_type pre_size() const noexcept { return this->pre_; }
  163. inline size_type max_size() const noexcept
  164. {
  165. if constexpr (detail::buffer_has_max_size<buffer_t>::value)
  166. return buffer_t::max_size();
  167. else
  168. return this->max_;
  169. }
  170. inline buffer_wrap& pre_size(size_type size) noexcept { this->pre_ = size; return (*this); }
  171. inline buffer_wrap& max_size(size_type size) noexcept { this->max_ = size; return (*this); }
  172. inline std::string_view data_view() noexcept
  173. {
  174. auto databuf = this->data();
  175. return std::string_view{ reinterpret_cast<
  176. std::string_view::const_pointer>(databuf.data()), databuf.size() };
  177. }
  178. protected:
  179. size_type pre_ = detail::min_size; // prepare size
  180. size_type max_ = (std::numeric_limits<size_type>::max)();
  181. };
  182. template<class B>
  183. class buffer_wrap<detail::proxy_buffer<B>, true> : public detail::proxy_buffer<B>
  184. {
  185. public:
  186. using proxy = detail::proxy_buffer<B>;
  187. using buffer_type = B;
  188. using detail::proxy_buffer<B>::proxy_buffer;
  189. using size_type = std::size_t;
  190. buffer_wrap() = default;
  191. ~buffer_wrap() = default;
  192. buffer_wrap(size_type max) : proxy(max) {}
  193. buffer_wrap(size_type pre, size_type max) : proxy(max), pre_(pre)
  194. {
  195. }
  196. buffer_wrap(buffer_wrap&& other) = default;
  197. buffer_wrap(buffer_wrap const& other) = default;
  198. buffer_wrap& operator=(buffer_wrap&& other) = default;
  199. buffer_wrap& operator=(buffer_wrap const& other) = default;
  200. inline buffer_type & base() noexcept { return (*this->b_); }
  201. inline buffer_type const& base() const noexcept { return (*this->b_); }
  202. inline size_type pre_size() const noexcept { return this->pre_; }
  203. inline size_type max_size() const noexcept
  204. {
  205. if constexpr (detail::buffer_has_max_size<proxy>::value)
  206. return proxy::max_size();
  207. else
  208. return (std::numeric_limits<size_type>::max)();
  209. }
  210. inline buffer_wrap& pre_size(size_type size) noexcept { this->pre_ = size; return (*this); }
  211. inline buffer_wrap& max_size(size_type ) noexcept { return (*this); }
  212. inline std::string_view data_view() noexcept
  213. {
  214. auto databuf = this->data();
  215. return std::string_view{ reinterpret_cast<
  216. std::string_view::const_pointer>(databuf.data()), databuf.size() };
  217. }
  218. protected:
  219. size_type pre_ = detail::min_size;
  220. };
  221. template<class B>
  222. class buffer_wrap<detail::proxy_buffer<B>, false> : public detail::proxy_buffer<B>
  223. {
  224. public:
  225. using proxy = detail::proxy_buffer<B>;
  226. using buffer_type = B;
  227. using detail::proxy_buffer<B>::proxy_buffer;
  228. using size_type = std::size_t;
  229. buffer_wrap() = default;
  230. ~buffer_wrap() = default;
  231. buffer_wrap(size_type max) : proxy(), max_(max) {}
  232. buffer_wrap(size_type pre, size_type max) : proxy(), pre_(pre), max_(max)
  233. {
  234. }
  235. buffer_wrap(buffer_wrap&& other) = default;
  236. buffer_wrap(buffer_wrap const& other) = default;
  237. buffer_wrap& operator=(buffer_wrap&& other) = default;
  238. buffer_wrap& operator=(buffer_wrap const& other) = default;
  239. inline buffer_type & base() noexcept { return (*this->b_); }
  240. inline buffer_type const& base() const noexcept { return (*this->b_); }
  241. inline size_type pre_size() const noexcept { return this->pre_; }
  242. inline size_type max_size() const noexcept
  243. {
  244. if constexpr (detail::buffer_has_max_size<proxy>::value)
  245. return proxy::max_size();
  246. else
  247. return this->max_;
  248. }
  249. inline buffer_wrap& pre_size(size_type size) noexcept { this->pre_ = size; return (*this); }
  250. inline buffer_wrap& max_size(size_type size) noexcept { this->max_ = size; return (*this); }
  251. inline std::string_view data_view() noexcept
  252. {
  253. auto databuf = this->data();
  254. return std::string_view{ reinterpret_cast<
  255. std::string_view::const_pointer>(databuf.data()), databuf.size() };
  256. }
  257. protected:
  258. size_type pre_ = detail::min_size; // prepare size
  259. size_type max_ = (std::numeric_limits<size_type>::max)();
  260. };
  261. template<>
  262. class buffer_wrap<detail::empty_buffer, true> : public detail::empty_buffer
  263. {
  264. public:
  265. using buffer_type = detail::empty_buffer;
  266. using size_type = std::size_t;
  267. buffer_wrap() = default;
  268. ~buffer_wrap() = default;
  269. buffer_wrap(size_type ) noexcept {}
  270. buffer_wrap(size_type, size_type) noexcept {}
  271. buffer_wrap(buffer_wrap&& other) = default;
  272. buffer_wrap(buffer_wrap const& other) = default;
  273. buffer_wrap& operator=(buffer_wrap&& other) = default;
  274. buffer_wrap& operator=(buffer_wrap const& other) = default;
  275. inline detail::empty_buffer & base() noexcept { return (*this); }
  276. inline detail::empty_buffer const& base() const noexcept { return (*this); }
  277. inline size_type pre_size( ) const noexcept { return 0; }
  278. inline size_type max_size( ) const noexcept { return 0; }
  279. inline buffer_wrap& pre_size(size_type) noexcept { return (*this); }
  280. inline buffer_wrap& max_size(size_type) noexcept { return (*this); }
  281. inline std::string_view data_view() noexcept
  282. {
  283. auto databuf = this->data();
  284. return std::string_view{ reinterpret_cast<
  285. std::string_view::const_pointer>(databuf.data()), databuf.size() };
  286. }
  287. };
  288. template<>
  289. class buffer_wrap<detail::empty_buffer, false> : public detail::empty_buffer
  290. {
  291. public:
  292. using buffer_type = detail::empty_buffer;
  293. using size_type = std::size_t;
  294. buffer_wrap() = default;
  295. ~buffer_wrap() = default;
  296. buffer_wrap(size_type ) noexcept {}
  297. buffer_wrap(size_type, size_type) noexcept {}
  298. buffer_wrap(buffer_wrap&& other) = default;
  299. buffer_wrap(buffer_wrap const& other) = default;
  300. buffer_wrap& operator=(buffer_wrap&& other) = default;
  301. buffer_wrap& operator=(buffer_wrap const& other) = default;
  302. inline detail::empty_buffer & base() noexcept { return (*this); }
  303. inline detail::empty_buffer const& base() const noexcept { return (*this); }
  304. inline size_type pre_size( ) const noexcept { return 0; }
  305. inline size_type max_size( ) const noexcept { return 0; }
  306. inline buffer_wrap& pre_size(size_type) noexcept { return (*this); }
  307. inline buffer_wrap& max_size(size_type) noexcept { return (*this); }
  308. inline std::string_view data_view() noexcept
  309. {
  310. auto databuf = this->data();
  311. return std::string_view{ reinterpret_cast<
  312. std::string_view::const_pointer>(databuf.data()), databuf.size() };
  313. }
  314. };
  315. }
  316. #endif // !__ASIO2_BUFFER_WRAP_HPP__