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/limits.hpp>
46 #include <boost/tuple/tuple.hpp>
47 #include <boost/version.hpp>
49 #include <luabind/detail/class_registry.hpp>
50 #include <luabind/detail/primitives.hpp>
51 #include <luabind/detail/object_rep.hpp>
52 #include <luabind/detail/typetraits.hpp>
53 #include <luabind/detail/class_cache.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
100 LUABIND_API
int implicit_cast(const class_rep
* crep
, type_id
const&, int& pointer_offset
);
103 // template<class T> class functor;
107 namespace luabind
{ namespace detail
109 template<class H
, class 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 policy_cons
<U
, policy_cons
<H
,T
> > operator|(policy_cons
<U
,detail::null_type
>)
130 return policy_cons
<U
, policy_cons
<H
,T
> >();
134 struct indirection_layer
137 indirection_layer(const T
&);
140 yes_t
is_policy_cons_test(const null_type
&);
141 template<class H
, class T
>
142 yes_t
is_policy_cons_test(const policy_cons
<H
,T
>&);
143 no_t
is_policy_cons_test(...);
146 struct is_policy_cons
150 BOOST_STATIC_CONSTANT(bool, value
=
151 sizeof(is_policy_cons_test(t
)) == sizeof(yes_t
));
153 typedef boost::mpl::bool_
<value
> type
;
157 struct is_string_literal
159 static no_t
helper(indirection_layer
);
160 static yes_t
helper(const char*);
164 struct is_string_literal
<false>
166 static no_t
helper(indirection_layer
);
170 namespace mpl
= boost::mpl
;
172 template <class T
, class Clone
>
173 void make_pointee_instance(lua_State
* L
, T
& x
, mpl::true_
, Clone
)
186 void make_pointee_instance(lua_State
* L
, T
& x
, mpl::false_
, mpl::true_
)
188 std::auto_ptr
<T
> ptr(new T(x
));
189 make_instance(L
, ptr
);
193 void make_pointee_instance(lua_State
* L
, T
& x
, mpl::false_
, mpl::false_
)
195 make_instance(L
, &x
);
198 template <class T
, class Clone
>
199 void make_pointee_instance(lua_State
* L
, T
& x
, Clone
)
201 make_pointee_instance(L
, x
, has_get_pointer
<T
>(), Clone());
204 // ********** pointer converter ***********
206 struct pointer_converter
208 typedef pointer_converter type
;
209 typedef mpl::false_ is_native
;
217 int const consumed_args(...)
223 void apply(lua_State
* L
, T
* ptr
)
231 if (luabind::get_back_reference(L
, ptr
))
234 make_instance(L
, ptr
);
238 T
* apply(lua_State
*, by_pointer
<T
>, int)
240 return static_cast<T
*>(result
);
244 int match(lua_State
* L
, by_pointer
<T
>, int index
)
246 if (lua_isnil(L
, index
)) return 0;
247 object_rep
* obj
= get_instance(L
, index
);
248 if (obj
== 0) return -1;
253 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
259 void converter_postcall(lua_State
*, by_pointer
<T
>, int)
263 // ******* value converter *******
265 struct value_converter
267 typedef value_converter type
;
268 typedef mpl::false_ is_native
;
270 int const consumed_args(...)
282 void apply(lua_State
* L
, T x
)
284 if (luabind::get_back_reference(L
, x
))
287 make_pointee_instance(L
, x
, mpl::true_());
291 T
apply(lua_State
*, by_value
<T
>, int)
293 return *static_cast<T
*>(result
);
297 int match(lua_State
* L
, by_value
<T
>, int index
)
299 // special case if we get nil in, try to match the holder type
300 if (lua_isnil(L
, index
))
303 object_rep
* obj
= get_instance(L
, index
);
304 if (obj
== 0) return -1;
306 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
312 void converter_postcall(lua_State
*, T
, int) {}
315 // ******* const pointer converter *******
317 struct const_pointer_converter
319 typedef const_pointer_converter type
;
320 typedef mpl::false_ is_native
;
322 int const consumed_args(...)
327 const_pointer_converter()
334 void apply(lua_State
* L
, const T
* ptr
)
342 if (luabind::get_back_reference(L
, ptr
))
345 make_instance(L
, ptr
);
349 T
const* apply(lua_State
*, by_const_pointer
<T
>, int)
351 return static_cast<T
const*>(result
);
355 int match(lua_State
* L
, by_const_pointer
<T
>, int index
)
357 if (lua_isnil(L
, index
)) return 0;
358 object_rep
* obj
= get_instance(L
, index
);
359 if (obj
== 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
360 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
361 if (s
.second
>= 0 && !obj
->is_const())
368 void converter_postcall(lua_State
*, T
, int) {}
371 // ******* reference converter *******
373 struct ref_converter
: pointer_converter
375 typedef ref_converter type
;
376 typedef mpl::false_ is_native
;
378 int const consumed_args(...)
384 void apply(lua_State
* L
, T
& ref
)
386 if (luabind::get_back_reference(L
, ref
))
389 make_pointee_instance(L
, ref
, mpl::false_());
393 T
& apply(lua_State
* L
, by_reference
<T
>, int index
)
395 assert(!lua_isnil(L
, index
));
396 return *pointer_converter::apply(L
, by_pointer
<T
>(), index
);
400 int match(lua_State
* L
, by_reference
<T
>, int index
)
402 if (lua_isnil(L
, index
)) return -1;
403 return pointer_converter::match(L
, by_pointer
<T
>(), index
);
407 void converter_postcall(lua_State
*, T
, int) {}
410 // ******** const reference converter *********
412 struct const_ref_converter
414 typedef const_ref_converter type
;
415 typedef mpl::false_ is_native
;
417 int const consumed_args(...)
422 const_ref_converter()
429 void apply(lua_State
* L
, T
const& ref
)
431 if (luabind::get_back_reference(L
, ref
))
434 make_pointee_instance(L
, ref
, mpl::false_());
438 T
const& apply(lua_State
*, by_const_reference
<T
>, int)
440 return *static_cast<T
*>(result
);
444 int match(lua_State
* L
, by_const_reference
<T
>, int index
)
446 object_rep
* obj
= get_instance(L
, index
);
447 if (obj
== 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
449 std::pair
<void*, int> s
= obj
->get_instance(registered_class
<T
>::id
);
450 if (s
.second
>= 0 && !obj
->is_const())
457 void converter_postcall(lua_State
*, by_const_reference
<T
>, int)
462 // ****** enum converter ********
464 struct enum_converter
466 typedef enum_converter type
;
467 typedef mpl::true_ is_native
;
469 int const consumed_args(...)
474 void apply(lua_State
* L
, int val
)
476 lua_pushnumber(L
, val
);
480 T
apply(lua_State
* L
, by_value
<T
>, int index
)
482 return static_cast<T
>(static_cast<int>(lua_tonumber(L
, index
)));
486 static int match(lua_State
* L
, by_value
<T
>, int index
)
488 if (lua_isnumber(L
, index
)) return 0; else return -1;
492 T
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
494 return static_cast<T
>(static_cast<int>(lua_tonumber(L
, index
)));
498 static int match(lua_State
* L
, by_const_reference
<T
>, int index
)
500 if (lua_isnumber(L
, index
)) return 0; else return -1;
504 void converter_postcall(lua_State
*, T
, int) {}
508 struct value_wrapper_converter
510 typedef value_wrapper_converter
<U
> type
;
511 typedef mpl::true_ is_native
;
513 int const consumed_args(...)
519 T
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
521 return T(from_stack(L
, index
));
525 T
apply(lua_State
* L
, by_value
<T
>, int index
)
527 return apply(L
, by_const_reference
<T
>(), index
);
531 static int match(lua_State
* L
, by_const_reference
<T
>, int index
)
533 return value_wrapper_traits
<T
>::check(L
, index
)
534 ? (std::numeric_limits
<int>::max
)() / LUABIND_MAX_ARITY
539 static int match(lua_State
* L
, by_value
<T
>, int index
)
541 return match(L
, by_const_reference
<T
>(), index
);
544 void converter_postcall(...) {}
547 void apply(lua_State
* interpreter
, T
const& value_wrapper
)
549 value_wrapper_traits
<T
>::unwrap(interpreter
, value_wrapper
);
554 struct default_converter_generator
556 is_value_wrapper_arg
<T
>
557 , value_wrapper_converter
<T
>
559 boost::is_enum
<typename
boost::remove_reference
<T
>::type
>
562 is_nonconst_pointer
<T
>
566 , const_pointer_converter
568 is_nonconst_reference
<T
>
571 is_const_reference
<T
>
572 , const_ref_converter
582 } // namespace detail
584 // *********** default_policy *****************
587 struct default_converter
588 : detail::default_converter_generator
<T
>::type
591 template <class T
, class Derived
= default_converter
<T
> >
592 struct native_converter_base
594 typedef boost::mpl::true_ is_native
;
596 int const consumed_args(...)
602 void converter_postcall(lua_State
*, U
const&, int)
605 int match(lua_State
* L
, detail::by_value
<T
>, int index
)
607 return derived().compute_score(L
, index
);
610 int match(lua_State
* L
, detail::by_value
<T
const>, int index
)
612 return derived().compute_score(L
, index
);
615 int match(lua_State
* L
, detail::by_const_reference
<T
>, int index
)
617 return derived().compute_score(L
, index
);
620 T
apply(lua_State
* L
, detail::by_value
<T
>, int index
)
622 return derived().from(L
, index
);
625 T
apply(lua_State
* L
, detail::by_value
<T
const>, int index
)
627 return derived().from(L
, index
);
630 T
apply(lua_State
* L
, detail::by_const_reference
<T
>, int index
)
632 return derived().from(L
, index
);
635 void apply(lua_State
* L
, T
const& value
)
637 derived().to(L
, value
);
642 return static_cast<Derived
&>(*this);
647 lua_Integer
as_lua_integer(T v
)
649 return static_cast<lua_Integer
>(v
);
653 lua_Number
as_lua_number(T v
)
655 return static_cast<lua_Number
>(v
);
658 # define LUABIND_NUMBER_CONVERTER(type, kind) \
660 struct default_converter<type> \
661 : native_converter_base<type> \
663 int compute_score(lua_State* L, int index) \
665 return lua_type(L, index) == LUA_TNUMBER ? 0 : -1; \
668 type from(lua_State* L, int index) \
670 return static_cast<type>(BOOST_PP_CAT(lua_to, kind)(L, index)); \
673 void to(lua_State* L, type const& value) \
675 BOOST_PP_CAT(lua_push, kind)(L, BOOST_PP_CAT(as_lua_, kind)(value)); \
680 struct default_converter<type const> \
681 : default_converter<type> \
685 struct default_converter<type const&> \
686 : default_converter<type> \
689 LUABIND_NUMBER_CONVERTER(char, integer
)
690 LUABIND_NUMBER_CONVERTER(signed char, integer
)
691 LUABIND_NUMBER_CONVERTER(unsigned char, integer
)
692 LUABIND_NUMBER_CONVERTER(signed short, integer
)
693 LUABIND_NUMBER_CONVERTER(unsigned short, integer
)
694 LUABIND_NUMBER_CONVERTER(signed int, integer
)
696 LUABIND_NUMBER_CONVERTER(unsigned int, number
)
697 LUABIND_NUMBER_CONVERTER(unsigned long, number
)
699 LUABIND_NUMBER_CONVERTER(signed long, integer
)
700 LUABIND_NUMBER_CONVERTER(float, number
)
701 LUABIND_NUMBER_CONVERTER(double, number
)
702 LUABIND_NUMBER_CONVERTER(long double, number
)
704 # undef LUABIND_NUMBER_CONVERTER
707 struct default_converter
<bool>
708 : native_converter_base
<bool>
710 static int compute_score(lua_State
* L
, int index
)
712 return lua_type(L
, index
) == LUA_TBOOLEAN
? 0 : -1;
715 bool from(lua_State
* L
, int index
)
717 return lua_toboolean(L
, index
) == 1;
720 void to(lua_State
* L
, bool value
)
722 lua_pushboolean(L
, value
);
727 struct default_converter
<bool const>
728 : default_converter
<bool>
732 struct default_converter
<bool const&>
733 : default_converter
<bool>
737 struct default_converter
<std::string
>
738 : native_converter_base
<std::string
>
740 static int compute_score(lua_State
* L
, int index
)
742 return lua_type(L
, index
) == LUA_TSTRING
? 0 : -1;
745 std::string
from(lua_State
* L
, int index
)
747 return std::string(lua_tostring(L
, index
), lua_strlen(L
, index
));
750 void to(lua_State
* L
, std::string
const& value
)
752 lua_pushlstring(L
, value
.data(), value
.size());
757 struct default_converter
<std::string
const>
758 : default_converter
<std::string
>
762 struct default_converter
<std::string
const&>
763 : default_converter
<std::string
>
767 struct default_converter
<char const*>
769 typedef boost::mpl::true_ is_native
;
771 int const consumed_args(...)
777 static int match(lua_State
* L
, U
, int index
)
779 int type
= lua_type(L
, index
);
780 return (type
== LUA_TSTRING
|| type
== LUA_TNIL
) ? 0 : -1;
784 char const* apply(lua_State
* L
, U
, int index
)
786 return lua_tostring(L
, index
);
789 void apply(lua_State
* L
, char const* str
)
791 lua_pushstring(L
, str
);
795 void converter_postcall(lua_State
*, U
, int)
800 struct default_converter
<const char* const>
801 : default_converter
<char const*>
805 struct default_converter
<char*>
806 : default_converter
<char const*>
809 template <std::size_t N
>
810 struct default_converter
<char const[N
]>
811 : default_converter
<char const*>
814 template <std::size_t N
>
815 struct default_converter
<char[N
]>
816 : default_converter
<char const*>
820 struct default_converter
<lua_State
*>
822 int const consumed_args(...)
828 lua_State
* apply(lua_State
* L
, U
, int)
834 static int match(lua_State
*, U
, int)
840 void converter_postcall(lua_State
*, U
, int) {}
846 struct default_policy
: converter_policy_tag
848 BOOST_STATIC_CONSTANT(bool, has_arg
= true);
851 static void precall(lua_State
*, T
, int) {}
853 template<class T
, class Direction
>
856 typedef default_converter
<T
> type
;
862 : default_converter
<T
>::is_native
865 // ============== new policy system =================
867 template<int, class> struct find_conversion_policy
;
869 template<bool IsConverter
= false>
870 struct find_conversion_impl
872 template<int N
, class Policies
>
875 typedef typename find_conversion_policy
<N
, typename
Policies::tail
>::type type
;
880 struct find_conversion_impl
<true>
882 template<int N
, class Policies
>
885 typedef typename
Policies::head head
;
886 typedef typename
Policies::tail tail
;
888 BOOST_STATIC_CONSTANT(bool, found
= (N
== head::index
));
891 boost::mpl::if_c
<found
893 , typename find_conversion_policy
<N
, tail
>::type
898 template<class Policies
>
899 struct find_conversion_impl2
903 : find_conversion_impl
<
904 boost::is_base_and_derived
<conversion_policy_base
, typename
Policies::head
>::value
905 >::template apply
<N
, Policies
>
911 struct find_conversion_impl2
<detail::null_type
>
916 typedef default_policy type
;
920 template<int N
, class Policies
>
921 struct find_conversion_policy
: find_conversion_impl2
<Policies
>::template apply
<N
>
926 struct policy_list_postcall
928 typedef typename
List::head head
;
929 typedef typename
List::tail tail
;
931 static void apply(lua_State
* L
, const index_map
& i
)
933 head::postcall(L
, i
);
934 policy_list_postcall
<tail
>::apply(L
, i
);
939 struct policy_list_postcall
<detail::null_type
>
941 static void apply(lua_State
*, const index_map
&) {}
944 // ==================================================
946 // ************** precall and postcall on policy_cons *********************
950 struct policy_precall
952 typedef typename
List::head head
;
953 typedef typename
List::tail tail
;
955 static void apply(lua_State
* L
, int index
)
957 head::precall(L
, index
);
958 policy_precall
<tail
>::apply(L
, index
);
963 struct policy_precall
<detail::null_type
>
965 static void apply(lua_State
*, int) {}
969 struct policy_postcall
971 typedef typename
List::head head
;
972 typedef typename
List::tail tail
;
974 static void apply(lua_State
* L
, int index
)
976 head::postcall(L
, index
);
977 policy_postcall
<tail
>::apply(L
, index
);
982 struct policy_postcall
<detail::null_type
>
984 static void apply(lua_State
*, int) {}
987 }} // namespace luabind::detail
990 namespace luabind
{ namespace
992 #if defined(__GNUC__) && \
993 (__GNUC__ * 100 + __GNUC_MINOR__ < 400 || BOOST_VERSION <= 103401)
994 static inline boost::arg
<0> return_value()
996 return boost::arg
<0>();
999 static inline boost::arg
<0> result()
1001 return boost::arg
<0>();
1003 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>(*)()
1004 #elif defined(BOOST_MSVC) || defined(__MWERKS__)
1005 static boost::arg
<0> return_value
;
1006 static boost::arg
<0> result
;
1007 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1009 boost::arg
<0> return_value
;
1010 boost::arg
<0> result
;
1011 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1015 #endif // LUABIND_POLICY_HPP_INCLUDED