xexpression_holder.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTENSOR_XEXPRESSION_HOLDER_HPP
  10. #define XTENSOR_XEXPRESSION_HOLDER_HPP
  11. #include <memory>
  12. #include <nlohmann/json.hpp>
  13. #include "xarray.hpp"
  14. #include "xjson.hpp"
  15. #include "xtensor_config.hpp"
  16. #include "xtl/xany.hpp"
  17. namespace xt
  18. {
  19. namespace detail
  20. {
  21. class xexpression_holder_impl;
  22. template <class CTE>
  23. class xexpression_wrapper;
  24. }
  25. class xexpression_holder // Value semantic
  26. {
  27. public:
  28. using implementation_type = detail::xexpression_holder_impl;
  29. xexpression_holder() = default;
  30. template <class E>
  31. xexpression_holder(E&& expr);
  32. xexpression_holder(implementation_type* holder);
  33. xexpression_holder(const xexpression_holder& holder);
  34. xexpression_holder(xexpression_holder&& holder);
  35. xexpression_holder& operator=(const xexpression_holder&);
  36. xexpression_holder& operator=(xexpression_holder&&);
  37. void swap(xexpression_holder&);
  38. void to_json(nlohmann::json&) const;
  39. void from_json(const nlohmann::json&);
  40. private:
  41. void init_pointer_from_json(const nlohmann::json&);
  42. void check_holder() const;
  43. std::unique_ptr<implementation_type> p_holder;
  44. };
  45. /*************************************
  46. * to_json and from_json declaration *
  47. *************************************/
  48. /// @cond DOXYGEN_INCLUDE_SFINAE
  49. void to_json(nlohmann::json& j, const xexpression_holder& o);
  50. void from_json(const nlohmann::json& j, xexpression_holder& o);
  51. /// @endcond
  52. namespace detail
  53. {
  54. class xexpression_holder_impl // Entity semantic
  55. {
  56. public:
  57. xexpression_holder_impl(xexpression_holder_impl&&) = delete;
  58. xexpression_holder_impl& operator=(const xexpression_holder_impl&) = delete;
  59. xexpression_holder_impl& operator=(xexpression_holder_impl&&) = delete;
  60. virtual xexpression_holder_impl* clone() const = 0;
  61. virtual void to_json(nlohmann::json&) const = 0;
  62. virtual void from_json(const nlohmann::json&) = 0;
  63. virtual ~xexpression_holder_impl() = default;
  64. protected:
  65. xexpression_holder_impl() = default;
  66. xexpression_holder_impl(const xexpression_holder_impl&) = default;
  67. };
  68. template <class CTE>
  69. class xexpression_wrapper : public xexpression_holder_impl
  70. {
  71. public:
  72. template <class E>
  73. xexpression_wrapper(E&& expr);
  74. xexpression_wrapper* clone() const;
  75. void to_json(nlohmann::json&) const;
  76. void from_json(const nlohmann::json&);
  77. ~xexpression_wrapper() = default;
  78. protected:
  79. xexpression_wrapper(const xexpression_wrapper&);
  80. private:
  81. CTE m_expression;
  82. };
  83. }
  84. template <class E>
  85. inline xexpression_holder::xexpression_holder(E&& expr)
  86. : p_holder(new detail::xexpression_wrapper<E>(std::forward<E>(expr)))
  87. {
  88. }
  89. inline xexpression_holder::xexpression_holder(implementation_type* holder)
  90. : p_holder(holder)
  91. {
  92. }
  93. inline xexpression_holder::xexpression_holder(const xexpression_holder& holder)
  94. : p_holder(holder.p_holder->clone())
  95. {
  96. }
  97. inline xexpression_holder::xexpression_holder(xexpression_holder&& holder)
  98. : p_holder(std::move(holder.p_holder))
  99. {
  100. }
  101. inline xexpression_holder& xexpression_holder::operator=(const xexpression_holder& holder)
  102. {
  103. xexpression_holder tmp(holder);
  104. swap(tmp);
  105. return *this;
  106. }
  107. inline xexpression_holder& xexpression_holder::operator=(xexpression_holder&& holder)
  108. {
  109. swap(holder);
  110. return *this;
  111. }
  112. inline void xexpression_holder::swap(xexpression_holder& holder)
  113. {
  114. std::swap(p_holder, holder.p_holder);
  115. }
  116. inline void xexpression_holder::to_json(nlohmann::json& j) const
  117. {
  118. if (p_holder == nullptr)
  119. {
  120. return;
  121. }
  122. p_holder->to_json(j);
  123. }
  124. inline void xexpression_holder::from_json(const nlohmann::json& j)
  125. {
  126. if (!j.is_array())
  127. {
  128. XTENSOR_THROW(std::runtime_error, "Received a JSON that does not contain a tensor");
  129. }
  130. if (p_holder == nullptr)
  131. {
  132. init_pointer_from_json(j);
  133. }
  134. p_holder->from_json(j);
  135. }
  136. inline void xexpression_holder::init_pointer_from_json(const nlohmann::json& j)
  137. {
  138. if (j.is_array())
  139. {
  140. return init_pointer_from_json(j[0]);
  141. }
  142. if (j.is_number())
  143. {
  144. xt::xarray<double> empty_arr;
  145. p_holder.reset(new detail::xexpression_wrapper<xt::xarray<double>>(std::move(empty_arr)));
  146. }
  147. if (j.is_boolean())
  148. {
  149. xt::xarray<bool> empty_arr;
  150. p_holder.reset(new detail::xexpression_wrapper<xt::xarray<bool>>(std::move(empty_arr)));
  151. }
  152. if (j.is_string())
  153. {
  154. xt::xarray<std::string> empty_arr;
  155. p_holder.reset(new detail::xexpression_wrapper<xt::xarray<std::string>>(std::move(empty_arr)));
  156. }
  157. XTENSOR_THROW(std::runtime_error, "Received a JSON with a tensor that contains unsupported data type");
  158. }
  159. inline void xexpression_holder::check_holder() const
  160. {
  161. if (p_holder == nullptr)
  162. {
  163. XTENSOR_THROW(std::runtime_error, "The holder does not contain an expression");
  164. }
  165. }
  166. /****************************************
  167. * to_json and from_json implementation *
  168. ****************************************/
  169. /// @cond DOXYGEN_INCLUDE_SFINAE
  170. inline void to_json(nlohmann::json& j, const xexpression_holder& o)
  171. {
  172. o.to_json(j);
  173. }
  174. inline void from_json(const nlohmann::json& j, xexpression_holder& o)
  175. {
  176. o.from_json(j);
  177. }
  178. /// @endcond
  179. namespace detail
  180. {
  181. template <class CTE>
  182. template <class E>
  183. inline xexpression_wrapper<CTE>::xexpression_wrapper(E&& expr)
  184. : xexpression_holder_impl()
  185. , m_expression(std::forward<E>(expr))
  186. {
  187. }
  188. template <class CTE>
  189. inline xexpression_wrapper<CTE>* xexpression_wrapper<CTE>::clone() const
  190. {
  191. return new xexpression_wrapper<CTE>(*this);
  192. }
  193. template <class CTE>
  194. inline void xexpression_wrapper<CTE>::to_json(nlohmann::json& j) const
  195. {
  196. ::xt::to_json(j, m_expression);
  197. }
  198. template <class CTE>
  199. inline void xexpression_wrapper<CTE>::from_json(const nlohmann::json& j)
  200. {
  201. ::xt::from_json(j, m_expression);
  202. }
  203. template <class CTE>
  204. inline xexpression_wrapper<CTE>::xexpression_wrapper(const xexpression_wrapper& wrapper)
  205. : xexpression_holder_impl()
  206. , m_expression(wrapper.m_expression)
  207. {
  208. }
  209. }
  210. }
  211. #endif