1 // Copyright (c) 2005 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 #ifndef LUABIND_OBJECT_050419_HPP
24 #define LUABIND_OBJECT_050419_HPP
25
26 #include <boost/implicit_cast.hpp> // detail::push()
27 #include <boost/ref.hpp> // detail::push()
28 #include <boost/mpl/bool.hpp> // value_wrapper_traits specializations
29 #include <boost/mpl/apply_wrap.hpp>
30 #include <boost/tuple/tuple.hpp>
31 #include <boost/optional.hpp>
32
33 #include <luabind/nil.hpp>
34 #include <luabind/value_wrapper.hpp>
35 #include <luabind/detail/pcall.hpp>
36 #include <luabind/handle.hpp>
37 #include <luabind/from_stack.hpp>
38 #include <luabind/detail/policy.hpp>
39 #include <luabind/detail/stack_utils.hpp>
40 #include <luabind/detail/convert_to_lua.hpp> // REFACTOR
41 #include <luabind/typeid.hpp>
42
43 #include <boost/iterator/iterator_facade.hpp> // iterator
44
45 #include <boost/preprocessor/iteration/iterate.hpp>
46 #include <boost/utility/enable_if.hpp>
47
48 namespace luabind {
49
50 namespace detail
51 {
52 namespace mpl = boost::mpl;
53
54 template<class T, class ConverterGenerator>
push_aux(lua_State * interpreter,T & value,ConverterGenerator *)55 void push_aux(lua_State* interpreter, T& value, ConverterGenerator*)
56 {
57 typedef typename boost::mpl::if_<
58 boost::is_reference_wrapper<T>
59 , BOOST_DEDUCED_TYPENAME boost::unwrap_reference<T>::type&
60 , T
61 >::type unwrapped_type;
62
63 typename mpl::apply_wrap2<
64 ConverterGenerator,unwrapped_type,cpp_to_lua
65 >::type cv;
66
67 cv.apply(
68 interpreter
69 , boost::implicit_cast<
70 BOOST_DEDUCED_TYPENAME boost::unwrap_reference<T>::type&
71 >(value)
72 );
73 }
74
75 template<class T, class Policies>
push(lua_State * interpreter,T & value,Policies const &)76 void push(lua_State* interpreter, T& value, Policies const&)
77 {
78 typedef typename find_conversion_policy<
79 0
80 , Policies
81 >::type converter_policy;
82
83 push_aux(interpreter, value, (converter_policy*)0);
84 }
85
86 template<class T>
push(lua_State * interpreter,T & value)87 void push(lua_State* interpreter, T& value)
88 {
89 push(interpreter, value, null_type());
90 }
91
92 } // namespace detail
93
94 namespace adl
95 {
96 namespace mpl = boost::mpl;
97
98 template <class T>
99 class object_interface;
100
101 namespace is_object_interface_aux
102 {
103 typedef char (&yes)[1];
104 typedef char (&no)[2];
105
106 template <class T>
107 yes check(object_interface<T>*);
108 no check(void*);
109
110 template <class T>
111 struct impl
112 {
113 BOOST_STATIC_CONSTANT(bool, value =
114 sizeof(is_object_interface_aux::check((T*)0)) == sizeof(yes)
115 );
116
117 typedef mpl::bool_<value> type;
118 };
119
120 } // namespace detail
121
122 template <class T>
123 struct is_object_interface
124 : is_object_interface_aux::impl<T>::type
125 {};
126
127 template <class R, class T, class U>
128 struct enable_binary
129 # ifndef BOOST_NO_SFINAE
130 : boost::enable_if<
131 mpl::or_<
132 is_object_interface<T>
133 , is_object_interface<U>
134 >
135 , R
136 >
137 {};
138 # else
139 {
140 typedef R type;
141 };
142 # endif
143
144 template<class T, class U>
binary_interpreter(lua_State * & L,T const & lhs,U const & rhs,boost::mpl::true_,boost::mpl::true_)145 int binary_interpreter(lua_State*& L, T const& lhs, U const& rhs
146 , boost::mpl::true_, boost::mpl::true_)
147 {
148 L = value_wrapper_traits<T>::interpreter(lhs);
149 lua_State* L2 = value_wrapper_traits<U>::interpreter(rhs);
150
151 // you are comparing objects with different interpreters
152 // that's not allowed.
153 assert(L == L2 || L == 0 || L2 == 0);
154
155 // if the two objects we compare have different interpreters
156 // then they
157
158 if (L != L2) return -1;
159 if (L == 0) return 1;
160 return 0;
161 }
162
163 template<class T, class U>
binary_interpreter(lua_State * & L,T const & x,U const &,boost::mpl::true_,boost::mpl::false_)164 int binary_interpreter(lua_State*& L, T const& x, U const&
165 , boost::mpl::true_, boost::mpl::false_)
166 {
167 L = value_wrapper_traits<T>::interpreter(x);
168 return 0;
169 }
170
171 template<class T, class U>
binary_interpreter(lua_State * & L,T const &,U const & x,boost::mpl::false_,boost::mpl::true_)172 int binary_interpreter(lua_State*& L, T const&, U const& x, boost::mpl::false_, boost::mpl::true_)
173 {
174 L = value_wrapper_traits<U>::interpreter(x);
175 return 0;
176 }
177
178 template<class T, class U>
binary_interpreter(lua_State * & L,T const & x,U const & y)179 int binary_interpreter(lua_State*& L, T const& x, U const& y)
180 {
181 return binary_interpreter(
182 L
183 , x
184 , y
185 , is_value_wrapper<T>()
186 , is_value_wrapper<U>()
187 );
188 }
189
190 #define LUABIND_BINARY_OP_DEF(op, fn) \
191 template<class LHS, class RHS> \
192 typename enable_binary<bool,LHS,RHS>::type \
193 operator op(LHS const& lhs, RHS const& rhs) \
194 { \
195 lua_State* L = 0; \
196 switch (binary_interpreter(L, lhs, rhs)) \
197 { \
198 case 1: \
199 return true; \
200 case -1: \
201 return false; \
202 } \
203 \
204 assert(L); \
205 \
206 detail::stack_pop pop1(L, 1); \
207 detail::push(L, lhs); \
208 detail::stack_pop pop2(L, 1); \
209 detail::push(L, rhs); \
210 \
211 return fn(L, -1, -2) != 0; \
212 }
213
214 LUABIND_BINARY_OP_DEF(==, lua_equal)
215 LUABIND_BINARY_OP_DEF(<, lua_lessthan)
216
217 template<class ValueWrapper>
operator <<(std::ostream & os,object_interface<ValueWrapper> const & v)218 std::ostream& operator<<(std::ostream& os
219 , object_interface<ValueWrapper> const& v)
220 {
221 using namespace luabind;
222 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
223 static_cast<ValueWrapper const&>(v));
224 detail::stack_pop pop(interpreter, 1);
225 value_wrapper_traits<ValueWrapper>::unwrap(interpreter
226 , static_cast<ValueWrapper const&>(v));
227 char const* p = lua_tostring(interpreter, -1);
228 int len = lua_strlen(interpreter, -1);
229 std::copy(p, p + len, std::ostream_iterator<char>(os));
230 return os;
231 }
232
233 #undef LUABIND_BINARY_OP_DEF
234
235 template<class LHS, class RHS>
236 typename enable_binary<bool,LHS,RHS>::type
operator >(LHS const & lhs,RHS const & rhs)237 operator>(LHS const& lhs, RHS const& rhs)
238 {
239 return !(lhs < rhs || lhs == rhs);
240 }
241
242 template<class LHS, class RHS>
243 typename enable_binary<bool,LHS,RHS>::type
operator <=(LHS const & lhs,RHS const & rhs)244 operator<=(LHS const& lhs, RHS const& rhs)
245 {
246 return lhs < rhs || lhs == rhs;
247 }
248
249 template<class LHS, class RHS>
250 typename enable_binary<bool,LHS,RHS>::type
operator >=(LHS const & lhs,RHS const & rhs)251 operator>=(LHS const& lhs, RHS const& rhs)
252 {
253 return !(lhs < rhs);
254 }
255
256 template<class LHS, class RHS>
257 typename enable_binary<bool,LHS,RHS>::type
operator !=(LHS const & lhs,RHS const & rhs)258 operator!=(LHS const& lhs, RHS const& rhs)
259 {
260 return !(lhs < rhs);
261 }
262
263 template<class ValueWrapper, class Arguments>
264 struct call_proxy;
265
266 template<class Next>
267 class index_proxy;
268
269 class object;
270
271 template<class Derived>
272 class object_interface
273 {
274 struct safe_bool_type {};
275 public:
~object_interface()276 ~object_interface() {}
277
278 call_proxy<Derived, boost::tuples::tuple<> > operator()();
279
280 template<class A0>
281 call_proxy<
282 Derived
283 , boost::tuples::tuple<A0 const*>
operator ()(A0 const & a0)284 > operator()(A0 const& a0)
285 {
286 typedef boost::tuples::tuple<A0 const*> arguments;
287
288 return call_proxy<Derived, arguments>(
289 derived()
290 , arguments(&a0)
291 );
292 }
293
294 template<class A0, class A1>
295 call_proxy<
296 Derived
297 , boost::tuples::tuple<A0 const*, A1 const*>
operator ()(A0 const & a0,A1 const & a1)298 > operator()(A0 const& a0, A1 const& a1)
299 {
300 typedef boost::tuples::tuple<A0 const*, A1 const*> arguments;
301
302 return call_proxy<Derived, arguments>(
303 derived()
304 , arguments(&a0, &a1)
305 );
306 }
307
308 // The rest of the overloads are PP-generated.
309 #define BOOST_PP_ITERATION_PARAMS_1 (3, \
310 (3, LUABIND_MAX_ARITY, <luabind/detail/object_call.hpp>))
311 #include BOOST_PP_ITERATE()
312
operator safe_bool_type*() const313 operator safe_bool_type*() const
314 {
315 lua_State* L = value_wrapper_traits<Derived>::interpreter(derived());
316
317 if (!L)
318 return 0;
319
320 value_wrapper_traits<Derived>::unwrap(L, derived());
321 detail::stack_pop pop(L, 1);
322
323 return lua_toboolean(L, -1) == 1 ? (safe_bool_type*)1 : 0;
324 }
325
326 private:
derived()327 Derived& derived()
328 {
329 return *static_cast<Derived*>(this);
330 }
331
derived() const332 Derived const& derived() const
333 {
334 return *static_cast<Derived const*>(this);
335 }
336 };
337
338 #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
339 struct iterator_proxy_tag;
340 #endif
341
342 template<class AccessPolicy>
343 class iterator_proxy
344 : public object_interface<iterator_proxy<AccessPolicy> >
345 {
346 public:
347 #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
348 typedef iterator_proxy_tag value_wrapper_tag;
349 #endif
350
iterator_proxy(lua_State * interpreter,handle const & table,handle const & key)351 iterator_proxy(lua_State* interpreter, handle const& table, handle const& key)
352 : m_interpreter(interpreter)
353 , m_table_index(lua_gettop(interpreter) + 1)
354 , m_key_index(m_table_index + 1)
355 {
356 table.push(m_interpreter);
357 key.push(m_interpreter);
358 }
359
iterator_proxy(iterator_proxy const & other)360 iterator_proxy(iterator_proxy const& other)
361 : m_interpreter(other.m_interpreter)
362 , m_table_index(other.m_table_index)
363 , m_key_index(other.m_key_index)
364 {
365 other.m_interpreter = 0;
366 }
367
~iterator_proxy()368 ~iterator_proxy()
369 {
370 if (m_interpreter)
371 lua_pop(m_interpreter, 2);
372 }
373
374 // this will set the value to nil
operator =(luabind::detail::nil_type)375 iterator_proxy & operator=(luabind::detail::nil_type)
376 {
377 lua_pushvalue(m_interpreter, m_key_index);
378 lua_pushnil(m_interpreter);
379 AccessPolicy::set(m_interpreter, m_table_index);
380 return *this;
381 }
382
383 template<class T>
operator =(T const & value)384 iterator_proxy& operator=(T const& value)
385 {
386 lua_pushvalue(m_interpreter, m_key_index);
387 detail::push(m_interpreter, value);
388 AccessPolicy::set(m_interpreter, m_table_index);
389 return *this;
390 }
391
392 template<class Key>
operator [](Key const & key)393 index_proxy<iterator_proxy<AccessPolicy> > operator[](Key const& key)
394 {
395 return index_proxy<iterator_proxy<AccessPolicy> >(
396 *this, m_interpreter, key
397 );
398 }
399
400 // This is non-const to prevent conversion on lvalues.
401 operator object();
402
interpreter() const403 lua_State* interpreter() const
404 {
405 return m_interpreter;
406 }
407
408 // TODO: Why is it non-const?
push(lua_State * interpreter)409 void push(lua_State* interpreter)
410 {
411 assert(interpreter == m_interpreter);
412 lua_pushvalue(m_interpreter, m_key_index);
413 AccessPolicy::get(m_interpreter, m_table_index);
414 }
415
416 private:
417 mutable lua_State* m_interpreter;
418 int m_table_index;
419 int m_key_index;
420 };
421
422 } // namespace adl
423
424 namespace detail
425 {
426 struct basic_access
427 {
setluabind::detail::basic_access428 static void set(lua_State* interpreter, int table)
429 {
430 lua_settable(interpreter, table);
431 }
432
getluabind::detail::basic_access433 static void get(lua_State* interpreter, int table)
434 {
435 lua_gettable(interpreter, table);
436 }
437 };
438
439 struct raw_access
440 {
setluabind::detail::raw_access441 static void set(lua_State* interpreter, int table)
442 {
443 lua_rawset(interpreter, table);
444 }
445
getluabind::detail::raw_access446 static void get(lua_State* interpreter, int table)
447 {
448 lua_rawget(interpreter, table);
449 }
450 };
451
452 template<class AccessPolicy>
453 class basic_iterator
454 : public boost::iterator_facade<
455 basic_iterator<AccessPolicy>
456 , adl::iterator_proxy<AccessPolicy>
457 , boost::single_pass_traversal_tag
458 , adl::iterator_proxy<AccessPolicy>
459 >
460 {
461 public:
basic_iterator()462 basic_iterator()
463 : m_interpreter(0)
464 {}
465
466 template<class ValueWrapper>
basic_iterator(ValueWrapper const & value_wrapper)467 explicit basic_iterator(ValueWrapper const& value_wrapper)
468 : m_interpreter(
469 value_wrapper_traits<ValueWrapper>::interpreter(value_wrapper)
470 )
471 {
472 detail::stack_pop pop(m_interpreter, 1);
473 value_wrapper_traits<ValueWrapper>::unwrap(m_interpreter, value_wrapper);
474
475 lua_pushnil(m_interpreter);
476 if (lua_next(m_interpreter, -2) != 0)
477 {
478 detail::stack_pop pop(m_interpreter, 2);
479 handle(m_interpreter, -2).swap(m_key);
480 }
481 else
482 {
483 m_interpreter = 0;
484 return;
485 }
486
487 handle(m_interpreter, -1).swap(m_table);
488 }
489
490 adl::object key() const;
491
492 private:
493 friend class boost::iterator_core_access;
494
increment()495 void increment()
496 {
497 m_table.push(m_interpreter);
498 m_key.push(m_interpreter);
499
500 detail::stack_pop pop(m_interpreter, 1);
501
502 if (lua_next(m_interpreter, -2) != 0)
503 {
504 m_key.replace(m_interpreter, -2);
505 lua_pop(m_interpreter, 2);
506 }
507 else
508 {
509 m_interpreter = 0;
510 handle().swap(m_table);
511 handle().swap(m_key);
512 }
513 }
514
equal(basic_iterator const & other) const515 bool equal(basic_iterator const& other) const
516 {
517 if (m_interpreter == 0 && other.m_interpreter == 0)
518 return true;
519
520 if (m_interpreter != other.m_interpreter)
521 return false;
522
523 detail::stack_pop pop(m_interpreter, 2);
524 m_key.push(m_interpreter);
525 other.m_key.push(m_interpreter);
526 return lua_equal(m_interpreter, -2, -1) != 0;
527 }
528
dereference() const529 adl::iterator_proxy<AccessPolicy> dereference() const
530 {
531 return adl::iterator_proxy<AccessPolicy>(m_interpreter, m_table, m_key);
532 }
533
534 lua_State* m_interpreter;
535 handle m_table;
536 handle m_key;
537 };
538
539 #if BOOST_VERSION < 105700
540 // Needed because of some strange ADL issues.
541
542 #define LUABIND_OPERATOR_ADL_WKND(op) \
543 inline bool operator op( \
544 basic_iterator<basic_access> const& x \
545 , basic_iterator<basic_access> const& y) \
546 { \
547 return boost::operator op(x, y); \
548 } \
549 \
550 inline bool operator op( \
551 basic_iterator<raw_access> const& x \
552 , basic_iterator<raw_access> const& y) \
553 { \
554 return boost::operator op(x, y); \
555 }
556
557 LUABIND_OPERATOR_ADL_WKND(==)
558 LUABIND_OPERATOR_ADL_WKND(!=)
559
560 #undef LUABIND_OPERATOR_ADL_WKND
561 #endif
562
563 } // namespace detail
564
565 namespace adl
566 {
567
568 #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
569 struct index_proxy_tag;
570 #endif
571
572 template<class Next>
573 class index_proxy
574 : public object_interface<index_proxy<Next> >
575 {
576 public:
577 #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
578 typedef index_proxy_tag value_wrapper_tag;
579 #endif
580
581 typedef index_proxy<Next> this_type;
582
583 template<class Key>
index_proxy(Next const & next,lua_State * interpreter,Key const & key)584 index_proxy(Next const& next, lua_State* interpreter, Key const& key)
585 : m_interpreter(interpreter)
586 , m_key_index(lua_gettop(interpreter) + 1)
587 , m_next(next)
588 {
589 detail::push(m_interpreter, key);
590 }
591
index_proxy(index_proxy const & other)592 index_proxy(index_proxy const& other)
593 : m_interpreter(other.m_interpreter)
594 , m_key_index(other.m_key_index)
595 , m_next(other.m_next)
596 {
597 other.m_interpreter = 0;
598 }
599
~index_proxy()600 ~index_proxy()
601 {
602 if (m_interpreter)
603 lua_pop(m_interpreter, 1);
604 }
605
606 // This is non-const to prevent conversion on lvalues.
607 operator object();
608
609 // this will set the value to nil
operator =(luabind::detail::nil_type)610 this_type& operator=(luabind::detail::nil_type)
611 {
612 value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
613 detail::stack_pop pop(m_interpreter, 1);
614
615 lua_pushvalue(m_interpreter, m_key_index);
616 lua_pushnil(m_interpreter);
617 lua_settable(m_interpreter, -3);
618 return *this;
619 }
620
621 template<class T>
operator =(T const & value)622 this_type& operator=(T const& value)
623 {
624 value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
625 detail::stack_pop pop(m_interpreter, 1);
626
627 lua_pushvalue(m_interpreter, m_key_index);
628 detail::push(m_interpreter, value);
629 lua_settable(m_interpreter, -3);
630 return *this;
631 }
632
operator =(this_type const & value)633 this_type& operator=(this_type const& value)
634 {
635 value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
636 detail::stack_pop pop(m_interpreter, 1);
637
638 lua_pushvalue(m_interpreter, m_key_index);
639 detail::push(m_interpreter, value);
640 lua_settable(m_interpreter, -3);
641 return *this;
642 }
643
644 template<class T>
operator [](T const & key)645 index_proxy<this_type> operator[](T const& key)
646 {
647 return index_proxy<this_type>(*this, m_interpreter, key);
648 }
649
650 void push(lua_State* interpreter);
651
interpreter() const652 lua_State* interpreter() const
653 {
654 return m_interpreter;
655 }
656
657 private:
658 struct hidden_type {};
659
660 // this_type& operator=(index_proxy<Next> const&);
661
662 mutable lua_State* m_interpreter;
663 int m_key_index;
664
665 Next const& m_next;
666 };
667
668 } // namespace adl
669
670 typedef detail::basic_iterator<detail::basic_access> iterator;
671 typedef detail::basic_iterator<detail::raw_access> raw_iterator;
672
673 #ifndef LUABIND_USE_VALUE_WRAPPER_TAG
674 template<class T>
675 struct value_wrapper_traits<adl::index_proxy<T> >
676 #else
677 template<>
678 struct value_wrapper_traits<adl::index_proxy_tag>
679 #endif
680 {
681 typedef boost::mpl::true_ is_specialized;
682
683 template<class Next>
interpreterluabind::value_wrapper_traits684 static lua_State* interpreter(adl::index_proxy<Next> const& proxy)
685 {
686 return proxy.interpreter();
687 }
688
689 template<class Next>
unwrapluabind::value_wrapper_traits690 static void unwrap(lua_State* interpreter, adl::index_proxy<Next> const& proxy)
691 {
692 const_cast<adl::index_proxy<Next>&>(proxy).push(interpreter);
693 }
694 };
695
696 #ifndef LUABIND_USE_VALUE_WRAPPER_TAG
697 template<class AccessPolicy>
698 struct value_wrapper_traits<adl::iterator_proxy<AccessPolicy> >
699 #else
700 template<>
701 struct value_wrapper_traits<adl::iterator_proxy_tag>
702 #endif
703 {
704 typedef boost::mpl::true_ is_specialized;
705
706 template<class Proxy>
interpreterluabind::value_wrapper_traits707 static lua_State* interpreter(Proxy const& p)
708 {
709 return p.interpreter();
710 }
711
712 template<class Proxy>
unwrapluabind::value_wrapper_traits713 static void unwrap(lua_State* interpreter, Proxy const& p)
714 {
715 // TODO: Why const_cast?
716 const_cast<Proxy&>(p).push(interpreter);
717 }
718 };
719
720 namespace adl
721 {
722
723 // An object holds a reference to a Lua value residing
724 // in the registry.
725 class object : public object_interface<object>
726 {
727 public:
object()728 object()
729 {}
730
object(handle const & other)731 explicit object(handle const& other)
732 : m_handle(other)
733 {}
734
object(from_stack const & stack_reference)735 explicit object(from_stack const& stack_reference)
736 : m_handle(stack_reference.interpreter, stack_reference.index)
737 {
738 }
739
740 template<class T>
object(lua_State * interpreter,T const & value)741 object(lua_State* interpreter, T const& value)
742 {
743 detail::push(interpreter, value);
744 detail::stack_pop pop(interpreter, 1);
745 handle(interpreter, -1).swap(m_handle);
746 }
747
748 template<class T, class Policies>
object(lua_State * interpreter,T const & value,Policies const &)749 object(lua_State* interpreter, T const& value, Policies const&)
750 {
751 detail::push(interpreter, value, Policies());
752 detail::stack_pop pop(interpreter, 1);
753 handle(interpreter, -1).swap(m_handle);
754 }
755
756 void push(lua_State* interpreter) const;
757 lua_State* interpreter() const;
758 bool is_valid() const;
759
760 template<class T>
operator [](T const & key) const761 index_proxy<object> operator[](T const& key) const
762 {
763 return index_proxy<object>(
764 *this, m_handle.interpreter(), key
765 );
766 }
767
swap(object & other)768 void swap(object& other)
769 {
770 m_handle.swap(other.m_handle);
771 }
772
773 private:
774 handle m_handle;
775 };
776
push(lua_State * interpreter) const777 inline void object::push(lua_State* interpreter) const
778 {
779 m_handle.push(interpreter);
780 }
781
interpreter() const782 inline lua_State* object::interpreter() const
783 {
784 return m_handle.interpreter();
785 }
786
is_valid() const787 inline bool object::is_valid() const
788 {
789 return m_handle.interpreter() != 0;
790 }
791
792 class argument : public object_interface<argument>
793 {
794 public:
argument(from_stack const & stack_reference)795 argument(from_stack const& stack_reference)
796 : m_interpreter(stack_reference.interpreter)
797 , m_index(stack_reference.index)
798 {
799 if (m_index < 0)
800 m_index = lua_gettop(m_interpreter) - m_index + 1;
801 }
802
803 template<class T>
operator [](T const & key) const804 index_proxy<argument> operator[](T const& key) const
805 {
806 return index_proxy<argument>(*this, m_interpreter, key);
807 }
808
push(lua_State * L) const809 void push(lua_State* L) const
810 {
811 lua_pushvalue(L, m_index);
812 }
813
interpreter() const814 lua_State* interpreter() const
815 {
816 return m_interpreter;
817 }
818
819 private:
820 lua_State* m_interpreter;
821 int m_index;
822 };
823
824 } // namespace adl
825
826 using adl::object;
827 using adl::argument;
828
829 #ifndef LUABIND_USE_VALUE_WRAPPER_TAG
830 template <class ValueWrapper, class Arguments>
831 struct value_wrapper_traits<adl::call_proxy<ValueWrapper, Arguments> >
832 #else
833 template<>
834 struct value_wrapper_traits<adl::call_proxy_tag>
835 #endif
836 {
837 typedef boost::mpl::true_ is_specialized;
838
839 template<class W, class A>
interpreterluabind::value_wrapper_traits840 static lua_State* interpreter(adl::call_proxy<W,A> const& proxy)
841 {
842 return value_wrapper_traits<W>::interpreter(*proxy.value_wrapper);
843 }
844
845 template<class W, class A>
unwrapluabind::value_wrapper_traits846 static void unwrap(lua_State*, adl::call_proxy<W,A> const& proxy)
847 {
848 object result = const_cast<adl::call_proxy<W,A>&>(proxy);
849 result.push(result.interpreter());
850 }
851 };
852
853 template<>
854 struct value_wrapper_traits<object>
855 {
856 typedef boost::mpl::true_ is_specialized;
857
interpreterluabind::value_wrapper_traits858 static lua_State* interpreter(object const& value)
859 {
860 return value.interpreter();
861 }
862
unwrapluabind::value_wrapper_traits863 static void unwrap(lua_State* interpreter, object const& value)
864 {
865 value.push(interpreter);
866 }
867
checkluabind::value_wrapper_traits868 static bool check(...)
869 {
870 return true;
871 }
872 };
873
874 template<>
875 struct value_wrapper_traits<argument>
876 {
877 typedef boost::mpl::true_ is_specialized;
878
interpreterluabind::value_wrapper_traits879 static lua_State* interpreter(argument const& value)
880 {
881 return value.interpreter();
882 }
883
unwrapluabind::value_wrapper_traits884 static void unwrap(lua_State* interpreter, argument const& value)
885 {
886 value.push(interpreter);
887 }
888
checkluabind::value_wrapper_traits889 static bool check(...)
890 {
891 return true;
892 }
893 };
894
895 template<class Next>
push(lua_State * interpreter)896 inline void adl::index_proxy<Next>::push(lua_State* interpreter)
897 {
898 assert(interpreter == m_interpreter);
899
900 value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
901
902 lua_pushvalue(m_interpreter, m_key_index);
903 lua_gettable(m_interpreter, -2);
904 lua_remove(m_interpreter, -2);
905 }
906
907 template<class Next>
operator object()908 inline adl::index_proxy<Next>::operator object()
909 {
910 detail::stack_pop pop(m_interpreter, 1);
911 push(m_interpreter);
912 return object(from_stack(m_interpreter, -1));
913 }
914
915 template<class AccessPolicy>
operator object()916 adl::iterator_proxy<AccessPolicy>::operator object()
917 {
918 lua_pushvalue(m_interpreter, m_key_index);
919 AccessPolicy::get(m_interpreter, m_table_index);
920 detail::stack_pop pop(m_interpreter, 1);
921 return object(from_stack(m_interpreter, -1));
922 }
923
924 template<class AccessPolicy>
key() const925 object detail::basic_iterator<AccessPolicy>::key() const
926 {
927 return object(m_key);
928 }
929
930 namespace detail
931 {
932
933 template<
934 class T
935 , class ValueWrapper
936 , class Policies
937 , class ErrorPolicy
938 , class ReturnType
939 >
object_cast_aux(ValueWrapper const & value_wrapper,T *,Policies *,ErrorPolicy *,ReturnType *)940 ReturnType object_cast_aux(
941 ValueWrapper const& value_wrapper
942 , T*
943 , Policies*
944 , ErrorPolicy*
945 , ReturnType*
946 )
947 {
948 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
949 value_wrapper
950 );
951
952 #ifndef LUABIND_NO_ERROR_CHECKING
953 if (!interpreter)
954 return ErrorPolicy::handle_error(interpreter, typeid(void));
955 #endif
956
957 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value_wrapper);
958
959 detail::stack_pop pop(interpreter, 1);
960
961 typedef typename detail::find_conversion_policy<
962 0
963 , Policies
964 >::type converter_generator;
965
966 typename mpl::apply_wrap2<converter_generator, T, lua_to_cpp>::type cv;
967
968 #ifndef LUABIND_NO_ERROR_CHECKING
969 if (cv.match(interpreter, LUABIND_DECORATE_TYPE(T), -1) < 0)
970 {
971 return ErrorPolicy::handle_error(interpreter, typeid(T));
972 }
973 #endif
974
975 return cv.apply(interpreter, LUABIND_DECORATE_TYPE(T), -1);
976 }
977
978 # ifdef BOOST_MSVC
979 # pragma warning(push)
980 # pragma warning(disable:4702) // unreachable code
981 # endif
982
983 template<class T>
984 struct throw_error_policy
985 {
handle_errorluabind::detail::throw_error_policy986 static T handle_error(lua_State* interpreter, type_id const& type_info)
987 {
988 #ifndef LUABIND_NO_EXCEPTIONS
989 throw cast_failed(interpreter, type_info);
990 #else
991 cast_failed_callback_fun e = get_cast_failed_callback();
992 if (e) e(interpreter, type_info);
993
994 assert(0 && "object_cast failed. If you want to handle this error use "
995 "luabind::set_error_callback()");
996 std::terminate();
997 #endif
998 return *(typename boost::remove_reference<T>::type*)0;
999 }
1000 };
1001
1002 # ifdef BOOST_MSVC
1003 # pragma warning(pop)
1004 # endif
1005
1006 template<class T>
1007 struct nothrow_error_policy
1008 {
handle_errorluabind::detail::nothrow_error_policy1009 static boost::optional<T> handle_error(lua_State*, type_id const&)
1010 {
1011 return boost::optional<T>();
1012 }
1013 };
1014
1015 } // namespace detail
1016
1017 template<class T, class ValueWrapper>
1018 T object_cast(ValueWrapper const& value_wrapper)
1019 {
1020 return detail::object_cast_aux(
1021 value_wrapper
1022 , (T*)0
1023 , (detail::null_type*)0
1024 , (detail::throw_error_policy<T>*)0
1025 , (T*)0
1026 );
1027 }
1028
1029 template<class T, class ValueWrapper, class Policies>
1030 T object_cast(ValueWrapper const& value_wrapper, Policies const&)
1031 {
1032 return detail::object_cast_aux(
1033 value_wrapper
1034 , (T*)0
1035 , (Policies*)0
1036 , (detail::throw_error_policy<T>*)0
1037 , (T*)0
1038 );
1039 }
1040
1041 template<class T, class ValueWrapper>
object_cast_nothrow(ValueWrapper const & value_wrapper)1042 boost::optional<T> object_cast_nothrow(ValueWrapper const& value_wrapper)
1043 {
1044 return detail::object_cast_aux(
1045 value_wrapper
1046 , (T*)0
1047 , (detail::null_type*)0
1048 , (detail::nothrow_error_policy<T>*)0
1049 , (boost::optional<T>*)0
1050 );
1051 }
1052
1053 template<class T, class ValueWrapper, class Policies>
object_cast_nothrow(ValueWrapper const & value_wrapper,Policies const &)1054 boost::optional<T> object_cast_nothrow(ValueWrapper const& value_wrapper, Policies const&)
1055 {
1056 return detail::object_cast_aux(
1057 value_wrapper
1058 , (T*)0
1059 , (Policies*)0
1060 , (detail::nothrow_error_policy<T>*)0
1061 , (boost::optional<T>*)0
1062 );
1063 }
1064
1065 namespace detail
1066 {
1067
1068 template<int Index>
1069 struct push_args_from_tuple
1070 {
1071 template<class H, class T, class Policies>
applyluabind::detail::push_args_from_tuple1072 inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x, const Policies& p)
1073 {
1074 convert_to_lua_p<Index>(L, *x.get_head(), p);
1075 push_args_from_tuple<Index+1>::apply(L, x.get_tail(), p);
1076 }
1077
1078 template<class H, class T>
applyluabind::detail::push_args_from_tuple1079 inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x)
1080 {
1081 convert_to_lua(L, *x.get_head());
1082 push_args_from_tuple<Index+1>::apply(L, x.get_tail());
1083 }
1084
1085 template<class Policies>
applyluabind::detail::push_args_from_tuple1086 inline static void apply(lua_State*, const boost::tuples::null_type&, const Policies&) {}
1087
applyluabind::detail::push_args_from_tuple1088 inline static void apply(lua_State*, const boost::tuples::null_type&) {}
1089 };
1090
1091 } // namespace detail
1092
1093 namespace adl
1094 {
1095
1096 template<class ValueWrapper, class Arguments>
1097 struct call_proxy
1098 {
call_proxyluabind::adl::call_proxy1099 call_proxy(ValueWrapper& value_wrapper, Arguments arguments)
1100 : value_wrapper(&value_wrapper)
1101 , arguments(arguments)
1102 {}
1103
call_proxyluabind::adl::call_proxy1104 call_proxy(call_proxy const& other)
1105 : value_wrapper(other.value_wrapper)
1106 , arguments(other.arguments)
1107 {
1108 other.value_wrapper = 0;
1109 }
1110
~call_proxyluabind::adl::call_proxy1111 ~call_proxy()
1112 {
1113 if (value_wrapper)
1114 call((detail::null_type*)0);
1115 }
1116
operator objectluabind::adl::call_proxy1117 operator object()
1118 {
1119 return call((detail::null_type*)0);
1120 }
1121
1122 template<class Policies>
operator []luabind::adl::call_proxy1123 object operator[](Policies const&)
1124 {
1125 return call((Policies*)0);
1126 }
1127
1128 template<class Policies>
callluabind::adl::call_proxy1129 object call(Policies*)
1130 {
1131 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1132 *value_wrapper
1133 );
1134
1135 value_wrapper_traits<ValueWrapper>::unwrap(
1136 interpreter
1137 , *value_wrapper
1138 );
1139
1140 value_wrapper = 0;
1141
1142 detail::push_args_from_tuple<1>::apply(interpreter, arguments, Policies());
1143
1144 if (detail::pcall(interpreter, boost::tuples::length<Arguments>::value, 1))
1145 {
1146 #ifndef LUABIND_NO_EXCEPTIONS
1147 throw luabind::error(interpreter);
1148 #else
1149 error_callback_fun e = get_error_callback();
1150 if (e) e(interpreter);
1151
1152 assert(0 && "the lua function threw an error and exceptions are disabled."
1153 "if you want to handle this error use luabind::set_error_callback()");
1154 std::terminate();
1155 #endif
1156 }
1157
1158 detail::stack_pop pop(interpreter, 1);
1159 return object(from_stack(interpreter, -1));
1160 }
1161
1162 mutable ValueWrapper* value_wrapper;
1163 Arguments arguments;
1164 };
1165
1166 template<class Derived>
1167 call_proxy<Derived, boost::tuples::tuple<> >
operator ()()1168 object_interface<Derived>::operator()()
1169 {
1170 return call_proxy<Derived, boost::tuples::tuple<> >(
1171 derived()
1172 , boost::tuples::tuple<>()
1173 );
1174 }
1175
1176 // Simple value_wrapper adaptor with the sole purpose of helping with
1177 // overload resolution. Use this as a function parameter type instead
1178 // of "object" or "argument" to restrict the parameter to Lua tables.
1179 template <class Base = object>
1180 struct table : Base
1181 {
tableluabind::adl::table1182 table(from_stack const& stack_reference)
1183 : Base(stack_reference)
1184 {}
1185 };
1186
1187 } // namespace adl
1188
1189 using adl::table;
1190
1191 template <class Base>
1192 struct value_wrapper_traits<adl::table<Base> >
1193 : value_wrapper_traits<Base>
1194 {
checkluabind::value_wrapper_traits1195 static bool check(lua_State* L, int idx)
1196 {
1197 return value_wrapper_traits<Base>::check(L, idx) &&
1198 lua_istable(L, idx);
1199 }
1200 };
1201
newtable(lua_State * interpreter)1202 inline object newtable(lua_State* interpreter)
1203 {
1204 lua_newtable(interpreter);
1205 detail::stack_pop pop(interpreter, 1);
1206 return object(from_stack(interpreter, -1));
1207 }
1208
1209 // this could be optimized by returning a proxy
globals(lua_State * interpreter)1210 inline object globals(lua_State* interpreter)
1211 {
1212 lua_pushvalue(interpreter, LUA_GLOBALSINDEX);
1213 detail::stack_pop pop(interpreter, 1);
1214 return object(from_stack(interpreter, -1));
1215 }
1216
1217 // this could be optimized by returning a proxy
registry(lua_State * interpreter)1218 inline object registry(lua_State* interpreter)
1219 {
1220 lua_pushvalue(interpreter, LUA_REGISTRYINDEX);
1221 detail::stack_pop pop(interpreter, 1);
1222 return object(from_stack(interpreter, -1));
1223 }
1224
1225 template<class ValueWrapper, class K>
gettable(ValueWrapper const & table,K const & key)1226 inline object gettable(ValueWrapper const& table, K const& key)
1227 {
1228 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1229 table
1230 );
1231
1232 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
1233 detail::stack_pop pop(interpreter, 2);
1234 detail::push(interpreter, key);
1235 lua_gettable(interpreter, -2);
1236 return object(from_stack(interpreter, -1));
1237 }
1238
1239 template<class ValueWrapper, class K, class T>
settable(ValueWrapper const & table,K const & key,T const & value)1240 inline void settable(ValueWrapper const& table, K const& key, T const& value)
1241 {
1242 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1243 table
1244 );
1245
1246 // TODO: Exception safe?
1247
1248 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
1249 detail::stack_pop pop(interpreter, 1);
1250 detail::push(interpreter, key);
1251 detail::push(interpreter, value);
1252 lua_settable(interpreter, -3);
1253 }
1254
1255 template<class ValueWrapper, class K>
rawget(ValueWrapper const & table,K const & key)1256 inline object rawget(ValueWrapper const& table, K const& key)
1257 {
1258 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1259 table
1260 );
1261
1262 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
1263 detail::stack_pop pop(interpreter, 2);
1264 detail::push(interpreter, key);
1265 lua_rawget(interpreter, -2);
1266 return object(from_stack(interpreter, -1));
1267 }
1268
1269 template<class ValueWrapper, class K, class T>
rawset(ValueWrapper const & table,K const & key,T const & value)1270 inline void rawset(ValueWrapper const& table, K const& key, T const& value)
1271 {
1272 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1273 table
1274 );
1275
1276 // TODO: Exception safe?
1277
1278 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
1279 detail::stack_pop pop(interpreter, 1);
1280 detail::push(interpreter, key);
1281 detail::push(interpreter, value);
1282 lua_rawset(interpreter, -3);
1283 }
1284
1285 template<class ValueWrapper>
type(ValueWrapper const & value)1286 inline int type(ValueWrapper const& value)
1287 {
1288 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1289 value
1290 );
1291
1292 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
1293 detail::stack_pop pop(interpreter, 1);
1294 return lua_type(interpreter, -1);
1295 }
1296
1297 template <class ValueWrapper>
getmetatable(ValueWrapper const & obj)1298 inline object getmetatable(ValueWrapper const& obj)
1299 {
1300 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1301 obj
1302 );
1303
1304 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, obj);
1305 detail::stack_pop pop(interpreter, 2);
1306 lua_getmetatable(interpreter, -1);
1307 return object(from_stack(interpreter, -1));
1308 }
1309
1310 template <class ValueWrapper1, class ValueWrapper2>
setmetatable(ValueWrapper1 const & obj,ValueWrapper2 const & metatable)1311 inline void setmetatable(
1312 ValueWrapper1 const& obj, ValueWrapper2 const& metatable)
1313 {
1314 lua_State* interpreter = value_wrapper_traits<ValueWrapper1>::interpreter(
1315 obj
1316 );
1317
1318 value_wrapper_traits<ValueWrapper1>::unwrap(interpreter, obj);
1319 detail::stack_pop pop(interpreter, 1);
1320 value_wrapper_traits<ValueWrapper2>::unwrap(interpreter, metatable);
1321 lua_setmetatable(interpreter, -2);
1322 }
1323
1324 template <class ValueWrapper>
tocfunction(ValueWrapper const & value)1325 inline lua_CFunction tocfunction(ValueWrapper const& value)
1326 {
1327 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1328 value
1329 );
1330
1331 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
1332 detail::stack_pop pop(interpreter, 1);
1333 return lua_tocfunction(interpreter, -1);
1334 }
1335
1336 template <class T, class ValueWrapper>
touserdata(ValueWrapper const & value)1337 inline T* touserdata(ValueWrapper const& value)
1338 {
1339 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1340 value
1341 );
1342
1343 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
1344 detail::stack_pop pop(interpreter, 1);
1345 return static_cast<T*>(lua_touserdata(interpreter, -1));
1346 }
1347
1348 template <class ValueWrapper>
getupvalue(ValueWrapper const & value,int index)1349 inline object getupvalue(ValueWrapper const& value, int index)
1350 {
1351 lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
1352 value
1353 );
1354
1355 value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
1356 detail::stack_pop pop(interpreter, 2);
1357 lua_getupvalue(interpreter, -1, index);
1358 return object(from_stack(interpreter, -1));
1359 }
1360
1361 template <class ValueWrapper1, class ValueWrapper2>
setupvalue(ValueWrapper1 const & function,int index,ValueWrapper2 const & value)1362 inline void setupvalue(
1363 ValueWrapper1 const& function, int index, ValueWrapper2 const& value)
1364 {
1365 lua_State* interpreter = value_wrapper_traits<ValueWrapper1>::interpreter(
1366 function
1367 );
1368
1369 value_wrapper_traits<ValueWrapper1>::unwrap(interpreter, function);
1370 detail::stack_pop pop(interpreter, 1);
1371 value_wrapper_traits<ValueWrapper2>::unwrap(interpreter, value);
1372 lua_setupvalue(interpreter, -2, index);
1373 }
1374
1375 template <class GetValueWrapper>
property(GetValueWrapper const & get)1376 object property(GetValueWrapper const& get)
1377 {
1378 lua_State* interpreter = value_wrapper_traits<GetValueWrapper>::interpreter(
1379 get
1380 );
1381
1382 value_wrapper_traits<GetValueWrapper>::unwrap(interpreter, get);
1383 lua_pushnil(interpreter);
1384
1385 lua_pushcclosure(interpreter, &detail::property_tag, 2);
1386 detail::stack_pop pop(interpreter, 1);
1387
1388 return object(from_stack(interpreter, -1));
1389 }
1390
1391 template <class GetValueWrapper, class SetValueWrapper>
property(GetValueWrapper const & get,SetValueWrapper const & set)1392 object property(GetValueWrapper const& get, SetValueWrapper const& set)
1393 {
1394 lua_State* interpreter = value_wrapper_traits<GetValueWrapper>::interpreter(
1395 get
1396 );
1397
1398 value_wrapper_traits<GetValueWrapper>::unwrap(interpreter, get);
1399 value_wrapper_traits<SetValueWrapper>::unwrap(interpreter, set);
1400
1401 lua_pushcclosure(interpreter, &detail::property_tag, 2);
1402 detail::stack_pop pop(interpreter, 1);
1403
1404 return object(from_stack(interpreter, -1));
1405
1406 }
1407
1408
1409 } // namespace luabind
1410
1411 #endif // LUABIND_OBJECT_050419_HPP
1412
1413