ecs.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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_ECS_HPP__
  11. #define __ASIO2_ECS_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <tuple>
  16. #include <asio2/base/detail/match_condition.hpp>
  17. #include <asio2/component/rdc/rdc_option.hpp>
  18. #include <asio2/component/socks/socks5_option.hpp>
  19. namespace asio2::detail
  20. {
  21. struct component_tag {};
  22. struct component_dummy {};
  23. template<class ConditionT, class... Args>
  24. struct component_t : public component_tag
  25. {
  26. static constexpr std::size_t componentc = sizeof...(Args);
  27. using components_type = std::tuple<typename detail::shared_ptr_adapter<Args>::type...>;
  28. using condition_type = condition_t<typename detail::remove_cvref_t<ConditionT>>;
  29. using condition_lowest_type = typename condition_type::type;
  30. template<std::size_t I>
  31. struct components
  32. {
  33. static_assert(I < componentc, "index is out of range, index must less than sizeof Args");
  34. using type = typename std::tuple_element<I, components_type>::type;
  35. using raw_type = typename element_type_adapter<type>::type;
  36. };
  37. component_t(component_t&&) noexcept = default;
  38. component_t(component_t const&) = delete;
  39. component_t& operator=(component_t&&) noexcept = default;
  40. component_t& operator=(component_t const&) = delete;
  41. template<std::size_t... I>
  42. inline component_t clone_impl(std::index_sequence<I...>) noexcept
  43. {
  44. return component_t{ this->condition_.clone(),
  45. (typename components<I>::raw_type(*std::get<I>(this->components_)))... };
  46. }
  47. inline component_t clone()
  48. {
  49. return clone_impl(std::make_index_sequence<componentc>{});
  50. }
  51. template<class LowestT, class... Ts>
  52. explicit component_t(LowestT&& c, Ts&&... ts)
  53. : condition_(std::forward<LowestT>(c))
  54. , components_(detail::to_shared_ptr(std::forward<Ts>(ts))...)
  55. {
  56. }
  57. inline decltype(auto) operator()() noexcept { return condition_(); }
  58. template<typename = void>
  59. static constexpr bool has_rdc() noexcept
  60. {
  61. return (std::is_base_of_v<asio2::rdc::option_base,
  62. typename element_type_adapter<typename detail::remove_cvref_t<Args>>::type> || ...);
  63. }
  64. template<std::size_t I, typename T1, typename... TN>
  65. static constexpr std::size_t rdc_index_helper() noexcept
  66. {
  67. if constexpr (std::is_base_of_v<asio2::rdc::option_base, T1>)
  68. return I;
  69. else
  70. {
  71. if constexpr (sizeof...(TN) == 0)
  72. return std::size_t(0);
  73. else
  74. return rdc_index_helper<I + 1, TN...>();
  75. }
  76. }
  77. template<typename = void>
  78. static constexpr std::size_t rdc_index() noexcept
  79. {
  80. return rdc_index_helper<0,
  81. typename element_type_adapter<typename detail::remove_cvref_t<Args>>::type...>();
  82. }
  83. template<class Tag, std::enable_if_t<std::is_same_v<Tag, std::in_place_t>, int> = 0>
  84. typename components<rdc_index()>::type rdc_option(Tag) noexcept
  85. {
  86. return std::get<rdc_index()>(components_);
  87. }
  88. template<typename = void>
  89. asio2::rdc::option_base* rdc_option_addr() noexcept
  90. {
  91. if constexpr (has_rdc())
  92. {
  93. return this->rdc_option(std::in_place).get();
  94. }
  95. else
  96. {
  97. return nullptr;
  98. }
  99. }
  100. template<typename = void>
  101. static constexpr bool has_socks5() noexcept
  102. {
  103. return (std::is_base_of_v<asio2::socks5::option_base,
  104. typename element_type_adapter<typename detail::remove_cvref_t<Args>>::type> || ...);
  105. }
  106. template<std::size_t I, typename T1, typename... TN>
  107. static constexpr std::size_t socks5_index_helper() noexcept
  108. {
  109. if constexpr (std::is_base_of_v<asio2::socks5::option_base, T1>)
  110. return I;
  111. else
  112. {
  113. if constexpr (sizeof...(TN) == 0)
  114. return std::size_t(0);
  115. else
  116. return socks5_index_helper<I + 1, TN...>();
  117. }
  118. }
  119. template<typename = void>
  120. static constexpr std::size_t socks5_index() noexcept
  121. {
  122. return socks5_index_helper<0,
  123. typename element_type_adapter<typename detail::remove_cvref_t<Args>>::type...>();
  124. }
  125. template<class Tag, std::enable_if_t<std::is_same_v<Tag, std::in_place_t>, int> = 0>
  126. typename components<socks5_index()>::type socks5_option(Tag) noexcept
  127. {
  128. return std::get<socks5_index()>(components_);
  129. }
  130. inline condition_type & get_condition() noexcept { return condition_; }
  131. inline components_type & values () noexcept { return components_; }
  132. protected:
  133. condition_type condition_;
  134. components_type components_;
  135. };
  136. // C++17 class template argument deduction guides
  137. template<class C, class... Ts>
  138. component_t(C, Ts...)->component_t<C, Ts...>;
  139. }
  140. namespace asio2::detail
  141. {
  142. /**
  143. *
  144. */
  145. class ecs_base
  146. {
  147. public:
  148. virtual ~ecs_base() {}
  149. virtual asio2::rdc::option_base* get_rdc() noexcept { return nullptr; }
  150. };
  151. template<class T>
  152. class ecs_t : public ecs_base
  153. {
  154. public:
  155. using component_type = component_dummy;
  156. using condition_type = condition_t<T>;
  157. using condition_lowest_type = typename condition_type::type;
  158. ecs_t() noexcept = default;
  159. ~ecs_t() noexcept = default;
  160. ecs_t(ecs_t&&) noexcept = default;
  161. ecs_t(ecs_t const&) = delete;
  162. ecs_t& operator=(ecs_t&&) noexcept = default;
  163. ecs_t& operator=(ecs_t const&) = delete;
  164. inline ecs_t clone() noexcept { return ecs_t{ this->condition_.clone() }; }
  165. template<class LowestT, std::enable_if_t<!std::is_base_of_v<ecs_t, detail::remove_cvref_t<LowestT>>, int> = 0>
  166. explicit ecs_t(LowestT c) noexcept : condition_(std::move(c)) {}
  167. explicit ecs_t(condition_type c) noexcept : condition_(std::move(c)) {}
  168. inline condition_type& get_condition() noexcept { return condition_; }
  169. inline component_type& get_component() noexcept { return component_; }
  170. protected:
  171. condition_type condition_;
  172. component_type component_;
  173. };
  174. // C++17 class template argument deduction guides
  175. template<class T>
  176. ecs_t(T)->ecs_t<std::remove_reference_t<T>>;
  177. template<>
  178. class ecs_t<void> : public ecs_base
  179. {
  180. public:
  181. using component_type = component_dummy;
  182. using condition_type = condition_t<void>;
  183. using condition_lowest_type = void;
  184. ecs_t() noexcept = default;
  185. ~ecs_t() noexcept = default;
  186. ecs_t(ecs_t&&) noexcept = default;
  187. ecs_t(ecs_t const&) noexcept = delete;
  188. ecs_t& operator=(ecs_t&&) noexcept = default;
  189. ecs_t& operator=(ecs_t const&) noexcept = delete;
  190. inline ecs_t clone() noexcept { return ecs_t{}; }
  191. inline condition_type& get_condition() noexcept { return condition_; }
  192. inline component_type& get_component() noexcept { return component_; }
  193. protected:
  194. condition_type condition_;
  195. component_type component_;
  196. };
  197. template<class ConditionT, class... Args>
  198. class ecs_t<component_t<ConditionT, Args...>> : public ecs_base
  199. {
  200. public:
  201. using component_type = component_t<ConditionT, Args...>;
  202. using condition_type = typename component_type::condition_type;
  203. using condition_lowest_type = typename condition_type::type;
  204. ecs_t() noexcept = default;
  205. ~ecs_t() noexcept = default;
  206. ecs_t(ecs_t&&) noexcept = default;
  207. ecs_t(ecs_t const&) = delete;
  208. ecs_t& operator=(ecs_t&&) noexcept = default;
  209. ecs_t& operator=(ecs_t const&) = delete;
  210. inline ecs_t clone() noexcept { return ecs_t{ this->component_.clone() }; }
  211. template<class C, std::enable_if_t<!std::is_base_of_v<ecs_t, detail::remove_cvref_t<C>>, int> = 0>
  212. explicit ecs_t(C c) : component_(std::move(c)) {}
  213. inline condition_type& get_condition() noexcept { return component_.get_condition(); }
  214. inline component_type& get_component() noexcept { return component_; }
  215. virtual asio2::rdc::option_base* get_rdc() noexcept override
  216. {
  217. return this->component_.rdc_option_addr();
  218. }
  219. protected:
  220. component_type component_;
  221. };
  222. }
  223. namespace asio2::detail
  224. {
  225. struct ecs_helper
  226. {
  227. template<class T>
  228. static constexpr bool is_component() noexcept
  229. {
  230. using type = detail::remove_cvref_t<T>;
  231. if constexpr (is_template_instance_of_v<std::shared_ptr, type>)
  232. {
  233. return is_component<typename type::element_type>();
  234. }
  235. else
  236. {
  237. if /**/ constexpr (std::is_base_of_v<asio2::rdc::option_base, type>)
  238. return true;
  239. else if constexpr (std::is_base_of_v<asio2::socks5::option_base, type>)
  240. return true;
  241. else
  242. return false;
  243. }
  244. }
  245. template<class... Args>
  246. static constexpr bool args_has_match_condition() noexcept
  247. {
  248. if constexpr (sizeof...(Args) == std::size_t(0))
  249. return false;
  250. else
  251. return (!(ecs_helper::is_component<Args>() && ...));
  252. }
  253. template<class... Args>
  254. static constexpr bool args_has_rdc() noexcept
  255. {
  256. if constexpr (sizeof...(Args) == std::size_t(0))
  257. return false;
  258. else
  259. return (std::is_base_of_v<asio2::rdc::option_base, detail::remove_cvref_t<Args>> || ...);
  260. }
  261. template<class... Args>
  262. static constexpr bool args_has_socks5() noexcept
  263. {
  264. if constexpr (sizeof...(Args) == std::size_t(0))
  265. return false;
  266. else
  267. return (std::is_base_of_v<asio2::socks5::option_base, detail::remove_cvref_t<Args>> || ...);
  268. }
  269. // use "DefaultConditionT c, Args... args", not use "DefaultConditionT&& c, Args&&... args"
  270. // to avoid the "c and args..." variables being references
  271. template<class DefaultConditionT, class... Args>
  272. static constexpr auto make_ecs(DefaultConditionT c, Args... args) noexcept
  273. {
  274. detail::ignore_unused(c);
  275. if constexpr (ecs_helper::args_has_match_condition<Args...>())
  276. {
  277. if constexpr (sizeof...(Args) == std::size_t(1))
  278. return detail::to_shared_ptr(ecs_t{ std::move(args)... });
  279. else
  280. return detail::to_shared_ptr(ecs_t{ component_t{std::move(args)...} });
  281. }
  282. else
  283. {
  284. if constexpr (sizeof...(Args) == std::size_t(0))
  285. return detail::to_shared_ptr(ecs_t{ std::move(c), std::move(args)... });
  286. else
  287. return detail::to_shared_ptr(ecs_t{ component_t{std::move(c), std::move(args)...} });
  288. }
  289. }
  290. template<typename C>
  291. static constexpr bool has_rdc() noexcept
  292. {
  293. if constexpr (std::is_base_of_v<component_tag, detail::remove_cvref_t<C>>)
  294. {
  295. return C::has_rdc();
  296. }
  297. else
  298. {
  299. return false;
  300. }
  301. }
  302. template<typename C>
  303. static constexpr bool has_socks5() noexcept
  304. {
  305. if constexpr (std::is_base_of_v<component_tag, detail::remove_cvref_t<C>>)
  306. {
  307. return C::has_socks5();
  308. }
  309. else
  310. {
  311. return false;
  312. }
  313. }
  314. };
  315. }
  316. #endif // !__ASIO2_ECS_HPP__