1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
2
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:
9
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
12
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.
22
23
24 #ifndef LUABIND_POLICY_HPP_INCLUDED
25 #define LUABIND_POLICY_HPP_INCLUDED
26
27 #include <luabind/config.hpp>
28
29 #include <typeinfo>
30 #include <string>
31 #include <memory>
32
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>
48
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>
58
59 #include <boost/type_traits/add_reference.hpp>
60
61 #include <luabind/detail/decorate_type.hpp>
62 #include <luabind/weak_ref.hpp>
63 #include <luabind/back_reference_fwd.hpp>
64
65 #include <luabind/value_wrapper.hpp>
66 #include <luabind/from_stack.hpp>
67 #include <luabind/typeid.hpp>
68
69 namespace luabind
70 {
71 namespace detail
72 {
73 struct conversion_policy_base {};
74 }
75
76 template<int N, bool HasArg = true>
77 struct conversion_policy : detail::conversion_policy_base
78 {
79 BOOST_STATIC_CONSTANT(int, index = N);
80 BOOST_STATIC_CONSTANT(bool, has_arg = HasArg);
81 };
82
83 class index_map
84 {
85 public:
index_map(const int * m)86 index_map(const int* m): m_map(m) {}
87
operator [](int index) const88 int operator[](int index) const
89 {
90 return m_map[index];
91 }
92
93 private:
94 const int* m_map;
95 };
96
97 // template<class T> class functor;
98 class weak_ref;
99 }
100
101 namespace luabind { namespace detail
102 {
103 template<class H, class T>
104 struct policy_cons
105 {
106 typedef H head;
107 typedef T tail;
108
109 template<class U>
operator ,luabind::detail::policy_cons110 policy_cons<U, policy_cons<H,T> > operator,(policy_cons<U,detail::null_type>)
111 {
112 return policy_cons<U, policy_cons<H,T> >();
113 }
114
115 template<class U>
operator +luabind::detail::policy_cons116 policy_cons<U, policy_cons<H,T> > operator+(policy_cons<U,detail::null_type>)
117 {
118 return policy_cons<U, policy_cons<H,T> >();
119 }
120
121 template<class U>
operator |luabind::detail::policy_cons122 policy_cons<U, policy_cons<H,T> > operator|(policy_cons<U,detail::null_type>)
123 {
124 return policy_cons<U, policy_cons<H,T> >();
125 }
126 };
127
128 struct indirection_layer
129 {
130 template<class T>
131 indirection_layer(const T&);
132 };
133
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(...);
138
139 template<class T>
140 struct is_policy_cons
141 {
142 static const T& t;
143
144 BOOST_STATIC_CONSTANT(bool, value =
145 sizeof(is_policy_cons_test(t)) == sizeof(yes_t));
146
147 typedef boost::mpl::bool_<value> type;
148 };
149
150 template<bool>
151 struct is_string_literal
152 {
153 static no_t helper(indirection_layer);
154 static yes_t helper(const char*);
155 };
156
157 template<>
158 struct is_string_literal<false>
159 {
160 static no_t helper(indirection_layer);
161 };
162
163
164 namespace mpl = boost::mpl;
165
166 template <class T, class Clone>
make_pointee_instance(lua_State * L,T & x,mpl::true_,Clone)167 void make_pointee_instance(lua_State* L, T& x, mpl::true_, Clone)
168 {
169 if (get_pointer(x))
170 {
171 make_instance(L, x);
172 }
173 else
174 {
175 lua_pushnil(L);
176 }
177 }
178
179 template <class T>
make_pointee_instance(lua_State * L,T & x,mpl::false_,mpl::true_)180 void make_pointee_instance(lua_State* L, T& x, mpl::false_, mpl::true_)
181 {
182 std::auto_ptr<T> ptr(new T(x));
183 make_instance(L, ptr);
184 }
185
186 template <class T>
make_pointee_instance(lua_State * L,T & x,mpl::false_,mpl::false_)187 void make_pointee_instance(lua_State* L, T& x, mpl::false_, mpl::false_)
188 {
189 make_instance(L, &x);
190 }
191
192 template <class T, class Clone>
make_pointee_instance(lua_State * L,T & x,Clone)193 void make_pointee_instance(lua_State* L, T& x, Clone)
194 {
195 make_pointee_instance(L, x, has_get_pointer<T>(), Clone());
196 }
197
198 // ********** pointer converter ***********
199
200 struct pointer_converter
201 {
202 typedef pointer_converter type;
203 typedef mpl::false_ is_native;
204
pointer_converterluabind::detail::pointer_converter205 pointer_converter()
206 : result(0)
207 {}
208
209 void* result;
210
consumed_argsluabind::detail::pointer_converter211 int const consumed_args(...)
212 {
213 return 1;
214 }
215
216 template<class T>
applyluabind::detail::pointer_converter217 void apply(lua_State* L, T* ptr)
218 {
219 if (ptr == 0)
220 {
221 lua_pushnil(L);
222 return;
223 }
224
225 if (luabind::get_back_reference(L, ptr))
226 return;
227
228 make_instance(L, ptr);
229 }
230
231 template<class T>
applyluabind::detail::pointer_converter232 T* apply(lua_State*, by_pointer<T>, int)
233 {
234 return static_cast<T*>(result);
235 }
236
237 template<class T>
matchluabind::detail::pointer_converter238 int match(lua_State* L, by_pointer<T>, int index)
239 {
240 if (lua_isnil(L, index)) return 0;
241 object_rep* obj = get_instance(L, index);
242 if (obj == 0) return -1;
243
244 if (obj->is_const())
245 return -1;
246
247 std::pair<void*, int> s = obj->get_instance(registered_class<T>::id);
248 result = s.first;
249 return s.second;
250 }
251
252 template<class T>
converter_postcallluabind::detail::pointer_converter253 void converter_postcall(lua_State*, by_pointer<T>, int)
254 {}
255 };
256
257 // ******* value converter *******
258
259 struct value_converter
260 {
261 typedef value_converter type;
262 typedef mpl::false_ is_native;
263
consumed_argsluabind::detail::value_converter264 int const consumed_args(...)
265 {
266 return 1;
267 }
268
value_converterluabind::detail::value_converter269 value_converter()
270 : result(0)
271 {}
272
273 void* result;
274
275 template<class T>
applyluabind::detail::value_converter276 void apply(lua_State* L, T x)
277 {
278 if (luabind::get_back_reference(L, x))
279 return;
280
281 make_pointee_instance(L, x, mpl::true_());
282 }
283
284 template<class T>
applyluabind::detail::value_converter285 T apply(lua_State*, by_value<T>, int)
286 {
287 return *static_cast<T*>(result);
288 }
289
290 template<class T>
matchluabind::detail::value_converter291 int match(lua_State* L, by_value<T>, int index)
292 {
293 // special case if we get nil in, try to match the holder type
294 if (lua_isnil(L, index))
295 return -1;
296
297 object_rep* obj = get_instance(L, index);
298 if (obj == 0) return -1;
299
300 std::pair<void*, int> s = obj->get_instance(registered_class<T>::id);
301 result = s.first;
302 return s.second;
303 }
304
305 template<class T>
converter_postcallluabind::detail::value_converter306 void converter_postcall(lua_State*, T, int) {}
307 };
308
309 // ******* const pointer converter *******
310
311 struct const_pointer_converter
312 {
313 typedef const_pointer_converter type;
314 typedef mpl::false_ is_native;
315
consumed_argsluabind::detail::const_pointer_converter316 int const consumed_args(...)
317 {
318 return 1;
319 }
320
const_pointer_converterluabind::detail::const_pointer_converter321 const_pointer_converter()
322 : result(0)
323 {}
324
325 void* result;
326
327 template<class T>
applyluabind::detail::const_pointer_converter328 void apply(lua_State* L, const T* ptr)
329 {
330 if (ptr == 0)
331 {
332 lua_pushnil(L);
333 return;
334 }
335
336 if (luabind::get_back_reference(L, ptr))
337 return;
338
339 make_instance(L, ptr);
340 }
341
342 template<class T>
applyluabind::detail::const_pointer_converter343 T const* apply(lua_State*, by_const_pointer<T>, int)
344 {
345 return static_cast<T const*>(result);
346 }
347
348 template<class T>
matchluabind::detail::const_pointer_converter349 int match(lua_State* L, by_const_pointer<T>, int index)
350 {
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;
359 }
360
361 template<class T>
converter_postcallluabind::detail::const_pointer_converter362 void converter_postcall(lua_State*, T, int) {}
363 };
364
365 // ******* reference converter *******
366
367 struct ref_converter : pointer_converter
368 {
369 typedef ref_converter type;
370 typedef mpl::false_ is_native;
371
consumed_argsluabind::detail::ref_converter372 int const consumed_args(...)
373 {
374 return 1;
375 }
376
377 template<class T>
applyluabind::detail::ref_converter378 void apply(lua_State* L, T& ref)
379 {
380 if (luabind::get_back_reference(L, ref))
381 return;
382
383 make_pointee_instance(L, ref, mpl::false_());
384 }
385
386 template<class T>
applyluabind::detail::ref_converter387 T& apply(lua_State* L, by_reference<T>, int index)
388 {
389 assert(!lua_isnil(L, index));
390 return *pointer_converter::apply(L, by_pointer<T>(), index);
391 }
392
393 template<class T>
matchluabind::detail::ref_converter394 int match(lua_State* L, by_reference<T>, int index)
395 {
396 object_rep* obj = get_instance(L, index);
397 if (obj == 0) return -1;
398
399 if (obj->is_const())
400 return -1;
401
402 std::pair<void*, int> s = obj->get_instance(registered_class<T>::id);
403 result = s.first;
404 return s.second;
405 }
406
407 template<class T>
converter_postcallluabind::detail::ref_converter408 void converter_postcall(lua_State*, T, int) {}
409 };
410
411 // ******** const reference converter *********
412
413 struct const_ref_converter
414 {
415 typedef const_ref_converter type;
416 typedef mpl::false_ is_native;
417
consumed_argsluabind::detail::const_ref_converter418 int const consumed_args(...)
419 {
420 return 1;
421 }
422
const_ref_converterluabind::detail::const_ref_converter423 const_ref_converter()
424 : result(0)
425 {}
426
427 void* result;
428
429 template<class T>
applyluabind::detail::const_ref_converter430 void apply(lua_State* L, T const& ref)
431 {
432 if (luabind::get_back_reference(L, ref))
433 return;
434
435 make_pointee_instance(L, ref, mpl::false_());
436 }
437
438 template<class T>
applyluabind::detail::const_ref_converter439 T const& apply(lua_State*, by_const_reference<T>, int)
440 {
441 return *static_cast<T*>(result);
442 }
443
444 template<class T>
matchluabind::detail::const_ref_converter445 int match(lua_State* L, by_const_reference<T>, int index)
446 {
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
449
450 std::pair<void*, int> s = obj->get_instance(registered_class<T>::id);
451 if (s.second >= 0 && !obj->is_const())
452 s.second += 10;
453 result = s.first;
454 return s.second;
455 }
456
457 template<class T>
converter_postcallluabind::detail::const_ref_converter458 void converter_postcall(lua_State*, by_const_reference<T>, int)
459 {
460 }
461 };
462
463 // ****** enum converter ********
464
465 struct enum_converter
466 {
467 typedef enum_converter type;
468 typedef mpl::true_ is_native;
469
consumed_argsluabind::detail::enum_converter470 int const consumed_args(...)
471 {
472 return 1;
473 }
474
applyluabind::detail::enum_converter475 void apply(lua_State* L, int val)
476 {
477 lua_pushnumber(L, val);
478 }
479
480 template<class T>
applyluabind::detail::enum_converter481 T apply(lua_State* L, by_value<T>, int index)
482 {
483 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
484 }
485
486 template<class T>
matchluabind::detail::enum_converter487 static int match(lua_State* L, by_value<T>, int index)
488 {
489 if (lua_isnumber(L, index)) return 0; else return -1;
490 }
491
492 template<class T>
applyluabind::detail::enum_converter493 T apply(lua_State* L, by_const_reference<T>, int index)
494 {
495 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
496 }
497
498 template<class T>
matchluabind::detail::enum_converter499 static int match(lua_State* L, by_const_reference<T>, int index)
500 {
501 if (lua_isnumber(L, index)) return 0; else return -1;
502 }
503
504 template<class T>
converter_postcallluabind::detail::enum_converter505 void converter_postcall(lua_State*, T, int) {}
506 };
507
508 template <class U>
509 struct value_wrapper_converter
510 {
511 typedef value_wrapper_converter<U> type;
512 typedef mpl::true_ is_native;
513
consumed_argsluabind::detail::value_wrapper_converter514 int const consumed_args(...)
515 {
516 return 1;
517 }
518
519 template<class T>
applyluabind::detail::value_wrapper_converter520 T apply(lua_State* L, by_const_reference<T>, int index)
521 {
522 return T(from_stack(L, index));
523 }
524
525 template<class T>
applyluabind::detail::value_wrapper_converter526 T apply(lua_State* L, by_value<T>, int index)
527 {
528 return apply(L, by_const_reference<T>(), index);
529 }
530
531 template<class T>
matchluabind::detail::value_wrapper_converter532 static int match(lua_State* L, by_const_reference<T>, int index)
533 {
534 return value_wrapper_traits<T>::check(L, index)
535 ? (std::numeric_limits<int>::max)() / LUABIND_MAX_ARITY
536 : -1;
537 }
538
539 template<class T>
matchluabind::detail::value_wrapper_converter540 static int match(lua_State* L, by_value<T>, int index)
541 {
542 return match(L, by_const_reference<T>(), index);
543 }
544
converter_postcallluabind::detail::value_wrapper_converter545 void converter_postcall(...) {}
546
547 template<class T>
applyluabind::detail::value_wrapper_converter548 void apply(lua_State* interpreter, T const& value_wrapper)
549 {
550 value_wrapper_traits<T>::unwrap(interpreter, value_wrapper);
551 }
552 };
553
554 template <class T>
555 struct default_converter_generator
556 : mpl::eval_if<
557 is_value_wrapper_arg<T>
558 , value_wrapper_converter<T>
559 , mpl::eval_if<
560 boost::is_enum<typename boost::remove_reference<T>::type>
561 , enum_converter
562 , mpl::eval_if<
563 is_nonconst_pointer<T>
564 , pointer_converter
565 , mpl::eval_if<
566 is_const_pointer<T>
567 , const_pointer_converter
568 , mpl::eval_if<
569 is_nonconst_reference<T>
570 , ref_converter
571 , mpl::eval_if<
572 is_const_reference<T>
573 , const_ref_converter
574 , value_converter
575 >
576 >
577 >
578 >
579 >
580 >
581 {};
582
583 } // namespace detail
584
585 // *********** default_policy *****************
586
587 template <class T>
588 struct default_converter
589 : detail::default_converter_generator<T>::type
590 {};
591
592 template <class T, class Derived = default_converter<T> >
593 struct native_converter_base
594 {
595 typedef boost::mpl::true_ is_native;
596
consumed_argsluabind::native_converter_base597 int const consumed_args(...)
598 {
599 return 1;
600 }
601
602 template <class U>
converter_postcallluabind::native_converter_base603 void converter_postcall(lua_State*, U const&, int)
604 {}
605
matchluabind::native_converter_base606 int match(lua_State* L, detail::by_value<T>, int index)
607 {
608 return derived().compute_score(L, index);
609 }
610
matchluabind::native_converter_base611 int match(lua_State* L, detail::by_value<T const>, int index)
612 {
613 return derived().compute_score(L, index);
614 }
615
matchluabind::native_converter_base616 int match(lua_State* L, detail::by_const_reference<T>, int index)
617 {
618 return derived().compute_score(L, index);
619 }
620
applyluabind::native_converter_base621 T apply(lua_State* L, detail::by_value<T>, int index)
622 {
623 return derived().from(L, index);
624 }
625
applyluabind::native_converter_base626 T apply(lua_State* L, detail::by_value<T const>, int index)
627 {
628 return derived().from(L, index);
629 }
630
applyluabind::native_converter_base631 T apply(lua_State* L, detail::by_const_reference<T>, int index)
632 {
633 return derived().from(L, index);
634 }
635
applyluabind::native_converter_base636 void apply(lua_State* L, T const& value)
637 {
638 derived().to(L, value);
639 }
640
derivedluabind::native_converter_base641 Derived& derived()
642 {
643 return static_cast<Derived&>(*this);
644 }
645 };
646
647 template <class T>
as_lua_integer(T v)648 lua_Integer as_lua_integer(T v)
649 {
650 return static_cast<lua_Integer>(v);
651 }
652
653 template <class T>
as_lua_number(T v)654 lua_Number as_lua_number(T v)
655 {
656 return static_cast<lua_Number>(v);
657 }
658
659 # define LUABIND_NUMBER_CONVERTER(type, kind) \
660 template <> \
661 struct default_converter<type> \
662 : native_converter_base<type> \
663 { \
664 int compute_score(lua_State* L, int index) \
665 { \
666 return lua_type(L, index) == LUA_TNUMBER ? 0 : -1; \
667 }; \
668 \
669 type from(lua_State* L, int index) \
670 { \
671 return static_cast<type>(BOOST_PP_CAT(lua_to, kind)(L, index)); \
672 } \
673 \
674 void to(lua_State* L, type const& value) \
675 { \
676 BOOST_PP_CAT(lua_push, kind)(L, BOOST_PP_CAT(as_lua_, kind)(value)); \
677 } \
678 }; \
679 \
680 template <> \
681 struct default_converter<type const> \
682 : default_converter<type> \
683 {}; \
684 \
685 template <> \
686 struct default_converter<type const&> \
687 : default_converter<type> \
688 {};
689
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)
696
697 LUABIND_NUMBER_CONVERTER(unsigned int, number)
698 LUABIND_NUMBER_CONVERTER(unsigned long, number)
699
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)
704
705 # undef LUABIND_NUMBER_CONVERTER
706
707 template <>
708 struct default_converter<bool>
709 : native_converter_base<bool>
710 {
compute_scoreluabind::default_converter711 static int compute_score(lua_State* L, int index)
712 {
713 return lua_type(L, index) == LUA_TBOOLEAN ? 0 : -1;
714 }
715
fromluabind::default_converter716 bool from(lua_State* L, int index)
717 {
718 return lua_toboolean(L, index) == 1;
719 }
720
toluabind::default_converter721 void to(lua_State* L, bool value)
722 {
723 lua_pushboolean(L, value);
724 }
725 };
726
727 template <>
728 struct default_converter<bool const>
729 : default_converter<bool>
730 {};
731
732 template <>
733 struct default_converter<bool const&>
734 : default_converter<bool>
735 {};
736
737 template <>
738 struct default_converter<std::string>
739 : native_converter_base<std::string>
740 {
compute_scoreluabind::default_converter741 static int compute_score(lua_State* L, int index)
742 {
743 return lua_type(L, index) == LUA_TSTRING ? 0 : -1;
744 }
745
fromluabind::default_converter746 std::string from(lua_State* L, int index)
747 {
748 return std::string(lua_tostring(L, index), lua_strlen(L, index));
749 }
750
toluabind::default_converter751 void to(lua_State* L, std::string const& value)
752 {
753 lua_pushlstring(L, value.data(), value.size());
754 }
755 };
756
757 template <>
758 struct default_converter<std::string const>
759 : default_converter<std::string>
760 {};
761
762 template <>
763 struct default_converter<std::string const&>
764 : default_converter<std::string>
765 {};
766
767 template <>
768 struct default_converter<char const*>
769 {
770 typedef boost::mpl::true_ is_native;
771
consumed_argsluabind::default_converter772 int const consumed_args(...)
773 {
774 return 1;
775 }
776
777 template <class U>
matchluabind::default_converter778 static int match(lua_State* L, U, int index)
779 {
780 int type = lua_type(L, index);
781 return (type == LUA_TSTRING || type == LUA_TNIL) ? 0 : -1;
782 }
783
784 template <class U>
applyluabind::default_converter785 char const* apply(lua_State* L, U, int index)
786 {
787 return lua_tostring(L, index);
788 }
789
applyluabind::default_converter790 void apply(lua_State* L, char const* str)
791 {
792 lua_pushstring(L, str);
793 }
794
795 template <class U>
converter_postcallluabind::default_converter796 void converter_postcall(lua_State*, U, int)
797 {}
798 };
799
800 template <>
801 struct default_converter<const char* const>
802 : default_converter<char const*>
803 {};
804
805 template <>
806 struct default_converter<char*>
807 : default_converter<char const*>
808 {};
809
810 template <std::size_t N>
811 struct default_converter<char const[N]>
812 : default_converter<char const*>
813 {};
814
815 template <std::size_t N>
816 struct default_converter<char[N]>
817 : default_converter<char const*>
818 {};
819
820 template <>
821 struct default_converter<lua_State*>
822 {
consumed_argsluabind::default_converter823 int const consumed_args(...)
824 {
825 return 0;
826 }
827
828 template <class U>
applyluabind::default_converter829 lua_State* apply(lua_State* L, U, int)
830 {
831 return L;
832 }
833
834 template <class U>
matchluabind::default_converter835 static int match(lua_State*, U, int)
836 {
837 return 0;
838 }
839
840 template <class U>
converter_postcallluabind::default_converter841 void converter_postcall(lua_State*, U, int) {}
842 };
843
844 namespace detail
845 {
846
847 struct default_policy : converter_policy_tag
848 {
849 BOOST_STATIC_CONSTANT(bool, has_arg = true);
850
851 template<class T>
precallluabind::detail::default_policy852 static void precall(lua_State*, T, int) {}
853
854 template<class T, class Direction>
855 struct apply
856 {
857 typedef default_converter<T> type;
858 };
859 };
860
861 template<class T>
862 struct is_primitive
863 : default_converter<T>::is_native
864 {};
865
866 // ============== new policy system =================
867
868 template<int, class> struct find_conversion_policy;
869
870 template<bool IsConverter = false>
871 struct find_conversion_impl
872 {
873 template<int N, class Policies>
874 struct apply
875 {
876 typedef typename find_conversion_policy<N, typename Policies::tail>::type type;
877 };
878 };
879
880 template<>
881 struct find_conversion_impl<true>
882 {
883 template<int N, class Policies>
884 struct apply
885 {
886 typedef typename Policies::head head;
887 typedef typename Policies::tail tail;
888
889 BOOST_STATIC_CONSTANT(bool, found = (N == head::index));
890
891 typedef typename
892 boost::mpl::if_c<found
893 , head
894 , typename find_conversion_policy<N, tail>::type
895 >::type type;
896 };
897 };
898
899 template<class Policies>
900 struct find_conversion_impl2
901 {
902 template<int N>
903 struct apply
904 : find_conversion_impl<
905 boost::is_base_and_derived<conversion_policy_base, typename Policies::head>::value
906 >::template apply<N, Policies>
907 {
908 };
909 };
910
911 template<>
912 struct find_conversion_impl2<detail::null_type>
913 {
914 template<int N>
915 struct apply
916 {
917 typedef default_policy type;
918 };
919 };
920
921 template<int N, class Policies>
922 struct find_conversion_policy : find_conversion_impl2<Policies>::template apply<N>
923 {
924 };
925
926 template<class List>
927 struct policy_list_postcall
928 {
929 typedef typename List::head head;
930 typedef typename List::tail tail;
931
applyluabind::detail::policy_list_postcall932 static void apply(lua_State* L, const index_map& i)
933 {
934 head::postcall(L, i);
935 policy_list_postcall<tail>::apply(L, i);
936 }
937 };
938
939 template<>
940 struct policy_list_postcall<detail::null_type>
941 {
applyluabind::detail::policy_list_postcall942 static void apply(lua_State*, const index_map&) {}
943 };
944
945 // ==================================================
946
947 // ************** precall and postcall on policy_cons *********************
948
949
950 template<class List>
951 struct policy_precall
952 {
953 typedef typename List::head head;
954 typedef typename List::tail tail;
955
applyluabind::detail::policy_precall956 static void apply(lua_State* L, int index)
957 {
958 head::precall(L, index);
959 policy_precall<tail>::apply(L, index);
960 }
961 };
962
963 template<>
964 struct policy_precall<detail::null_type>
965 {
applyluabind::detail::policy_precall966 static void apply(lua_State*, int) {}
967 };
968
969 template<class List>
970 struct policy_postcall
971 {
972 typedef typename List::head head;
973 typedef typename List::tail tail;
974
applyluabind::detail::policy_postcall975 static void apply(lua_State* L, int index)
976 {
977 head::postcall(L, index);
978 policy_postcall<tail>::apply(L, index);
979 }
980 };
981
982 template<>
983 struct policy_postcall<detail::null_type>
984 {
applyluabind::detail::policy_postcall985 static void apply(lua_State*, int) {}
986 };
987
988 }} // namespace luabind::detail
989
990
991 namespace luabind { namespace
992 {
993 #if defined(__GNUC__) && ( \
994 (BOOST_VERSION < 103500) \
995 || (BOOST_VERSION < 103900 && (__GNUC__ * 100 + __GNUC_MINOR__ <= 400)) \
996 || (__GNUC__ * 100 + __GNUC_MINOR__ < 400))
return_value()997 static inline boost::arg<0> return_value()
998 {
999 return boost::arg<0>();
1000 }
1001
result()1002 static inline boost::arg<0> result()
1003 {
1004 return boost::arg<0>();
1005 }
1006 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>(*)()
1007 #elif defined(BOOST_MSVC) || defined(__MWERKS__) \
1008 || (BOOST_VERSION >= 103900 && defined(__GNUC__) \
1009 && (__GNUC__ * 100 + __GNUC_MINOR__ == 400))
1010 static boost::arg<0> return_value;
1011 static boost::arg<0> result;
1012 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1013 #else
1014 boost::arg<0> return_value;
1015 boost::arg<0> result;
1016 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1017 #endif
1018 }}
1019
1020 #endif // LUABIND_POLICY_HPP_INCLUDED
1021
1022