1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
24 #ifndef LUABIND_POLICY_HPP_INCLUDED
25 #define LUABIND_POLICY_HPP_INCLUDED
27 #include <luabind/config.hpp>
33 #include <boost/type_traits/is_enum.hpp>
34 #include <boost/type_traits/is_array.hpp>
35 #include <boost/mpl/bool.hpp>
36 #include <boost/mpl/integral_c.hpp>
37 #include <boost/mpl/equal_to.hpp>
38 #include <boost/mpl/eval_if.hpp>
39 #include <boost/mpl/or.hpp>
40 #include <boost/type_traits/add_reference.hpp>
41 #include <boost/type_traits/remove_reference.hpp>
42 #include <boost/type_traits/is_pointer.hpp>
43 #include <boost/type_traits/is_base_and_derived.hpp>
44 #include <boost/bind/arg.hpp>
45 #include <boost/bind/placeholders.hpp>
46 #include <boost/limits.hpp>
47 #include <boost/tuple/tuple.hpp>
48 #include <boost/version.hpp>
50 #include <luabind/detail/class_registry.hpp>
51 #include <luabind/detail/primitives.hpp>
52 #include <luabind/detail/object_rep.hpp>
53 #include <luabind/detail/typetraits.hpp>
54 #include <luabind/detail/debug.hpp>
55 #include <luabind/detail/class_rep.hpp>
56 #include <luabind/detail/has_get_pointer.hpp>
57 #include <luabind/detail/make_instance.hpp>
59 #include <boost/type_traits/add_reference.hpp>
61 #include <luabind/detail/decorate_type.hpp>
62 #include <luabind/weak_ref.hpp>
63 #include <luabind/back_reference_fwd.hpp>
65 #include <luabind/value_wrapper.hpp>
66 #include <luabind/from_stack.hpp>
67 #include <luabind/typeid.hpp>
73 struct conversion_policy_base
{};
76 template<int N
, bool HasArg
= true>
77 struct conversion_policy
: detail::conversion_policy_base
79 BOOST_STATIC_CONSTANT(int, index
= N
);
80 BOOST_STATIC_CONSTANT(bool, has_arg
= HasArg
);
86 index_map(const int* m
): m_map(m
) {}
88 int operator[](int index
) const
97 // template<class T> class functor;
101 namespace luabind
{ namespace detail
103 template<class H
, class T
>
110 policy_cons
<U
, policy_cons
<H
,T
> > operator,(policy_cons
<U
,detail::null_type
>)
112 return policy_cons
<U
, policy_cons
<H
,T
> >();
116 policy_cons
<U
, policy_cons
<H
,T
> > operator+(policy_cons
<U
,detail::null_type
>)
118 return policy_cons
<U
, policy_cons
<H
,T
> >();
122 policy_cons
<U
, policy_cons
<H
,T
> > operator|(policy_cons
<U
,detail::null_type
>)
124 return policy_cons
<U
, policy_cons
<H
,T
> >();
128 struct indirection_layer
131 indirection_layer(const T
&);
134 yes_t
is_policy_cons_test(const null_type
&);
135 template<class H
, class T
>
136 yes_t
is_policy_cons_test(const policy_cons
<H
,T
>&);
137 no_t
is_policy_cons_test(...);
140 struct is_policy_cons
144 BOOST_STATIC_CONSTANT(bool, value
=
145 sizeof(is_policy_cons_test(t
)) == sizeof(yes_t
));
147 typedef boost::mpl::bool_
<value
> type
;
151 struct is_string_literal
153 static no_t
helper(indirection_layer
);
154 static yes_t
helper(const char*);
158 struct is_string_literal
<false>
160 static no_t
helper(indirection_layer
);
164 namespace mpl
= boost::mpl
;
166 template <class T
, class Clone
>
167 void make_pointee_instance(lua_State
* L
, T
& x
, mpl::true_
, Clone
)
180 void make_pointee_instance(lua_State
* L
, T
& x
, mpl::false_
, mpl::true_
)
182 std::auto_ptr
<T
> ptr(new T(x
));
183 make_instance(L
, ptr
);
187 void make_pointee_instance(lua_State
* L
, T
& x
, mpl::false_
, mpl::false_
)
189 make_instance(L
, &x
);
192 template <class T
, class Clone
>
193 void make_pointee_instance(lua_State
* L
, T
& x
, Clone
)
195 make_pointee_instance(L
, x
, has_get_pointer
<T
>(), Clone());
198 // ********** pointer converter ***********
200 struct pointer_converter
202 typedef pointer_converter type
;
203 typedef mpl::false_ is_native
;
211 int const consumed_args(...)
217 void apply(lua_State
* L
, T
* ptr
)
225 if (luabind::get_back_reference(L
, ptr
))
228 make_instance(L
, ptr
);
232 T
* apply(lua_State
*, by_pointer
<T
>, int)
234 return static_cast<T
*>(result
);
238 int match(lua_State
* L
, by_pointer
<T
>, int index
)
240 if (lua_isnil(L
, index
)) return 0;
241 object_rep
* obj
= get_instance(L
, index
);
242 if (obj
== 0) return -1;
247 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
253 void converter_postcall(lua_State
*, by_pointer
<T
>, int)
257 // ******* value converter *******
259 struct value_converter
261 typedef value_converter type
;
262 typedef mpl::false_ is_native
;
264 int const consumed_args(...)
276 void apply(lua_State
* L
, T x
)
278 if (luabind::get_back_reference(L
, x
))
281 make_pointee_instance(L
, x
, mpl::true_());
285 T
apply(lua_State
*, by_value
<T
>, int)
287 return *static_cast<T
*>(result
);
291 int match(lua_State
* L
, by_value
<T
>, int index
)
293 // special case if we get nil in, try to match the holder type
294 if (lua_isnil(L
, index
))
297 object_rep
* obj
= get_instance(L
, index
);
298 if (obj
== 0) return -1;
300 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
306 void converter_postcall(lua_State
*, T
, int) {}
309 // ******* const pointer converter *******
311 struct const_pointer_converter
313 typedef const_pointer_converter type
;
314 typedef mpl::false_ is_native
;
316 int const consumed_args(...)
321 const_pointer_converter()
328 void apply(lua_State
* L
, const T
* ptr
)
336 if (luabind::get_back_reference(L
, ptr
))
339 make_instance(L
, ptr
);
343 T
const* apply(lua_State
*, by_const_pointer
<T
>, int)
345 return static_cast<T
const*>(result
);
349 int match(lua_State
* L
, by_const_pointer
<T
>, int index
)
351 if (lua_isnil(L
, index
)) return 0;
352 object_rep
* obj
= get_instance(L
, index
);
353 if (obj
== 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
354 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
355 if (s
.second
>= 0 && !obj
->is_const())
362 void converter_postcall(lua_State
*, T
, int) {}
365 // ******* reference converter *******
367 struct ref_converter
: pointer_converter
369 typedef ref_converter type
;
370 typedef mpl::false_ is_native
;
372 int const consumed_args(...)
378 void apply(lua_State
* L
, T
& ref
)
380 if (luabind::get_back_reference(L
, ref
))
383 make_pointee_instance(L
, ref
, mpl::false_());
387 T
& apply(lua_State
* L
, by_reference
<T
>, int index
)
389 assert(!lua_isnil(L
, index
));
390 return *pointer_converter::apply(L
, by_pointer
<T
>(), index
);
394 int match(lua_State
* L
, by_reference
<T
>, int index
)
396 object_rep
* obj
= get_instance(L
, index
);
397 if (obj
== 0) return -1;
402 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
408 void converter_postcall(lua_State
*, T
, int) {}
411 // ******** const reference converter *********
413 struct const_ref_converter
415 typedef const_ref_converter type
;
416 typedef mpl::false_ is_native
;
418 int const consumed_args(...)
423 const_ref_converter()
430 void apply(lua_State
* L
, T
const& ref
)
432 if (luabind::get_back_reference(L
, ref
))
435 make_pointee_instance(L
, ref
, mpl::false_());
439 T
const& apply(lua_State
*, by_const_reference
<T
>, int)
441 return *static_cast<T
*>(result
);
445 int match(lua_State
* L
, by_const_reference
<T
>, int index
)
447 object_rep
* obj
= get_instance(L
, index
);
448 if (obj
== 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
450 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
451 if (s
.second
>= 0 && !obj
->is_const())
458 void converter_postcall(lua_State
*, by_const_reference
<T
>, int)
463 // ****** enum converter ********
465 struct enum_converter
467 typedef enum_converter type
;
468 typedef mpl::true_ is_native
;
470 int const consumed_args(...)
475 void apply(lua_State
* L
, int val
)
477 lua_pushnumber(L
, val
);
481 T
apply(lua_State
* L
, by_value
<T
>, int index
)
483 return static_cast<T
>(static_cast<int>(lua_tonumber(L
, index
)));
487 static int match(lua_State
* L
, by_value
<T
>, int index
)
489 if (lua_isnumber(L
, index
)) return 0; else return -1;
493 T
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
495 return static_cast<T
>(static_cast<int>(lua_tonumber(L
, index
)));
499 static int match(lua_State
* L
, by_const_reference
<T
>, int index
)
501 if (lua_isnumber(L
, index
)) return 0; else return -1;
505 void converter_postcall(lua_State
*, T
, int) {}
509 struct value_wrapper_converter
511 typedef value_wrapper_converter
<U
> type
;
512 typedef mpl::true_ is_native
;
514 int const consumed_args(...)
520 T
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
522 return T(from_stack(L
, index
));
526 T
apply(lua_State
* L
, by_value
<T
>, int index
)
528 return apply(L
, by_const_reference
<T
>(), index
);
532 static int match(lua_State
* L
, by_const_reference
<T
>, int index
)
534 return value_wrapper_traits
<T
>::check(L
, index
)
535 ? (std::numeric_limits
<int>::max
)() / LUABIND_MAX_ARITY
540 static int match(lua_State
* L
, by_value
<T
>, int index
)
542 return match(L
, by_const_reference
<T
>(), index
);
545 void converter_postcall(...) {}
548 void apply(lua_State
* interpreter
, T
const& value_wrapper
)
550 value_wrapper_traits
<T
>::unwrap(interpreter
, value_wrapper
);
555 struct default_converter_generator
557 is_value_wrapper_arg
<T
>
558 , value_wrapper_converter
<T
>
560 boost::is_enum
<typename
boost::remove_reference
<T
>::type
>
563 is_nonconst_pointer
<T
>
567 , const_pointer_converter
569 is_nonconst_reference
<T
>
572 is_const_reference
<T
>
573 , const_ref_converter
583 } // namespace detail
585 // *********** default_policy *****************
588 struct default_converter
589 : detail::default_converter_generator
<T
>::type
592 template <class T
, class Derived
= default_converter
<T
> >
593 struct native_converter_base
595 typedef boost::mpl::true_ is_native
;
597 int const consumed_args(...)
603 void converter_postcall(lua_State
*, U
const&, int)
606 int match(lua_State
* L
, detail::by_value
<T
>, int index
)
608 return derived().compute_score(L
, index
);
611 int match(lua_State
* L
, detail::by_value
<T
const>, int index
)
613 return derived().compute_score(L
, index
);
616 int match(lua_State
* L
, detail::by_const_reference
<T
>, int index
)
618 return derived().compute_score(L
, index
);
621 T
apply(lua_State
* L
, detail::by_value
<T
>, int index
)
623 return derived().from(L
, index
);
626 T
apply(lua_State
* L
, detail::by_value
<T
const>, int index
)
628 return derived().from(L
, index
);
631 T
apply(lua_State
* L
, detail::by_const_reference
<T
>, int index
)
633 return derived().from(L
, index
);
636 void apply(lua_State
* L
, T
const& value
)
638 derived().to(L
, value
);
643 return static_cast<Derived
&>(*this);
648 lua_Integer
as_lua_integer(T v
)
650 return static_cast<lua_Integer
>(v
);
654 lua_Number
as_lua_number(T v
)
656 return static_cast<lua_Number
>(v
);
659 # define LUABIND_NUMBER_CONVERTER(type, kind) \
661 struct default_converter<type> \
662 : native_converter_base<type> \
664 int compute_score(lua_State* L, int index) \
666 return lua_type(L, index) == LUA_TNUMBER ? 0 : -1; \
669 type from(lua_State* L, int index) \
671 return static_cast<type>(BOOST_PP_CAT(lua_to, kind)(L, index)); \
674 void to(lua_State* L, type const& value) \
676 BOOST_PP_CAT(lua_push, kind)(L, BOOST_PP_CAT(as_lua_, kind)(value)); \
681 struct default_converter<type const> \
682 : default_converter<type> \
686 struct default_converter<type const&> \
687 : default_converter<type> \
690 LUABIND_NUMBER_CONVERTER(char, integer
)
691 LUABIND_NUMBER_CONVERTER(signed char, integer
)
692 LUABIND_NUMBER_CONVERTER(unsigned char, integer
)
693 LUABIND_NUMBER_CONVERTER(signed short, integer
)
694 LUABIND_NUMBER_CONVERTER(unsigned short, integer
)
695 LUABIND_NUMBER_CONVERTER(signed int, integer
)
697 LUABIND_NUMBER_CONVERTER(unsigned int, number
)
698 LUABIND_NUMBER_CONVERTER(unsigned long, number
)
700 LUABIND_NUMBER_CONVERTER(signed long, integer
)
701 LUABIND_NUMBER_CONVERTER(float, number
)
702 LUABIND_NUMBER_CONVERTER(double, number
)
703 LUABIND_NUMBER_CONVERTER(long double, number
)
705 # undef LUABIND_NUMBER_CONVERTER
708 struct default_converter
<bool>
709 : native_converter_base
<bool>
711 static int compute_score(lua_State
* L
, int index
)
713 return lua_type(L
, index
) == LUA_TBOOLEAN
? 0 : -1;
716 bool from(lua_State
* L
, int index
)
718 return lua_toboolean(L
, index
) == 1;
721 void to(lua_State
* L
, bool value
)
723 lua_pushboolean(L
, value
);
728 struct default_converter
<bool const>
729 : default_converter
<bool>
733 struct default_converter
<bool const&>
734 : default_converter
<bool>
738 struct default_converter
<std::string
>
739 : native_converter_base
<std::string
>
741 static int compute_score(lua_State
* L
, int index
)
743 return lua_type(L
, index
) == LUA_TSTRING
? 0 : -1;
746 std::string
from(lua_State
* L
, int index
)
748 return std::string(lua_tostring(L
, index
), lua_strlen(L
, index
));
751 void to(lua_State
* L
, std::string
const& value
)
753 lua_pushlstring(L
, value
.data(), value
.size());
758 struct default_converter
<std::string
const>
759 : default_converter
<std::string
>
763 struct default_converter
<std::string
const&>
764 : default_converter
<std::string
>
768 struct default_converter
<char const*>
770 typedef boost::mpl::true_ is_native
;
772 int const consumed_args(...)
778 static int match(lua_State
* L
, U
, int index
)
780 int type
= lua_type(L
, index
);
781 return (type
== LUA_TSTRING
|| type
== LUA_TNIL
) ? 0 : -1;
785 char const* apply(lua_State
* L
, U
, int index
)
787 return lua_tostring(L
, index
);
790 void apply(lua_State
* L
, char const* str
)
792 lua_pushstring(L
, str
);
796 void converter_postcall(lua_State
*, U
, int)
801 struct default_converter
<const char* const>
802 : default_converter
<char const*>
806 struct default_converter
<char*>
807 : default_converter
<char const*>
810 template <std::size_t N
>
811 struct default_converter
<char const[N
]>
812 : default_converter
<char const*>
815 template <std::size_t N
>
816 struct default_converter
<char[N
]>
817 : default_converter
<char const*>
821 struct default_converter
<lua_State
*>
823 int const consumed_args(...)
829 lua_State
* apply(lua_State
* L
, U
, int)
835 static int match(lua_State
*, U
, int)
841 void converter_postcall(lua_State
*, U
, int) {}
847 struct default_policy
: converter_policy_tag
849 BOOST_STATIC_CONSTANT(bool, has_arg
= true);
852 static void precall(lua_State
*, T
, int) {}
854 template<class T
, class Direction
>
857 typedef default_converter
<T
> type
;
863 : default_converter
<T
>::is_native
866 // ============== new policy system =================
868 template<int, class> struct find_conversion_policy
;
870 template<bool IsConverter
= false>
871 struct find_conversion_impl
873 template<int N
, class Policies
>
876 typedef typename find_conversion_policy
<N
, typename
Policies::tail
>::type type
;
881 struct find_conversion_impl
<true>
883 template<int N
, class Policies
>
886 typedef typename
Policies::head head
;
887 typedef typename
Policies::tail tail
;
889 BOOST_STATIC_CONSTANT(bool, found
= (N
== head::index
));
892 boost::mpl::if_c
<found
894 , typename find_conversion_policy
<N
, tail
>::type
899 template<class Policies
>
900 struct find_conversion_impl2
904 : find_conversion_impl
<
905 boost::is_base_and_derived
<conversion_policy_base
, typename
Policies::head
>::value
906 >::template apply
<N
, Policies
>
912 struct find_conversion_impl2
<detail::null_type
>
917 typedef default_policy type
;
921 template<int N
, class Policies
>
922 struct find_conversion_policy
: find_conversion_impl2
<Policies
>::template apply
<N
>
927 struct policy_list_postcall
929 typedef typename
List::head head
;
930 typedef typename
List::tail tail
;
932 static void apply(lua_State
* L
, const index_map
& i
)
934 head::postcall(L
, i
);
935 policy_list_postcall
<tail
>::apply(L
, i
);
940 struct policy_list_postcall
<detail::null_type
>
942 static void apply(lua_State
*, const index_map
&) {}
945 // ==================================================
947 // ************** precall and postcall on policy_cons *********************
951 struct policy_precall
953 typedef typename
List::head head
;
954 typedef typename
List::tail tail
;
956 static void apply(lua_State
* L
, int index
)
958 head::precall(L
, index
);
959 policy_precall
<tail
>::apply(L
, index
);
964 struct policy_precall
<detail::null_type
>
966 static void apply(lua_State
*, int) {}
970 struct policy_postcall
972 typedef typename
List::head head
;
973 typedef typename
List::tail tail
;
975 static void apply(lua_State
* L
, int index
)
977 head::postcall(L
, index
);
978 policy_postcall
<tail
>::apply(L
, index
);
983 struct policy_postcall
<detail::null_type
>
985 static void apply(lua_State
*, int) {}
988 template <class Policies
, class Sought
>
991 boost::is_same
<typename
Policies::head
, Sought
>
993 , has_policy
<typename
Policies::tail
, Sought
>
997 template <class Sought
>
998 struct has_policy
<null_type
, Sought
>
1002 }} // namespace luabind::detail
1005 namespace luabind
{ namespace
1007 #if defined(__GNUC__) && ( \
1008 (BOOST_VERSION < 103500) \
1009 || (BOOST_VERSION < 103900 && (__GNUC__ * 100 + __GNUC_MINOR__ <= 400)) \
1010 || (__GNUC__ * 100 + __GNUC_MINOR__ < 400))
1011 static inline boost::arg
<0> return_value()
1013 return boost::arg
<0>();
1016 static inline boost::arg
<0> result()
1018 return boost::arg
<0>();
1020 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>(*)()
1021 #elif defined(BOOST_MSVC) || defined(__MWERKS__) \
1022 || (BOOST_VERSION >= 103900 && defined(__GNUC__) \
1023 && (__GNUC__ * 100 + __GNUC_MINOR__ == 400))
1024 static boost::arg
<0> return_value
;
1025 static boost::arg
<0> result
;
1026 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1028 boost::arg
<0> return_value
;
1029 boost::arg
<0> result
;
1030 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1034 #endif // LUABIND_POLICY_HPP_INCLUDED