Remove old unused files accidentally left around.
[luabind.git] / luabind / detail / policy.hpp
blob7d1c43ea1a008d08b2c16eb4ac21fa6a447705aa
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>
29 #include <typeinfo>
30 #include <string>
31 #include <memory>
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>
69 namespace luabind
71 namespace detail
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);
83 class index_map
85 public:
86 index_map(const int* m): m_map(m) {}
88 int operator[](int index) const
90 return m_map[index];
93 private:
94 const int* m_map;
97 // template<class T> class functor;
98 class weak_ref;
101 namespace luabind { namespace detail
103 template<class H, class T>
104 struct policy_cons
106 typedef H head;
107 typedef T tail;
109 template<class U>
110 policy_cons<U, policy_cons<H,T> > operator,(policy_cons<U,detail::null_type>)
112 return policy_cons<U, policy_cons<H,T> >();
115 template<class U>
116 policy_cons<U, policy_cons<H,T> > operator+(policy_cons<U,detail::null_type>)
118 return policy_cons<U, policy_cons<H,T> >();
121 template<class U>
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
130 template<class T>
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(...);
139 template<class T>
140 struct is_policy_cons
142 static const T& t;
144 BOOST_STATIC_CONSTANT(bool, value =
145 sizeof(is_policy_cons_test(t)) == sizeof(yes_t));
147 typedef boost::mpl::bool_<value> type;
150 template<bool>
151 struct is_string_literal
153 static no_t helper(indirection_layer);
154 static yes_t helper(const char*);
157 template<>
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)
169 if (get_pointer(x))
171 make_instance(L, x);
173 else
175 lua_pushnil(L);
179 template <class T>
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);
186 template <class T>
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;
205 pointer_converter()
206 : result(0)
209 void* result;
211 int const consumed_args(...)
213 return 1;
216 template<class T>
217 void apply(lua_State* L, T* ptr)
219 if (ptr == 0)
221 lua_pushnil(L);
222 return;
225 if (luabind::get_back_reference(L, ptr))
226 return;
228 make_instance(L, ptr);
231 template<class T>
232 T* apply(lua_State*, by_pointer<T>, int)
234 return static_cast<T*>(result);
237 template<class T>
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;
244 if (obj->is_const())
245 return -1;
247 std::pair<void*, int> s = obj->get_instance(registered_class<T>::id);
248 result = s.first;
249 return s.second;
252 template<class T>
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(...)
266 return 1;
269 value_converter()
270 : result(0)
273 void* result;
275 template<class T>
276 void apply(lua_State* L, T x)
278 if (luabind::get_back_reference(L, x))
279 return;
281 make_pointee_instance(L, x, mpl::true_());
284 template<class T>
285 T apply(lua_State*, by_value<T>, int)
287 return *static_cast<T*>(result);
290 template<class T>
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))
295 return -1;
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);
301 result = s.first;
302 return s.second;
305 template<class T>
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(...)
318 return 1;
321 const_pointer_converter()
322 : result(0)
325 void* result;
327 template<class T>
328 void apply(lua_State* L, const T* ptr)
330 if (ptr == 0)
332 lua_pushnil(L);
333 return;
336 if (luabind::get_back_reference(L, ptr))
337 return;
339 make_instance(L, ptr);
342 template<class T>
343 T const* apply(lua_State*, by_const_pointer<T>, int)
345 return static_cast<T const*>(result);
348 template<class T>
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())
356 s.second += 10;
357 result = s.first;
358 return s.second;
361 template<class T>
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(...)
374 return 1;
377 template<class T>
378 void apply(lua_State* L, T& ref)
380 if (luabind::get_back_reference(L, ref))
381 return;
383 make_pointee_instance(L, ref, mpl::false_());
386 template<class T>
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);
393 template<class T>
394 int match(lua_State* L, by_reference<T>, int index)
396 if (lua_isnil(L, index)) return -1;
397 return pointer_converter::match(L, by_pointer<T>(), index);
400 template<class T>
401 void converter_postcall(lua_State*, T, int) {}
404 // ******** const reference converter *********
406 struct const_ref_converter
408 typedef const_ref_converter type;
409 typedef mpl::false_ is_native;
411 int const consumed_args(...)
413 return 1;
416 const_ref_converter()
417 : result(0)
420 void* result;
422 template<class T>
423 void apply(lua_State* L, T const& ref)
425 if (luabind::get_back_reference(L, ref))
426 return;
428 make_pointee_instance(L, ref, mpl::false_());
431 template<class T>
432 T const& apply(lua_State*, by_const_reference<T>, int)
434 return *static_cast<T*>(result);
437 template<class T>
438 int match(lua_State* L, by_const_reference<T>, int index)
440 object_rep* obj = get_instance(L, index);
441 if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
443 std::pair<void*, int> s = obj->get_instance(registered_class<T>::id);
444 if (s.second >= 0 && !obj->is_const())
445 s.second += 10;
446 result = s.first;
447 return s.second;
450 template<class T>
451 void converter_postcall(lua_State*, by_const_reference<T>, int)
456 // ****** enum converter ********
458 struct enum_converter
460 typedef enum_converter type;
461 typedef mpl::true_ is_native;
463 int const consumed_args(...)
465 return 1;
468 void apply(lua_State* L, int val)
470 lua_pushnumber(L, val);
473 template<class T>
474 T apply(lua_State* L, by_value<T>, int index)
476 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
479 template<class T>
480 static int match(lua_State* L, by_value<T>, int index)
482 if (lua_isnumber(L, index)) return 0; else return -1;
485 template<class T>
486 T apply(lua_State* L, by_const_reference<T>, int index)
488 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
491 template<class T>
492 static int match(lua_State* L, by_const_reference<T>, int index)
494 if (lua_isnumber(L, index)) return 0; else return -1;
497 template<class T>
498 void converter_postcall(lua_State*, T, int) {}
501 template <class U>
502 struct value_wrapper_converter
504 typedef value_wrapper_converter<U> type;
505 typedef mpl::true_ is_native;
507 int const consumed_args(...)
509 return 1;
512 template<class T>
513 T apply(lua_State* L, by_const_reference<T>, int index)
515 return T(from_stack(L, index));
518 template<class T>
519 T apply(lua_State* L, by_value<T>, int index)
521 return apply(L, by_const_reference<T>(), index);
524 template<class T>
525 static int match(lua_State* L, by_const_reference<T>, int index)
527 return value_wrapper_traits<T>::check(L, index)
528 ? (std::numeric_limits<int>::max)() / LUABIND_MAX_ARITY
529 : -1;
532 template<class T>
533 static int match(lua_State* L, by_value<T>, int index)
535 return match(L, by_const_reference<T>(), index);
538 void converter_postcall(...) {}
540 template<class T>
541 void apply(lua_State* interpreter, T const& value_wrapper)
543 value_wrapper_traits<T>::unwrap(interpreter, value_wrapper);
547 template <class T>
548 struct default_converter_generator
549 : mpl::eval_if<
550 is_value_wrapper_arg<T>
551 , value_wrapper_converter<T>
552 , mpl::eval_if<
553 boost::is_enum<typename boost::remove_reference<T>::type>
554 , enum_converter
555 , mpl::eval_if<
556 is_nonconst_pointer<T>
557 , pointer_converter
558 , mpl::eval_if<
559 is_const_pointer<T>
560 , const_pointer_converter
561 , mpl::eval_if<
562 is_nonconst_reference<T>
563 , ref_converter
564 , mpl::eval_if<
565 is_const_reference<T>
566 , const_ref_converter
567 , value_converter
576 } // namespace detail
578 // *********** default_policy *****************
580 template <class T>
581 struct default_converter
582 : detail::default_converter_generator<T>::type
585 template <class T, class Derived = default_converter<T> >
586 struct native_converter_base
588 typedef boost::mpl::true_ is_native;
590 int const consumed_args(...)
592 return 1;
595 template <class U>
596 void converter_postcall(lua_State*, U const&, int)
599 int match(lua_State* L, detail::by_value<T>, int index)
601 return derived().compute_score(L, index);
604 int match(lua_State* L, detail::by_value<T const>, int index)
606 return derived().compute_score(L, index);
609 int match(lua_State* L, detail::by_const_reference<T>, int index)
611 return derived().compute_score(L, index);
614 T apply(lua_State* L, detail::by_value<T>, int index)
616 return derived().from(L, index);
619 T apply(lua_State* L, detail::by_value<T const>, int index)
621 return derived().from(L, index);
624 T apply(lua_State* L, detail::by_const_reference<T>, int index)
626 return derived().from(L, index);
629 void apply(lua_State* L, T const& value)
631 derived().to(L, value);
634 Derived& derived()
636 return static_cast<Derived&>(*this);
640 template <class T>
641 lua_Integer as_lua_integer(T v)
643 return static_cast<lua_Integer>(v);
646 template <class T>
647 lua_Number as_lua_number(T v)
649 return static_cast<lua_Number>(v);
652 # define LUABIND_NUMBER_CONVERTER(type, kind) \
653 template <> \
654 struct default_converter<type> \
655 : native_converter_base<type> \
657 int compute_score(lua_State* L, int index) \
659 return lua_type(L, index) == LUA_TNUMBER ? 0 : -1; \
660 }; \
662 type from(lua_State* L, int index) \
664 return static_cast<type>(BOOST_PP_CAT(lua_to, kind)(L, index)); \
667 void to(lua_State* L, type const& value) \
669 BOOST_PP_CAT(lua_push, kind)(L, BOOST_PP_CAT(as_lua_, kind)(value)); \
671 }; \
673 template <> \
674 struct default_converter<type const> \
675 : default_converter<type> \
676 {}; \
678 template <> \
679 struct default_converter<type const&> \
680 : default_converter<type> \
683 LUABIND_NUMBER_CONVERTER(char, integer)
684 LUABIND_NUMBER_CONVERTER(signed char, integer)
685 LUABIND_NUMBER_CONVERTER(unsigned char, integer)
686 LUABIND_NUMBER_CONVERTER(signed short, integer)
687 LUABIND_NUMBER_CONVERTER(unsigned short, integer)
688 LUABIND_NUMBER_CONVERTER(signed int, integer)
690 LUABIND_NUMBER_CONVERTER(unsigned int, number)
691 LUABIND_NUMBER_CONVERTER(unsigned long, number)
693 LUABIND_NUMBER_CONVERTER(signed long, integer)
694 LUABIND_NUMBER_CONVERTER(float, number)
695 LUABIND_NUMBER_CONVERTER(double, number)
696 LUABIND_NUMBER_CONVERTER(long double, number)
698 # undef LUABIND_NUMBER_CONVERTER
700 template <>
701 struct default_converter<bool>
702 : native_converter_base<bool>
704 static int compute_score(lua_State* L, int index)
706 return lua_type(L, index) == LUA_TBOOLEAN ? 0 : -1;
709 bool from(lua_State* L, int index)
711 return lua_toboolean(L, index) == 1;
714 void to(lua_State* L, bool value)
716 lua_pushboolean(L, value);
720 template <>
721 struct default_converter<bool const>
722 : default_converter<bool>
725 template <>
726 struct default_converter<bool const&>
727 : default_converter<bool>
730 template <>
731 struct default_converter<std::string>
732 : native_converter_base<std::string>
734 static int compute_score(lua_State* L, int index)
736 return lua_type(L, index) == LUA_TSTRING ? 0 : -1;
739 std::string from(lua_State* L, int index)
741 return std::string(lua_tostring(L, index), lua_strlen(L, index));
744 void to(lua_State* L, std::string const& value)
746 lua_pushlstring(L, value.data(), value.size());
750 template <>
751 struct default_converter<std::string const>
752 : default_converter<std::string>
755 template <>
756 struct default_converter<std::string const&>
757 : default_converter<std::string>
760 template <>
761 struct default_converter<char const*>
763 typedef boost::mpl::true_ is_native;
765 int const consumed_args(...)
767 return 1;
770 template <class U>
771 static int match(lua_State* L, U, int index)
773 int type = lua_type(L, index);
774 return (type == LUA_TSTRING || type == LUA_TNIL) ? 0 : -1;
777 template <class U>
778 char const* apply(lua_State* L, U, int index)
780 return lua_tostring(L, index);
783 void apply(lua_State* L, char const* str)
785 lua_pushstring(L, str);
788 template <class U>
789 void converter_postcall(lua_State*, U, int)
793 template <>
794 struct default_converter<const char* const>
795 : default_converter<char const*>
798 template <>
799 struct default_converter<char*>
800 : default_converter<char const*>
803 template <std::size_t N>
804 struct default_converter<char const[N]>
805 : default_converter<char const*>
808 template <std::size_t N>
809 struct default_converter<char[N]>
810 : default_converter<char const*>
813 template <>
814 struct default_converter<lua_State*>
816 int const consumed_args(...)
818 return 0;
821 template <class U>
822 lua_State* apply(lua_State* L, U, int)
824 return L;
827 template <class U>
828 static int match(lua_State*, U, int)
830 return 0;
833 template <class U>
834 void converter_postcall(lua_State*, U, int) {}
837 namespace detail
840 struct default_policy : converter_policy_tag
842 BOOST_STATIC_CONSTANT(bool, has_arg = true);
844 template<class T>
845 static void precall(lua_State*, T, int) {}
847 template<class T, class Direction>
848 struct apply
850 typedef default_converter<T> type;
854 template<class T>
855 struct is_primitive
856 : default_converter<T>::is_native
859 // ============== new policy system =================
861 template<int, class> struct find_conversion_policy;
863 template<bool IsConverter = false>
864 struct find_conversion_impl
866 template<int N, class Policies>
867 struct apply
869 typedef typename find_conversion_policy<N, typename Policies::tail>::type type;
873 template<>
874 struct find_conversion_impl<true>
876 template<int N, class Policies>
877 struct apply
879 typedef typename Policies::head head;
880 typedef typename Policies::tail tail;
882 BOOST_STATIC_CONSTANT(bool, found = (N == head::index));
884 typedef typename
885 boost::mpl::if_c<found
886 , head
887 , typename find_conversion_policy<N, tail>::type
888 >::type type;
892 template<class Policies>
893 struct find_conversion_impl2
895 template<int N>
896 struct apply
897 : find_conversion_impl<
898 boost::is_base_and_derived<conversion_policy_base, typename Policies::head>::value
899 >::template apply<N, Policies>
904 template<>
905 struct find_conversion_impl2<detail::null_type>
907 template<int N>
908 struct apply
910 typedef default_policy type;
914 template<int N, class Policies>
915 struct find_conversion_policy : find_conversion_impl2<Policies>::template apply<N>
919 template<class List>
920 struct policy_list_postcall
922 typedef typename List::head head;
923 typedef typename List::tail tail;
925 static void apply(lua_State* L, const index_map& i)
927 head::postcall(L, i);
928 policy_list_postcall<tail>::apply(L, i);
932 template<>
933 struct policy_list_postcall<detail::null_type>
935 static void apply(lua_State*, const index_map&) {}
938 // ==================================================
940 // ************** precall and postcall on policy_cons *********************
943 template<class List>
944 struct policy_precall
946 typedef typename List::head head;
947 typedef typename List::tail tail;
949 static void apply(lua_State* L, int index)
951 head::precall(L, index);
952 policy_precall<tail>::apply(L, index);
956 template<>
957 struct policy_precall<detail::null_type>
959 static void apply(lua_State*, int) {}
962 template<class List>
963 struct policy_postcall
965 typedef typename List::head head;
966 typedef typename List::tail tail;
968 static void apply(lua_State* L, int index)
970 head::postcall(L, index);
971 policy_postcall<tail>::apply(L, index);
975 template<>
976 struct policy_postcall<detail::null_type>
978 static void apply(lua_State*, int) {}
981 }} // namespace luabind::detail
984 namespace luabind { namespace
986 #if defined(__GNUC__) && ( \
987 (BOOST_VERSION < 103500) \
988 || (BOOST_VERSION < 103900 && (__GNUC__ * 100 + __GNUC_MINOR__ <= 400)) \
989 || (__GNUC__ * 100 + __GNUC_MINOR__ < 400))
990 static inline boost::arg<0> return_value()
992 return boost::arg<0>();
995 static inline boost::arg<0> result()
997 return boost::arg<0>();
999 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>(*)()
1000 #elif defined(BOOST_MSVC) || defined(__MWERKS__) \
1001 || (BOOST_VERSION >= 103900 && defined(__GNUC__) \
1002 && (__GNUC__ * 100 + __GNUC_MINOR__ == 400))
1003 static boost::arg<0> return_value;
1004 static boost::arg<0> result;
1005 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1006 #else
1007 boost::arg<0> return_value;
1008 boost::arg<0> result;
1009 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1010 #endif
1013 #endif // LUABIND_POLICY_HPP_INCLUDED