Changed placeholder definitions to work on GCC3.X.
[luabind.git] / luabind / detail / policy.hpp
blobd29227d1c97ae119ce9517937f0830af898298ff
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>
32 #include <boost/type_traits/is_enum.hpp>
33 #include <boost/type_traits/is_array.hpp>
34 #include <boost/mpl/bool.hpp>
35 #include <boost/mpl/integral_c.hpp>
36 #include <boost/mpl/equal_to.hpp>
37 #include <boost/mpl/eval_if.hpp>
38 #include <boost/mpl/or.hpp>
39 #include <boost/type_traits/add_reference.hpp>
40 #include <boost/type_traits/is_pointer.hpp>
41 #include <boost/type_traits/is_base_and_derived.hpp>
42 #include <boost/bind/arg.hpp>
43 #include <boost/limits.hpp>
44 #include <boost/tuple/tuple.hpp>
45 #include <boost/version.hpp>
47 #include <luabind/detail/class_registry.hpp>
48 #include <luabind/detail/primitives.hpp>
49 #include <luabind/detail/object_rep.hpp>
50 #include <luabind/detail/typetraits.hpp>
51 #include <luabind/detail/class_cache.hpp>
52 #include <luabind/detail/debug.hpp>
53 #include <luabind/detail/class_rep.hpp>
55 #include <boost/type_traits/add_reference.hpp>
57 #include <luabind/detail/decorate_type.hpp>
58 #include <luabind/weak_ref.hpp>
59 #include <luabind/back_reference_fwd.hpp>
61 #include <luabind/value_wrapper.hpp>
62 #include <luabind/from_stack.hpp>
64 namespace luabind
66 namespace detail
68 struct conversion_policy_base {};
71 template<int N, bool HasArg = true>
72 struct conversion_policy : detail::conversion_policy_base
74 BOOST_STATIC_CONSTANT(int, index = N);
75 BOOST_STATIC_CONSTANT(bool, has_arg = HasArg);
78 class index_map
80 public:
81 index_map(const int* m): m_map(m) {}
83 int operator[](int index) const
85 return m_map[index];
88 private:
89 const int* m_map;
92 namespace converters
94 using luabind::detail::yes_t;
95 using luabind::detail::no_t;
96 using luabind::detail::by_value;
97 using luabind::detail::by_reference;
98 using luabind::detail::by_const_reference;
99 using luabind::detail::by_pointer;
100 using luabind::detail::by_const_pointer;
102 no_t is_user_defined(...);
105 namespace detail
107 template<class T>
108 struct is_user_defined
110 BOOST_STATIC_CONSTANT(bool, value =
111 sizeof(luabind::converters::is_user_defined(LUABIND_DECORATE_TYPE(T))) == sizeof(yes_t));
114 LUABIND_API int implicit_cast(const class_rep* crep, LUABIND_TYPE_INFO const&, int& pointer_offset);
117 // template<class T> class functor;
118 class weak_ref;
121 namespace luabind { namespace detail
123 template<class>
124 struct is_primitive;
126 template<class T>
127 yes_t is_lua_functor_test(const functor<T>&);
129 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
130 no_t is_lua_functor_test(...);
131 #else
132 template<class T>
133 no_t is_lua_functor_test(const T&);
134 #endif
136 template<class T>
137 struct is_lua_functor
139 static T t;
141 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_lua_functor_test(t)) == sizeof(yes_t));
144 template<class H, class T>
145 struct policy_cons
147 typedef H head;
148 typedef T tail;
150 template<class U>
151 policy_cons<U, policy_cons<H,T> > operator,(policy_cons<U,detail::null_type>)
153 return policy_cons<U, policy_cons<H,T> >();
156 template<class U>
157 policy_cons<U, policy_cons<H,T> > operator+(policy_cons<U,detail::null_type>)
159 return policy_cons<U, policy_cons<H,T> >();
162 template<class U>
163 policy_cons<U, policy_cons<H,T> > operator|(policy_cons<U,detail::null_type>)
165 return policy_cons<U, policy_cons<H,T> >();
169 struct indirection_layer
171 template<class T>
172 indirection_layer(const T&);
175 yes_t is_policy_cons_test(const null_type&);
176 template<class H, class T>
177 yes_t is_policy_cons_test(const policy_cons<H,T>&);
178 no_t is_policy_cons_test(...);
180 template<class T>
181 struct is_policy_cons
183 static const T& t;
185 BOOST_STATIC_CONSTANT(bool, value =
186 sizeof(is_policy_cons_test(t)) == sizeof(yes_t));
188 typedef boost::mpl::bool_<value> type;
191 template<bool>
192 struct is_string_literal
194 static no_t helper(indirection_layer);
195 static yes_t helper(const char*);
198 template<>
199 struct is_string_literal<false>
201 static no_t helper(indirection_layer);
205 template<class T>
206 struct is_primitive/*: boost::mpl::bool_c<false>*/
208 static T t;
210 BOOST_STATIC_CONSTANT(bool, value =
211 sizeof(is_string_literal<boost::is_array<T>::value>::helper(t)) == sizeof(yes_t));
214 #define LUABIND_INTEGER_TYPE(type) \
215 template<> struct is_primitive<type> : boost::mpl::true_ {}; \
216 template<> struct is_primitive<type const> : boost::mpl::true_ {}; \
217 template<> struct is_primitive<type const&> : boost::mpl::true_ {}; \
218 template<> struct is_primitive<unsigned type> : boost::mpl::true_ {}; \
219 template<> struct is_primitive<unsigned type const> : boost::mpl::true_ {}; \
220 template<> struct is_primitive<unsigned type const&> : boost::mpl::true_ {};
222 LUABIND_INTEGER_TYPE(char)
223 LUABIND_INTEGER_TYPE(short)
224 LUABIND_INTEGER_TYPE(int)
225 LUABIND_INTEGER_TYPE(long)
227 template<> struct is_primitive<signed char> : boost::mpl::true_ {}; \
228 template<> struct is_primitive<signed char const> : boost::mpl::true_ {}; \
229 template<> struct is_primitive<signed char const&> : boost::mpl::true_ {}; \
231 #undef LUABIND_INTEGER_TYPE
233 template<> struct is_primitive<luabind::weak_ref>: boost::mpl::bool_<true> {};
234 template<> struct is_primitive<const luabind::weak_ref>: boost::mpl::bool_<true> {};
235 template<> struct is_primitive<const luabind::weak_ref&>: boost::mpl::bool_<true> {};
237 template<> struct is_primitive<float>: boost::mpl::bool_<true> {};
238 template<> struct is_primitive<double>: boost::mpl::bool_<true> {};
239 template<> struct is_primitive<long double>: boost::mpl::bool_<true> {};
240 template<> struct is_primitive<char*>: boost::mpl::bool_<true> {};
241 template<> struct is_primitive<bool>: boost::mpl::bool_<true> {};
243 template<> struct is_primitive<const float>: boost::mpl::bool_<true> {};
244 template<> struct is_primitive<const double>: boost::mpl::bool_<true> {};
245 template<> struct is_primitive<const long double>: boost::mpl::bool_<true> {};
246 template<> struct is_primitive<const char*>: boost::mpl::bool_<true> {};
247 template<> struct is_primitive<const char* const>: boost::mpl::bool_<true> {};
248 template<> struct is_primitive<const bool>: boost::mpl::bool_<true> {};
250 // TODO: add more
251 template<> struct is_primitive<const float&>: boost::mpl::bool_<true> {};
252 template<> struct is_primitive<const double&>: boost::mpl::bool_<true> {};
253 template<> struct is_primitive<const long double&>: boost::mpl::bool_<true> {};
254 template<> struct is_primitive<const bool&>: boost::mpl::bool_<true> {};
256 template<> struct is_primitive<const std::string&>: boost::mpl::bool_<true> {};
257 template<> struct is_primitive<std::string>: boost::mpl::bool_<true> {};
258 template<> struct is_primitive<const std::string>: boost::mpl::bool_<true> {};
261 template<class Direction> struct primitive_converter;
263 template<>
264 struct primitive_converter<cpp_to_lua>
266 typedef boost::mpl::bool_<false> is_value_converter;
267 typedef primitive_converter type;
269 void apply(lua_State* L, int v) { lua_pushnumber(L, (lua_Number)v); }
270 void apply(lua_State* L, short v) { lua_pushnumber(L, (lua_Number)v); }
271 void apply(lua_State* L, char v) { lua_pushnumber(L, (lua_Number)v); }
272 void apply(lua_State* L, long v) { lua_pushnumber(L, (lua_Number)v); }
273 void apply(lua_State* L, unsigned int v) { lua_pushnumber(L, (lua_Number)v); }
274 void apply(lua_State* L, unsigned short v) { lua_pushnumber(L, (lua_Number)v); }
275 void apply(lua_State* L, unsigned char v) { lua_pushnumber(L, (lua_Number)v); }
276 void apply(lua_State* L, unsigned long v) { lua_pushnumber(L, (lua_Number)v); }
277 void apply(lua_State* L, float v) { lua_pushnumber(L, (lua_Number)v); }
278 void apply(lua_State* L, double v) { lua_pushnumber(L, (lua_Number)v); }
279 void apply(lua_State* L, long double v) { lua_pushnumber(L, (lua_Number)v); }
280 void apply(lua_State* L, const char* v)
282 if (v)
284 lua_pushstring(L, v);
286 else
288 lua_pushnil(L);
291 void apply(lua_State* L, const std::string& v)
292 { lua_pushlstring(L, v.data(), v.size()); }
293 void apply(lua_State* L, bool b) { lua_pushboolean(L, b); }
296 template<>
297 struct primitive_converter<lua_to_cpp>
299 typedef boost::mpl::bool_<false> is_value_converter;
300 typedef primitive_converter type;
302 #define PRIMITIVE_CONVERTER(prim) \
303 prim apply(lua_State* L, luabind::detail::by_const_reference<prim>, int index) { return apply(L, detail::by_value<prim>(), index); } \
304 prim apply(lua_State* L, luabind::detail::by_value<const prim>, int index) { return apply(L, detail::by_value<prim>(), index); } \
305 prim apply(lua_State* L, luabind::detail::by_value<prim>, int index)
307 #define PRIMITIVE_MATCHER(prim) \
308 static int match(lua_State* L, luabind::detail::by_const_reference<prim>, int index) { return match(L, detail::by_value<prim>(), index); } \
309 static int match(lua_State* L, luabind::detail::by_value<const prim>, int index) { return match(L, detail::by_value<prim>(), index); } \
310 static int match(lua_State* L, luabind::detail::by_value<prim>, int index)
312 PRIMITIVE_CONVERTER(bool) { return lua_toboolean(L, index) == 1; }
313 PRIMITIVE_MATCHER(bool) { if (lua_type(L, index) == LUA_TBOOLEAN) return 0; else return -1; }
315 PRIMITIVE_CONVERTER(int) { return static_cast<int>(lua_tonumber(L, index)); }
316 PRIMITIVE_MATCHER(int) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
318 PRIMITIVE_CONVERTER(unsigned int) { return static_cast<unsigned int>(lua_tonumber(L, index)); }
319 PRIMITIVE_MATCHER(unsigned int) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
321 PRIMITIVE_CONVERTER(char) { return static_cast<char>(lua_tonumber(L, index)); }
322 PRIMITIVE_MATCHER(char) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
324 PRIMITIVE_CONVERTER(signed char) { return static_cast<char>(lua_tonumber(L, index)); }
325 PRIMITIVE_MATCHER(signed char) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
327 PRIMITIVE_CONVERTER(unsigned char) { return static_cast<unsigned char>(lua_tonumber(L, index)); }
328 PRIMITIVE_MATCHER(unsigned char) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
330 PRIMITIVE_CONVERTER(short) { return static_cast<short>(lua_tonumber(L, index)); }
331 PRIMITIVE_MATCHER(short) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
333 PRIMITIVE_CONVERTER(unsigned short) { return static_cast<unsigned short>(lua_tonumber(L, index)); }
334 PRIMITIVE_MATCHER(unsigned short) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
336 PRIMITIVE_CONVERTER(long) { return static_cast<long>(lua_tonumber(L, index)); }
337 PRIMITIVE_MATCHER(long) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
339 PRIMITIVE_CONVERTER(unsigned long) { return static_cast<unsigned long>(lua_tonumber(L, index)); }
340 PRIMITIVE_MATCHER(unsigned long) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
342 PRIMITIVE_CONVERTER(float) { return static_cast<float>(lua_tonumber(L, index)); }
343 PRIMITIVE_MATCHER(float) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
345 PRIMITIVE_CONVERTER(double) { return static_cast<double>(lua_tonumber(L, index)); }
346 PRIMITIVE_MATCHER(double) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
348 PRIMITIVE_CONVERTER(lua_State*) { return lua_tothread(L, index); }
349 PRIMITIVE_MATCHER(lua_State*) { if (lua_type(L, index) == LUA_TTHREAD) return 0; else return -1; }
351 PRIMITIVE_CONVERTER(std::string)
352 { return std::string(lua_tostring(L, index), lua_strlen(L, index)); }
353 PRIMITIVE_MATCHER(std::string) { if (lua_type(L, index) == LUA_TSTRING) return 0; else return -1; }
355 PRIMITIVE_CONVERTER(luabind::weak_ref)
357 LUABIND_CHECK_STACK(L);
358 return luabind::weak_ref(L, index);
361 PRIMITIVE_MATCHER(luabind::weak_ref) { (void)index; (void)L; return (std::numeric_limits<int>::max)() - 1; }
363 const char* apply(lua_State* L, detail::by_const_pointer<char>, int index)
365 return static_cast<const char*>(lua_tostring(L, index));
368 const char* apply(lua_State* L, detail::by_const_pointer<const char>, int index)
370 return static_cast<const char*>(lua_tostring(L, index));
373 static int match(lua_State* L, by_const_pointer<char>, int index)
375 return lua_type(L, index) == LUA_TSTRING
376 || lua_isnil(L, index) ? 0 : -1;
378 static int match(lua_State* L, by_const_pointer<const char>, int index)
380 return lua_type(L, index) == LUA_TSTRING
381 || lua_isnil(L, index) ? 0 : -1;
384 template<class T>
385 void converter_postcall(lua_State*, T, int) {}
387 #undef PRIMITIVE_MATCHER
388 #undef PRIMITIVE_CONVERTER
393 // ********** user defined converter ***********
395 template<class Direction> struct user_defined_converter;
397 template<>
398 struct user_defined_converter<lua_to_cpp>
400 typedef boost::mpl::bool_<false> is_value_converter;
401 typedef user_defined_converter type;
403 template<class T>
404 T apply(lua_State* L, detail::by_value<T>, int index)
406 using namespace converters;
407 return convert_lua_to_cpp(L, detail::by_value<T>(), index);
410 template<class T>
411 T apply(lua_State* L, detail::by_reference<T>, int index)
413 using namespace converters;
414 return convert_lua_to_cpp(L, detail::by_reference<T>(), index);
417 template<class T>
418 T apply(lua_State* L, detail::by_const_reference<T>, int index)
420 using namespace converters;
421 return convert_lua_to_cpp(L, detail::by_const_reference<T>(), index);
424 template<class T>
425 T* apply(lua_State* L, detail::by_pointer<T>, int index)
427 using namespace converters;
428 return convert_lua_to_cpp(L, detail::by_pointer<T>(), index);
431 template<class T>
432 const T* apply(lua_State* L, detail::by_const_pointer<T>, int index)
434 using namespace converters;
435 return convert_lua_to_cpp(L, detail::by_pointer<T>(), index);
438 template<class T>
439 static int match(lua_State* L, T, int index)
441 using namespace converters;
442 return match_lua_to_cpp(L, T(), index);
445 template<class T>
446 void converter_postcall(lua_State*, T, int) {}
449 template<>
450 struct user_defined_converter<cpp_to_lua>
452 typedef boost::mpl::bool_<false> is_value_converter;
453 typedef user_defined_converter type;
455 template<class T>
456 void apply(lua_State* L, const T& v)
458 using namespace converters;
459 convert_cpp_to_lua(L, v);
463 // ********** pointer converter ***********
466 template<class Direction> struct pointer_converter;
468 template<>
469 struct pointer_converter<cpp_to_lua>
471 typedef boost::mpl::bool_<false> is_value_converter;
472 typedef pointer_converter type;
474 template<class T>
475 void apply(lua_State* L, T* ptr)
477 if (ptr == 0)
479 lua_pushnil(L);
480 return;
483 if (luabind::get_back_reference(L, ptr))
484 return;
486 class_rep* crep = get_class_rep<T>(L);
488 // if you get caught in this assert you are
489 // trying to use an unregistered type
490 assert(crep && "you are trying to use an unregistered type");
492 // create the struct to hold the object
493 void* obj = lua_newuserdata(L, sizeof(object_rep));
494 //new(obj) object_rep(ptr, crep, object_rep::owner, destructor_s<T>::apply);
495 new(obj) object_rep(ptr, crep, 0, 0);
497 // set the meta table
498 detail::getref(L, crep->metatable_ref());
499 lua_setmetatable(L, -2);
503 template<class T> struct make_pointer { typedef T* type; };
504 template<>
505 struct pointer_converter<lua_to_cpp>
507 typedef boost::mpl::bool_<false> is_value_converter;
508 typedef pointer_converter type;
510 // TODO: does the pointer converter need this?!
511 char target[32];
512 void (*destructor)(void *);
514 pointer_converter(): destructor(0) {}
516 template<class T>
517 typename make_pointer<T>::type apply(lua_State* L, by_pointer<T>, int index)
519 // preconditions:
520 // lua_isuserdata(L, index);
521 // getmetatable().__lua_class is true
522 // object_rep->flags() & object_rep::constant == 0
524 if (lua_isnil(L, index)) return 0;
526 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, index));
527 assert((obj != 0) && "internal error, please report"); // internal error
528 const class_rep* crep = obj->crep();
530 T* ptr = reinterpret_cast<T*>(crep->convert_to(LUABIND_TYPEID(T), obj, target));
532 if ((void*)ptr == (char*)target) destructor = detail::destruct_only_s<T>::apply;
533 assert(!destructor || sizeof(T) <= 32);
535 return ptr;
538 template<class T>
539 static int match(lua_State* L, by_pointer<T>, int index)
541 if (lua_isnil(L, index)) return 0;
542 object_rep* obj = is_class_object(L, index);
543 if (obj == 0) return -1;
544 // cannot cast a constant object to nonconst
545 if (obj->flags() & object_rep::constant) return -1;
547 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
548 return (obj->flags() & object_rep::constant)?-1:0;
549 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
550 return (obj->flags() & object_rep::constant)?0:-1;
552 int d;
553 return implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
556 ~pointer_converter()
558 if (destructor) destructor(target);
561 template<class T>
562 void converter_postcall(lua_State*, by_pointer<T>, int)
566 // ******* value converter *******
568 template<class Direction> struct value_converter;
570 template<>
571 struct value_converter<cpp_to_lua>
573 typedef boost::mpl::bool_<true> is_value_converter;
574 typedef value_converter type;
576 template<class T>
577 void apply(lua_State* L, const T& ref)
579 if (luabind::get_back_reference(L, ref))
580 return;
582 class_rep* crep = get_class_rep<T>(L);
584 // if you get caught in this assert you are
585 // trying to use an unregistered type
586 assert(crep && "you are trying to use an unregistered type");
588 void* obj_rep;
589 void* held;
591 boost::tie(obj_rep,held) = crep->allocate(L);
593 void* object_ptr;
594 void(*destructor)(void*);
595 destructor = crep->destructor();
596 int flags = object_rep::owner;
597 if (crep->has_holder())
599 new(held) T(ref);
600 object_ptr = held;
601 if (LUABIND_TYPE_INFO_EQUAL(LUABIND_TYPEID(T), crep->const_holder_type()))
603 flags |= object_rep::constant;
604 destructor = crep->const_holder_destructor();
607 else
609 object_ptr = new T(ref);
611 new(obj_rep) object_rep(object_ptr, crep, flags, destructor);
613 // set the meta table
614 detail::getref(L, crep->metatable_ref());
615 lua_setmetatable(L, -2);
620 template<class T> struct make_const_reference { typedef const T& type; };
622 template<class T>
623 struct destruct_guard
625 T* ptr;
626 bool dismiss;
627 destruct_guard(T* p): ptr(p), dismiss(false) {}
629 ~destruct_guard()
631 if (!dismiss)
632 ptr->~T();
636 template<>
637 struct value_converter<lua_to_cpp>
639 typedef boost::mpl::bool_<true> is_value_converter;
640 typedef value_converter type;
642 template<class T>
643 T apply(lua_State* L, by_value<T>, int index)
645 // preconditions:
646 // lua_isuserdata(L, index);
647 // getmetatable().__lua_class is true
648 // object_rep->flags() & object_rep::constant == 0
650 object_rep* obj = 0;
651 const class_rep* crep = 0;
653 // special case if we get nil in, try to convert the holder type
654 if (lua_isnil(L, index))
656 crep = get_class_rep<T>(L);
657 assert(crep);
659 else
661 obj = static_cast<object_rep*>(lua_touserdata(L, index));
662 assert((obj != 0) && "internal error, please report"); // internal error
663 crep = obj->crep();
665 assert(crep);
667 // TODO: align!
668 char target[sizeof(T)];
669 T* ptr = reinterpret_cast<T*>(crep->convert_to(LUABIND_TYPEID(T), obj, target));
671 destruct_guard<T> guard(ptr);
672 if ((void*)ptr != (void*)target) guard.dismiss = true;
674 return *ptr;
677 template<class T>
678 static int match(lua_State* L, by_value<T>, int index)
680 // special case if we get nil in, try to match the holder type
681 if (lua_isnil(L, index))
683 class_rep* crep = get_class_rep<T>(L);
684 if (crep == 0) return -1;
685 if ((LUABIND_TYPE_INFO_EQUAL(crep->holder_type(), LUABIND_TYPEID(T))))
686 return 0;
687 if ((LUABIND_TYPE_INFO_EQUAL(crep->const_holder_type(), LUABIND_TYPEID(T))))
688 return 0;
689 return -1;
692 object_rep* obj = is_class_object(L, index);
693 if (obj == 0) return -1;
694 int d;
696 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
697 return (obj->flags() & object_rep::constant)?-1:0;
698 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
699 return (obj->flags() & object_rep::constant)?0:1;
701 return implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
704 template<class T>
705 void converter_postcall(lua_State*, T, int) {}
708 // ******* const pointer converter *******
710 template<class Direction> struct const_pointer_converter;
712 template<>
713 struct const_pointer_converter<cpp_to_lua>
715 typedef boost::mpl::bool_<false> is_value_converter;
716 typedef const_pointer_converter type;
718 template<class T>
719 void apply(lua_State* L, const T* ptr)
721 if (ptr == 0)
723 lua_pushnil(L);
724 return;
727 if (luabind::get_back_reference(L, ptr))
728 return;
730 class_rep* crep = get_class_rep<T>(L);
732 // if you get caught in this assert you are
733 // trying to use an unregistered type
734 assert(crep && "you are trying to use an unregistered type");
736 // create the struct to hold the object
737 void* obj = lua_newuserdata(L, sizeof(object_rep));
738 assert(obj && "internal error, please report");
739 // we send 0 as destructor since we know it will never be called
740 new(obj) object_rep(const_cast<T*>(ptr), crep, object_rep::constant, 0);
742 // set the meta table
743 detail::getref(L, crep->metatable_ref());
744 lua_setmetatable(L, -2);
749 template<class T> struct make_const_pointer { typedef const T* type; };
750 template<>
751 struct const_pointer_converter<lua_to_cpp>
752 : private pointer_converter<lua_to_cpp>
754 typedef boost::mpl::bool_<false> is_value_converter;
755 typedef const_pointer_converter type;
757 template<class T>
758 typename make_const_pointer<T>::type apply(lua_State* L, by_const_pointer<T>, int index)
760 return pointer_converter<lua_to_cpp>::apply(L, by_pointer<T>(), index);
763 template<class T>
764 static int match(lua_State* L, by_const_pointer<T>, int index)
766 if (lua_isnil(L, index)) return 0;
767 object_rep* obj = is_class_object(L, index);
768 if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
770 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
771 return (obj->flags() & object_rep::constant)?-1:0;
772 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
773 return (obj->flags() & object_rep::constant)?0:1;
775 bool const_ = obj->flags() & object_rep::constant;
776 int d;
777 int points = implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
778 return points == -1 ? -1 : points + !const_;
781 template<class T>
782 void converter_postcall(lua_State* L, by_const_pointer<T>, int index)
784 pointer_converter<lua_to_cpp>::converter_postcall(L, by_pointer<T>(), index);
788 // ******* reference converter *******
790 template<class Direction> struct ref_converter;
792 template<>
793 struct ref_converter<cpp_to_lua>
795 typedef boost::mpl::bool_<false> is_value_converter;
796 typedef ref_converter type;
798 template<class T>
799 void apply(lua_State* L, T& ref)
801 if (luabind::get_back_reference(L, ref))
802 return;
804 class_rep* crep = get_class_rep<T>(L);
806 // if you get caught in this assert you are
807 // trying to use an unregistered type
808 assert(crep && "you are trying to use an unregistered type");
810 T* ptr = &ref;
812 // create the struct to hold the object
813 void* obj = lua_newuserdata(L, sizeof(object_rep));
814 assert(obj && "internal error, please report");
815 new(obj) object_rep(ptr, crep, 0, 0);
817 // set the meta table
818 detail::getref(L, crep->metatable_ref());
819 lua_setmetatable(L, -2);
823 template<class T> struct make_reference { typedef T& type; };
824 template<>
825 struct ref_converter<lua_to_cpp>
827 typedef boost::mpl::bool_<false> is_value_converter;
828 typedef ref_converter type;
830 template<class T>
831 typename make_reference<T>::type apply(lua_State* L, by_reference<T>, int index)
833 assert(!lua_isnil(L, index));
834 return *pointer_converter<lua_to_cpp>().apply(L, by_pointer<T>(), index);
837 template<class T>
838 static int match(lua_State* L, by_reference<T>, int index)
840 if (lua_isnil(L, index)) return -1;
841 return pointer_converter<lua_to_cpp>::match(L, by_pointer<T>(), index);
844 template<class T>
845 void converter_postcall(lua_State*, T, int) {}
848 // ******** const reference converter *********
850 template<class Direction> struct const_ref_converter;
852 template<>
853 struct const_ref_converter<cpp_to_lua>
855 typedef boost::mpl::bool_<false> is_value_converter;
856 typedef const_ref_converter type;
858 template<class T>
859 void apply(lua_State* L, T const& ref)
861 if (luabind::get_back_reference(L, ref))
862 return;
864 class_rep* crep = get_class_rep<T>(L);
866 // if you get caught in this assert you are
867 // trying to use an unregistered type
868 assert(crep && "you are trying to use an unregistered type");
870 T const* ptr = &ref;
872 // create the struct to hold the object
873 void* obj = lua_newuserdata(L, sizeof(object_rep));
874 assert(obj && "internal error, please report");
875 new(obj) object_rep(const_cast<T*>(ptr), crep, object_rep::constant, 0);
877 // set the meta table
878 detail::getref(L, crep->metatable_ref());
879 lua_setmetatable(L, -2);
883 template<>
884 struct const_ref_converter<lua_to_cpp>
886 typedef boost::mpl::bool_<false> is_value_converter;
887 typedef const_ref_converter type;
889 // TODO: align!
890 char target[32];
891 void (*destructor)(void*);
893 const_ref_converter(): destructor(0) {}
895 template<class T>
896 typename make_const_reference<T>::type apply(lua_State* L, by_const_reference<T>, int index)
898 object_rep* obj = 0;
899 class_rep const * crep = 0;
901 // special case if we get nil in, try to convert the holder type
902 if (lua_isnil(L, index))
904 crep = get_class_rep<T>(L);
905 assert(crep);
907 else
909 obj = static_cast<object_rep*>(lua_touserdata(L, index));
910 assert((obj != 0) && "internal error, please report"); // internal error
911 crep = obj->crep();
913 assert(crep);
915 T* ptr = reinterpret_cast<T*>(crep->convert_to(LUABIND_TYPEID(T), obj, target));
916 // if the pointer returned points into the converter storage,
917 // we need to destruct it once the converter destructs
918 if ((void*)ptr == (void*)target) destructor = detail::destruct_only_s<T>::apply;
919 assert(!destructor || sizeof(T) <= 32);
921 return *ptr;
924 template<class T>
925 static int match(lua_State* L, by_const_reference<T>, int index)
927 // special case if we get nil in, try to match the holder type
928 if (lua_isnil(L, index))
930 class_rep* crep = get_class_rep<T>(L);
931 if (crep == 0) return -1;
932 if ((LUABIND_TYPE_INFO_EQUAL(crep->holder_type(), LUABIND_TYPEID(T))))
933 return 0;
934 if ((LUABIND_TYPE_INFO_EQUAL(crep->const_holder_type(), LUABIND_TYPEID(T))))
935 return 0;
936 return -1;
939 object_rep* obj = is_class_object(L, index);
940 if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
942 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
943 return (obj->flags() & object_rep::constant)?-1:0;
944 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
945 return (obj->flags() & object_rep::constant)?0:1;
947 bool const_ = obj->flags() & object_rep::constant;
948 int d;
949 int points = implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
950 return points == -1 ? -1 : points + !const_;
953 ~const_ref_converter()
955 if (destructor) destructor(target);
958 template<class T>
959 void converter_postcall(lua_State* L, by_const_reference<T>, int index)
964 // ****** enum converter ********
966 template<class Direction = cpp_to_lua>
967 struct enum_converter
969 typedef boost::mpl::bool_<false> is_value_converter;
970 typedef enum_converter type;
972 void apply(lua_State* L, int val)
974 lua_pushnumber(L, val);
978 template<>
979 struct enum_converter<lua_to_cpp>
981 typedef boost::mpl::bool_<false> is_value_converter;
982 typedef enum_converter type;
984 template<class T>
985 T apply(lua_State* L, by_value<T>, int index)
987 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
990 template<class T>
991 static int match(lua_State* L, by_value<T>, int index)
993 if (lua_isnumber(L, index)) return 0; else return -1;
996 template<class T>
997 void converter_postcall(lua_State*, T, int) {}
1000 // ****** functor converter ********
1002 template<class Direction> struct functor_converter;
1004 template<>
1005 struct functor_converter<lua_to_cpp>
1007 typedef functor_converter type;
1009 template<class T>
1010 functor<T> apply(lua_State* L, by_const_reference<functor<T> >, int index)
1012 if (lua_isnil(L, index))
1013 return functor<T>();
1015 lua_pushvalue(L, index);
1016 detail::lua_reference ref;
1017 ref.set(L);
1018 return functor<T>(L, ref);
1021 template<class T>
1022 functor<T> apply(lua_State* L, by_value<functor<T> >, int index)
1024 if (lua_isnil(L, index))
1025 return functor<T>();
1027 lua_pushvalue(L, index);
1028 detail::lua_reference ref;
1029 ref.set(L);
1030 return functor<T>(L, ref);
1033 template<class T>
1034 static int match(lua_State* L, by_const_reference<functor<T> >, int index)
1036 if (lua_isfunction(L, index) || lua_isnil(L, index)) return 0; else return -1;
1039 template<class T>
1040 static int match(lua_State* L, by_value<functor<T> >, int index)
1042 if (lua_isfunction(L, index) || lua_isnil(L, index)) return 0; else return -1;
1045 template<class T>
1046 void converter_postcall(lua_State*, T, int) {}
1050 template<class Direction>
1051 struct value_wrapper_converter;
1053 template<>
1054 struct value_wrapper_converter<lua_to_cpp>
1056 typedef boost::mpl::bool_<false> is_value_converter;
1057 typedef value_wrapper_converter type;
1059 template<class T>
1060 T apply(lua_State* L, by_const_reference<T>, int index)
1062 return T(from_stack(L, index));
1065 template<class T>
1066 T apply(lua_State* L, by_value<T>, int index)
1068 return apply(L, by_const_reference<T>(), index);
1071 template<class T>
1072 static int match(lua_State* L, by_const_reference<T>, int index)
1074 return value_wrapper_traits<T>::check(L, index)
1075 ? (std::numeric_limits<int>::max)() / LUABIND_MAX_ARITY
1076 : -1;
1079 template<class T>
1080 static int match(lua_State* L, by_value<T>, int index)
1082 return match(L, by_const_reference<T>(), index);
1085 void converter_postcall(...) {}
1088 template<>
1089 struct value_wrapper_converter<cpp_to_lua>
1091 typedef boost::mpl::bool_<false> is_value_converter;
1092 typedef value_wrapper_converter type;
1094 template<class T>
1095 void apply(lua_State* interpreter, T const& value_wrapper)
1097 value_wrapper_traits<T>::unwrap(interpreter, value_wrapper);
1101 // *********** default_policy *****************
1103 using boost::mpl::eval_if;
1105 struct default_policy : converter_policy_tag
1107 BOOST_STATIC_CONSTANT(bool, has_arg = true);
1109 template<class T>
1110 static void precall(lua_State*, T, int) {}
1112 template<class T, class Direction>
1113 struct apply
1114 : eval_if<
1115 is_user_defined<T>
1116 , user_defined_converter<Direction>
1117 , eval_if<
1118 is_value_wrapper_arg<T>
1119 , value_wrapper_converter<Direction>
1120 , eval_if<
1121 is_primitive<T>
1122 , primitive_converter<Direction>
1123 , eval_if<
1124 // is_lua_functor<T>
1125 // , functor_converter<Direction>
1126 // , eval_if<
1127 boost::is_enum<T>
1128 , enum_converter<Direction>
1129 , eval_if<
1130 is_nonconst_pointer<T>
1131 , pointer_converter<Direction>
1132 , eval_if<
1133 is_const_pointer<T>
1134 , const_pointer_converter<Direction>
1135 , eval_if<
1136 is_nonconst_reference<T>
1137 , ref_converter<Direction>
1138 , eval_if<
1139 is_const_reference<T>
1140 , const_ref_converter<Direction>
1141 , value_converter<Direction>
1147 // >
1155 // ============== new policy system =================
1157 template<int, class> struct find_conversion_policy;
1159 template<bool IsConverter = false>
1160 struct find_conversion_impl
1162 template<int N, class Policies>
1163 struct apply
1165 typedef typename find_conversion_policy<N, typename Policies::tail>::type type;
1169 template<>
1170 struct find_conversion_impl<true>
1172 template<int N, class Policies>
1173 struct apply
1175 typedef typename Policies::head head;
1176 typedef typename Policies::tail tail;
1178 BOOST_STATIC_CONSTANT(bool, found = (N == head::index));
1180 typedef typename
1181 boost::mpl::if_c<found
1182 , head
1183 , typename find_conversion_policy<N, tail>::type
1184 >::type type;
1188 template<class Policies>
1189 struct find_conversion_impl2
1191 template<int N>
1192 struct apply
1193 : find_conversion_impl<
1194 boost::is_base_and_derived<conversion_policy_base, typename Policies::head>::value
1195 >::template apply<N, Policies>
1200 template<>
1201 struct find_conversion_impl2<detail::null_type>
1203 template<int N>
1204 struct apply
1206 typedef default_policy type;
1210 template<int N, class Policies>
1211 struct find_conversion_policy : find_conversion_impl2<Policies>::template apply<N>
1215 template<class List>
1216 struct policy_list_postcall
1218 typedef typename List::head head;
1219 typedef typename List::tail tail;
1221 static void apply(lua_State* L, const index_map& i)
1223 head::postcall(L, i);
1224 policy_list_postcall<tail>::apply(L, i);
1228 template<>
1229 struct policy_list_postcall<detail::null_type>
1231 static void apply(lua_State*, const index_map&) {}
1234 // ==================================================
1236 // ************** precall and postcall on policy_cons *********************
1239 template<class List>
1240 struct policy_precall
1242 typedef typename List::head head;
1243 typedef typename List::tail tail;
1245 static void apply(lua_State* L, int index)
1247 head::precall(L, index);
1248 policy_precall<tail>::apply(L, index);
1252 template<>
1253 struct policy_precall<detail::null_type>
1255 static void apply(lua_State*, int) {}
1258 template<class List>
1259 struct policy_postcall
1261 typedef typename List::head head;
1262 typedef typename List::tail tail;
1264 static void apply(lua_State* L, int index)
1266 head::postcall(L, index);
1267 policy_postcall<tail>::apply(L, index);
1271 template<>
1272 struct policy_postcall<detail::null_type>
1274 static void apply(lua_State*, int) {}
1277 }} // namespace luabind::detail
1280 namespace luabind { namespace
1282 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ <= 400)
1283 static inline boost::arg<0> return_value()
1285 return boost::arg<0>();
1288 static inline boost::arg<0> result()
1290 return boost::arg<0>();
1292 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>(*)()
1293 #elif defined(BOOST_MSVC) || defined(__MWERKS__)
1294 static boost::arg<0> return_value;
1295 static boost::arg<0> result;
1296 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1297 #else
1298 boost::arg<0> return_value;
1299 boost::arg<0> result;
1300 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1301 #endif
1304 #endif // LUABIND_POLICY_HPP_INCLUDED