out_value_policy.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
  2. // Permission is hereby granted, free of charge, to any person obtaining a
  3. // copy of this software and associated documentation files (the "Software"),
  4. // to deal in the Software without restriction, including without limitation
  5. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  6. // and/or sell copies of the Software, and to permit persons to whom the
  7. // Software is furnished to do so, subject to the following conditions:
  8. // The above copyright notice and this permission notice shall be included
  9. // in all copies or substantial portions of the Software.
  10. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  11. // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  12. // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  13. // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  14. // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  15. // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  16. // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  18. // OR OTHER DEALINGS IN THE SOFTWARE.
  19. #ifndef LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED
  20. #define LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED
  21. #include <luabind/config.hpp>
  22. #include <luabind/detail/policy.hpp>
  23. #include <boost/mpl/apply_wrap.hpp>
  24. namespace luabind { namespace detail
  25. {
  26. template<int N>
  27. struct char_array
  28. {
  29. char storage[N];
  30. };
  31. #if defined(__GNUC__) && ( __GNUC__ == 3 && __GNUC_MINOR__ == 1 )
  32. template<class U>
  33. char_array<sizeof(U)> indirect_sizeof_test(by_reference<U>);
  34. template<class U>
  35. char_array<sizeof(U)> indirect_sizeof_test(by_const_reference<U>);
  36. template<class U>
  37. char_array<sizeof(U)> indirect_sizeof_test(by_pointer<U>);
  38. template<class U>
  39. char_array<sizeof(U)> indirect_sizeof_test(by_const_pointer<U>);
  40. template<class U>
  41. char_array<sizeof(U)> indirect_sizeof_test(by_value<U>);
  42. #else
  43. template<class U>
  44. char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_reference<U>);
  45. template<class U>
  46. char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_const_reference<U>);
  47. template<class U>
  48. char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_pointer<U>);
  49. template<class U>
  50. char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_const_pointer<U>);
  51. template<class U>
  52. char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_value<U>);
  53. #endif
  54. template<class T>
  55. struct indirect_sizeof
  56. {
  57. BOOST_STATIC_CONSTANT(int, value = sizeof(indirect_sizeof_test(LUABIND_DECORATE_TYPE(T))));
  58. };
  59. namespace mpl = boost::mpl;
  60. template<int Size, class Policies = detail::null_type>
  61. struct out_value_converter
  62. {
  63. int const consumed_args(...)
  64. {
  65. return 1;
  66. }
  67. template<class T>
  68. T& apply(lua_State* L, by_reference<T>, int index)
  69. {
  70. typedef typename find_conversion_policy<1, Policies>::type converter_policy;
  71. typename mpl::apply_wrap2<converter_policy,T,lua_to_cpp>::type converter;
  72. new (m_storage) T(converter.apply(L, LUABIND_DECORATE_TYPE(T), index));
  73. return *reinterpret_cast<T*>(m_storage);
  74. }
  75. template<class T>
  76. static int match(lua_State* L, by_reference<T>, int index)
  77. {
  78. typedef typename find_conversion_policy<1, Policies>::type converter_policy;
  79. typedef typename mpl::apply_wrap2<converter_policy,T,lua_to_cpp>::type converter;
  80. return converter::match(L, LUABIND_DECORATE_TYPE(T), index);
  81. }
  82. template<class T>
  83. void converter_postcall(lua_State* L, by_reference<T>, int)
  84. {
  85. typedef typename find_conversion_policy<2, Policies>::type converter_policy;
  86. typename mpl::apply_wrap2<converter_policy,T,cpp_to_lua>::type converter;
  87. converter.apply(L, *reinterpret_cast<T*>(m_storage));
  88. reinterpret_cast<T*>(m_storage)->~T();
  89. }
  90. template<class T>
  91. T* apply(lua_State* L, by_pointer<T>, int index)
  92. {
  93. typedef typename find_conversion_policy<1, Policies>::type converter_policy;
  94. typename mpl::apply_wrap2<converter_policy,T,lua_to_cpp>::type converter;
  95. new (m_storage) T(converter.apply(L, LUABIND_DECORATE_TYPE(T), index));
  96. return reinterpret_cast<T*>(m_storage);
  97. }
  98. template<class T>
  99. static int match(lua_State* L, by_pointer<T>, int index)
  100. {
  101. typedef typename find_conversion_policy<1, Policies>::type converter_policy;
  102. typedef typename mpl::apply_wrap2<converter_policy,T,lua_to_cpp>::type converter;
  103. return converter::match(L, LUABIND_DECORATE_TYPE(T), index);
  104. }
  105. template<class T>
  106. void converter_postcall(lua_State* L, by_pointer<T>, int)
  107. {
  108. typedef typename find_conversion_policy<2, Policies>::type converter_policy;
  109. typename mpl::apply_wrap2<converter_policy,T,cpp_to_lua>::type converter;
  110. converter.apply(L, *reinterpret_cast<T*>(m_storage));
  111. reinterpret_cast<T*>(m_storage)->~T();
  112. }
  113. char m_storage[Size];
  114. };
  115. template<int N, class Policies = detail::null_type>
  116. struct out_value_policy : conversion_policy<N>
  117. {
  118. static void precall(lua_State*, const index_map&) {}
  119. static void postcall(lua_State*, const index_map&) {}
  120. struct only_accepts_nonconst_references_or_pointers {};
  121. struct can_only_convert_from_lua_to_cpp {};
  122. template<class T, class Direction>
  123. struct apply
  124. {
  125. typedef typename boost::mpl::if_<boost::is_same<lua_to_cpp, Direction>
  126. , typename boost::mpl::if_<boost::mpl::or_<is_nonconst_reference<T>, is_nonconst_pointer<T> >
  127. , out_value_converter<indirect_sizeof<T>::value, Policies>
  128. , only_accepts_nonconst_references_or_pointers
  129. >::type
  130. , can_only_convert_from_lua_to_cpp
  131. >::type type;
  132. };
  133. };
  134. template<int Size, class Policies = detail::null_type>
  135. struct pure_out_value_converter
  136. {
  137. int const consumed_args(...)
  138. {
  139. return 0;
  140. }
  141. template<class T>
  142. T& apply(lua_State*, by_reference<T>, int)
  143. {
  144. new (m_storage) T();
  145. return *reinterpret_cast<T*>(m_storage);
  146. }
  147. template<class T>
  148. static int match(lua_State*, by_reference<T>, int)
  149. {
  150. return 0;
  151. }
  152. template<class T>
  153. void converter_postcall(lua_State* L, by_reference<T>, int)
  154. {
  155. typedef typename find_conversion_policy<1, Policies>::type converter_policy;
  156. typename mpl::apply_wrap2<converter_policy,T,cpp_to_lua>::type converter;
  157. converter.apply(L, *reinterpret_cast<T*>(m_storage));
  158. reinterpret_cast<T*>(m_storage)->~T();
  159. }
  160. template<class T>
  161. T* apply(lua_State*, by_pointer<T>, int)
  162. {
  163. new (m_storage) T();
  164. return reinterpret_cast<T*>(m_storage);
  165. }
  166. template<class T>
  167. static int match(lua_State*, by_pointer<T>, int)
  168. {
  169. return 0;
  170. }
  171. template<class T>
  172. void converter_postcall(lua_State* L, by_pointer<T>, int)
  173. {
  174. typedef typename find_conversion_policy<1, Policies>::type converter_policy;
  175. typename mpl::apply_wrap2<converter_policy,T,cpp_to_lua>::type converter;
  176. converter.apply(L, *reinterpret_cast<T*>(m_storage));
  177. reinterpret_cast<T*>(m_storage)->~T();
  178. }
  179. char m_storage[Size];
  180. };
  181. template<int N, class Policies = detail::null_type>
  182. struct pure_out_value_policy : conversion_policy<N, false>
  183. {
  184. static void precall(lua_State*, const index_map&) {}
  185. static void postcall(lua_State*, const index_map&) {}
  186. struct only_accepts_nonconst_references_or_pointers {};
  187. struct can_only_convert_from_lua_to_cpp {};
  188. template<class T, class Direction>
  189. struct apply
  190. {
  191. typedef typename boost::mpl::if_<boost::is_same<lua_to_cpp, Direction>
  192. , typename boost::mpl::if_<boost::mpl::or_<is_nonconst_reference<T>, is_nonconst_pointer<T> >
  193. , pure_out_value_converter<indirect_sizeof<T>::value, Policies>
  194. , only_accepts_nonconst_references_or_pointers
  195. >::type
  196. , can_only_convert_from_lua_to_cpp
  197. >::type type;
  198. };
  199. };
  200. }}
  201. namespace luabind
  202. {
  203. template<int N>
  204. detail::policy_cons<detail::out_value_policy<N>, detail::null_type>
  205. out_value(LUABIND_PLACEHOLDER_ARG(N))
  206. {
  207. return detail::policy_cons<detail::out_value_policy<N>, detail::null_type>();
  208. }
  209. template<int N, class Policies>
  210. detail::policy_cons<detail::out_value_policy<N, Policies>, detail::null_type>
  211. out_value(LUABIND_PLACEHOLDER_ARG(N), const Policies&)
  212. {
  213. return detail::policy_cons<detail::out_value_policy<N, Policies>, detail::null_type>();
  214. }
  215. template<int N>
  216. detail::policy_cons<detail::pure_out_value_policy<N>, detail::null_type>
  217. pure_out_value(LUABIND_PLACEHOLDER_ARG(N))
  218. {
  219. return detail::policy_cons<detail::pure_out_value_policy<N>, detail::null_type>();
  220. }
  221. template<int N, class Policies>
  222. detail::policy_cons<detail::pure_out_value_policy<N, Policies>, detail::null_type>
  223. pure_out_value(LUABIND_PLACEHOLDER_ARG(N), const Policies&)
  224. {
  225. return detail::policy_cons<detail::pure_out_value_policy<N, Policies>, detail::null_type>();
  226. }
  227. }
  228. #endif // LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED