| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470 |
- // Copyright (c) 2005 Daniel Wallin and Arvid Norberg
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the "Software"),
- // to deal in the Software without restriction, including without limitation
- // the rights to use, copy, modify, merge, publish, distribute, sublicense,
- // and/or sell copies of the Software, and to permit persons to whom the
- // Software is furnished to do so, subject to the following conditions:
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
- // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
- // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
- // OR OTHER DEALINGS IN THE SOFTWARE.
- #ifndef LUABIND_OBJECT_050419_HPP
- #define LUABIND_OBJECT_050419_HPP
- #include <boost/implicit_cast.hpp> // detail::push()
- #include <boost/ref.hpp> // detail::push()
- #include <boost/mpl/bool.hpp> // value_wrapper_traits specializations
- #include <boost/mpl/apply_wrap.hpp>
- #ifdef LUABIND_CPP0x
- # include <tuple>
- #else
- # include <boost/tuple/tuple.hpp>
- #endif
- #include <boost/optional.hpp>
- #include <luabind/nil.hpp>
- #include <luabind/value_wrapper.hpp>
- #include <luabind/detail/pcall.hpp>
- #include <luabind/handle.hpp>
- #include <luabind/from_stack.hpp>
- #include <luabind/detail/policy.hpp>
- #include <luabind/detail/stack_utils.hpp>
- #include <luabind/detail/convert_to_lua.hpp> // REFACTOR
- #include <luabind/typeid.hpp>
- #include <boost/iterator/iterator_facade.hpp> // iterator
- #ifndef LUABIND_CPP0x
- #include <boost/preprocessor/iteration/iterate.hpp>
- #endif
- #include <boost/utility/enable_if.hpp>
- namespace luabind {
- namespace detail
- {
- namespace mpl = boost::mpl;
-
- template<class T, class ConverterGenerator>
- void push_aux(lua_State* interpreter, T& value, ConverterGenerator*)
- {
- typedef typename boost::mpl::if_<
- boost::is_reference_wrapper<T>
- , BOOST_DEDUCED_TYPENAME boost::unwrap_reference<T>::type&
- , T
- >::type unwrapped_type;
- typename mpl::apply_wrap2<
- ConverterGenerator,unwrapped_type,cpp_to_lua
- >::type cv;
- cv.apply(
- interpreter
- , boost::implicit_cast<
- BOOST_DEDUCED_TYPENAME boost::unwrap_reference<T>::type&
- >(value)
- );
- }
- template<class T, class Policies>
- void push(lua_State* interpreter, T& value, Policies const&)
- {
- typedef typename find_conversion_policy<
- 0
- , Policies
- >::type converter_policy;
- push_aux(interpreter, value, (converter_policy*)0);
- }
- template<class T>
- void push(lua_State* interpreter, T& value)
- {
- push(interpreter, value, null_type());
- }
- } // namespace detail
- namespace adl
- {
- namespace mpl = boost::mpl;
-
- template <class T>
- class object_interface;
-
- namespace is_object_interface_aux
- {
- typedef char (&yes)[1];
- typedef char (&no)[2];
-
- template <class T>
- yes check(object_interface<T>*);
- no check(void*);
- template <class T>
- struct impl
- {
- BOOST_STATIC_CONSTANT(bool, value =
- sizeof(is_object_interface_aux::check((T*)0)) == sizeof(yes)
- );
- typedef mpl::bool_<value> type;
- };
- } // namespace detail
- template <class T>
- struct is_object_interface
- : is_object_interface_aux::impl<T>::type
- {};
- template <class R, class T, class U>
- struct enable_binary
- # ifndef BOOST_NO_SFINAE
- : boost::enable_if<
- mpl::or_<
- is_object_interface<T>
- , is_object_interface<U>
- >
- , R
- >
- {};
- # else
- {
- typedef R type;
- };
- # endif
- template<class T, class U>
- int binary_interpreter(lua_State*& L, T const& lhs, U const& rhs
- , boost::mpl::true_, boost::mpl::true_)
- {
- L = value_wrapper_traits<T>::interpreter(lhs);
- lua_State* L2 = value_wrapper_traits<U>::interpreter(rhs);
- // you are comparing objects with different interpreters
- // that's not allowed.
- assert(L == L2 || L == 0 || L2 == 0);
- // if the two objects we compare have different interpreters
- // then they
- if (L != L2) return -1;
- if (L == 0) return 1;
- return 0;
- }
-
- template<class T, class U>
- int binary_interpreter(lua_State*& L, T const& x, U const&
- , boost::mpl::true_, boost::mpl::false_)
- {
- L = value_wrapper_traits<T>::interpreter(x);
- return 0;
- }
- template<class T, class U>
- int binary_interpreter(lua_State*& L, T const&, U const& x, boost::mpl::false_, boost::mpl::true_)
- {
- L = value_wrapper_traits<U>::interpreter(x);
- return 0;
- }
- template<class T, class U>
- int binary_interpreter(lua_State*& L, T const& x, U const& y)
- {
- return binary_interpreter(
- L
- , x
- , y
- , is_value_wrapper<T>()
- , is_value_wrapper<U>()
- );
- }
- #define LUABIND_BINARY_OP_DEF(op, fn) \
- template<class LHS, class RHS> \
- typename enable_binary<bool,LHS,RHS>::type \
- operator op(LHS const& lhs, RHS const& rhs) \
- { \
- lua_State* L = 0; \
- switch (binary_interpreter(L, lhs, rhs)) \
- { \
- case 1: \
- return true; \
- case -1: \
- return false; \
- } \
- \
- assert(L); \
- \
- detail::stack_pop pop1(L, 1); \
- detail::push(L, lhs); \
- detail::stack_pop pop2(L, 1); \
- detail::push(L, rhs); \
- \
- return fn(L, -1, -2) != 0; \
- }
- LUABIND_BINARY_OP_DEF(==, lua_equal)
- LUABIND_BINARY_OP_DEF(<, lua_lessthan)
- template<class ValueWrapper>
- std::ostream& operator<<(std::ostream& os
- , object_interface<ValueWrapper> const& v)
- {
- using namespace luabind;
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- static_cast<ValueWrapper const&>(v));
- detail::stack_pop pop(interpreter, 1);
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter
- , static_cast<ValueWrapper const&>(v));
- char const* p = lua_tostring(interpreter, -1);
- std::size_t len = lua_strlen(interpreter, -1);
- std::copy(p, p + len, std::ostream_iterator<char>(os));
- return os;
- }
- #undef LUABIND_BINARY_OP_DEF
- template<class LHS, class RHS>
- typename enable_binary<bool,LHS,RHS>::type
- operator>(LHS const& lhs, RHS const& rhs)
- {
- return !(lhs < rhs || lhs == rhs);
- }
- template<class LHS, class RHS>
- typename enable_binary<bool,LHS,RHS>::type
- operator<=(LHS const& lhs, RHS const& rhs)
- {
- return lhs < rhs || lhs == rhs;
- }
- template<class LHS, class RHS>
- typename enable_binary<bool,LHS,RHS>::type
- operator>=(LHS const& lhs, RHS const& rhs)
- {
- return !(lhs < rhs);
- }
- template<class LHS, class RHS>
- typename enable_binary<bool,LHS,RHS>::type
- operator!=(LHS const& lhs, RHS const& rhs)
- {
- return !(lhs == rhs);
- }
- template<class ValueWrapper, class Arguments>
- struct call_proxy;
- template<class Next>
- class index_proxy;
- class object;
-
- template<class Derived>
- class object_interface
- {
- struct safe_bool_type {};
- public:
- ~object_interface() {}
- # ifdef LUABIND_CPP0x
- template <class... Args>
- call_proxy<
- Derived, std::tuple<Args const*...>
- > operator()(Args const& ...args)
- {
- typedef std::tuple<Args const*...> arguments;
- return call_proxy<Derived, arguments>(derived(), arguments(&args...));
- }
- # else
- call_proxy<Derived, boost::tuples::tuple<> > operator()();
- template<class A0>
- call_proxy<
- Derived
- , boost::tuples::tuple<A0 const*>
- > operator()(A0 const& a0)
- {
- typedef boost::tuples::tuple<A0 const*> arguments;
- return call_proxy<Derived, arguments>(
- derived()
- , arguments(&a0)
- );
- }
- template<class A0, class A1>
- call_proxy<
- Derived
- , boost::tuples::tuple<A0 const*, A1 const*>
- > operator()(A0 const& a0, A1 const& a1)
- {
- typedef boost::tuples::tuple<A0 const*, A1 const*> arguments;
- return call_proxy<Derived, arguments>(
- derived()
- , arguments(&a0, &a1)
- );
- }
- // The rest of the overloads are PP-generated.
- #define BOOST_PP_ITERATION_PARAMS_1 (3, \
- (3, LUABIND_MAX_ARITY, <luabind/detail/object_call.hpp>))
- #include BOOST_PP_ITERATE()
- # endif // LUABIND_CPP0x
- operator safe_bool_type*() const
- {
- lua_State* L = value_wrapper_traits<Derived>::interpreter(derived());
- if (!L)
- return 0;
- value_wrapper_traits<Derived>::unwrap(L, derived());
- detail::stack_pop pop(L, 1);
- return lua_toboolean(L, -1) == 1 ? (safe_bool_type*)1 : 0;
- }
- private:
- Derived& derived()
- {
- return *static_cast<Derived*>(this);
- }
- Derived const& derived() const
- {
- return *static_cast<Derived const*>(this);
- }
- };
- #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
- struct iterator_proxy_tag;
- #endif
-
- template<class AccessPolicy>
- class iterator_proxy
- : public object_interface<iterator_proxy<AccessPolicy> >
- {
- public:
- #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
- typedef iterator_proxy_tag value_wrapper_tag;
- #endif
- iterator_proxy(lua_State* interpreter, handle const& table, handle const& key)
- : m_interpreter(interpreter)
- , m_table_index(lua_gettop(interpreter) + 1)
- , m_key_index(m_table_index + 1)
- {
- table.push(m_interpreter);
- key.push(m_interpreter);
- }
- iterator_proxy(iterator_proxy const& other)
- : m_interpreter(other.m_interpreter)
- , m_table_index(other.m_table_index)
- , m_key_index(other.m_key_index)
- {
- other.m_interpreter = 0;
- }
- ~iterator_proxy()
- {
- if (m_interpreter)
- lua_pop(m_interpreter, 2);
- }
- // this will set the value to nil
- iterator_proxy & operator=(luabind::detail::nil_type)
- {
- lua_pushvalue(m_interpreter, m_key_index);
- lua_pushnil(m_interpreter);
- AccessPolicy::set(m_interpreter, m_table_index);
- return *this;
- }
- template<class T>
- iterator_proxy& operator=(T const& value)
- {
- lua_pushvalue(m_interpreter, m_key_index);
- detail::push(m_interpreter, value);
- AccessPolicy::set(m_interpreter, m_table_index);
- return *this;
- }
- template<class Key>
- index_proxy<iterator_proxy<AccessPolicy> > operator[](Key const& key)
- {
- return index_proxy<iterator_proxy<AccessPolicy> >(
- *this, m_interpreter, key
- );
- }
- // This is non-const to prevent conversion on lvalues.
- operator object();
- lua_State* interpreter() const
- {
- return m_interpreter;
- }
- // TODO: Why is it non-const?
- void push(lua_State* interpreter)
- {
- assert(interpreter == m_interpreter);
- lua_pushvalue(m_interpreter, m_key_index);
- AccessPolicy::get(m_interpreter, m_table_index);
- }
- private:
- mutable lua_State* m_interpreter;
- int m_table_index;
- int m_key_index;
- };
- } // namespace adl
- namespace detail
- {
- struct basic_access
- {
- static void set(lua_State* interpreter, int table)
- {
- lua_settable(interpreter, table);
- }
- static void get(lua_State* interpreter, int table)
- {
- lua_gettable(interpreter, table);
- }
- };
- struct raw_access
- {
- static void set(lua_State* interpreter, int table)
- {
- lua_rawset(interpreter, table);
- }
- static void get(lua_State* interpreter, int table)
- {
- lua_rawget(interpreter, table);
- }
- };
- template<class AccessPolicy>
- class basic_iterator
- : public boost::iterator_facade<
- basic_iterator<AccessPolicy>
- , adl::iterator_proxy<AccessPolicy>
- , boost::single_pass_traversal_tag
- , adl::iterator_proxy<AccessPolicy>
- >
- {
- public:
- basic_iterator()
- : m_interpreter(0)
- {}
- template<class ValueWrapper>
- explicit basic_iterator(ValueWrapper const& value_wrapper)
- : m_interpreter(
- value_wrapper_traits<ValueWrapper>::interpreter(value_wrapper)
- )
- {
- detail::stack_pop pop(m_interpreter, 1);
- value_wrapper_traits<ValueWrapper>::unwrap(m_interpreter, value_wrapper);
- lua_pushnil(m_interpreter);
- if (lua_next(m_interpreter, -2) != 0)
- {
- detail::stack_pop pop(m_interpreter, 2);
- handle(m_interpreter, -2).swap(m_key);
- }
- else
- {
- m_interpreter = 0;
- return;
- }
- handle(m_interpreter, -1).swap(m_table);
- }
- adl::object key() const;
- private:
- friend class boost::iterator_core_access;
- void increment()
- {
- m_table.push(m_interpreter);
- m_key.push(m_interpreter);
- detail::stack_pop pop(m_interpreter, 1);
- if (lua_next(m_interpreter, -2) != 0)
- {
- m_key.replace(m_interpreter, -2);
- lua_pop(m_interpreter, 2);
- }
- else
- {
- m_interpreter = 0;
- handle().swap(m_table);
- handle().swap(m_key);
- }
- }
- bool equal(basic_iterator const& other) const
- {
- if (m_interpreter == 0 && other.m_interpreter == 0)
- return true;
- if (m_interpreter != other.m_interpreter)
- return false;
- detail::stack_pop pop(m_interpreter, 2);
- m_key.push(m_interpreter);
- other.m_key.push(m_interpreter);
- return lua_equal(m_interpreter, -2, -1) != 0;
- }
- adl::iterator_proxy<AccessPolicy> dereference() const
- {
- return adl::iterator_proxy<AccessPolicy>(m_interpreter, m_table, m_key);
- }
- lua_State* m_interpreter;
- handle m_table;
- handle m_key;
- };
- // Needed because of some strange ADL issues.
- /*#define LUABIND_OPERATOR_ADL_WKND(op) \
- inline bool operator op( \
- basic_iterator<basic_access> const& x \
- , basic_iterator<basic_access> const& y) \
- { \
- return boost::operator op(x, y); \
- } \
- \
- inline bool operator op( \
- basic_iterator<raw_access> const& x \
- , basic_iterator<raw_access> const& y) \
- { \
- return boost::operator op(x, y); \
- }
- LUABIND_OPERATOR_ADL_WKND(==)
- LUABIND_OPERATOR_ADL_WKND(!=)
- #undef LUABIND_OPERATOR_ADL_WKND
- */
- } // namespace detail
- namespace adl
- {
-
- #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
- struct index_proxy_tag;
- #endif
- template<class Next>
- class index_proxy
- : public object_interface<index_proxy<Next> >
- {
- public:
- #ifdef LUABIND_USE_VALUE_WRAPPER_TAG
- typedef index_proxy_tag value_wrapper_tag;
- #endif
- typedef index_proxy<Next> this_type;
- template<class Key>
- index_proxy(Next const& next, lua_State* interpreter, Key const& key)
- : m_interpreter(interpreter)
- , m_key_index(lua_gettop(interpreter) + 1)
- , m_next(next)
- {
- detail::push(m_interpreter, key);
- }
- index_proxy(index_proxy const& other)
- : m_interpreter(other.m_interpreter)
- , m_key_index(other.m_key_index)
- , m_next(other.m_next)
- {
- other.m_interpreter = 0;
- }
- ~index_proxy()
- {
- if (m_interpreter)
- lua_pop(m_interpreter, 1);
- }
- // This is non-const to prevent conversion on lvalues.
- operator object();
- // this will set the value to nil
- this_type& operator=(luabind::detail::nil_type)
- {
- value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
- detail::stack_pop pop(m_interpreter, 1);
- lua_pushvalue(m_interpreter, m_key_index);
- lua_pushnil(m_interpreter);
- lua_settable(m_interpreter, -3);
- return *this;
- }
-
- template<class T>
- this_type& operator=(T const& value)
- {
- value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
- detail::stack_pop pop(m_interpreter, 1);
- lua_pushvalue(m_interpreter, m_key_index);
- detail::push(m_interpreter, value);
- lua_settable(m_interpreter, -3);
- return *this;
- }
- this_type& operator=(this_type const& value)
- {
- value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
- detail::stack_pop pop(m_interpreter, 1);
- lua_pushvalue(m_interpreter, m_key_index);
- detail::push(m_interpreter, value);
- lua_settable(m_interpreter, -3);
- return *this;
- }
- template<class T>
- index_proxy<this_type> operator[](T const& key)
- {
- return index_proxy<this_type>(*this, m_interpreter, key);
- }
- void push(lua_State* interpreter);
- lua_State* interpreter() const
- {
- return m_interpreter;
- }
- private:
- struct hidden_type {};
-
- // this_type& operator=(index_proxy<Next> const&);
- mutable lua_State* m_interpreter;
- int m_key_index;
- Next const& m_next;
- };
- } // namespace adl
- typedef detail::basic_iterator<detail::basic_access> iterator;
- typedef detail::basic_iterator<detail::raw_access> raw_iterator;
- #ifndef LUABIND_USE_VALUE_WRAPPER_TAG
- template<class T>
- struct value_wrapper_traits<adl::index_proxy<T> >
- #else
- template<>
- struct value_wrapper_traits<adl::index_proxy_tag>
- #endif
- {
- typedef boost::mpl::true_ is_specialized;
- template<class Next>
- static lua_State* interpreter(adl::index_proxy<Next> const& proxy)
- {
- return proxy.interpreter();
- }
- template<class Next>
- static void unwrap(lua_State* interpreter, adl::index_proxy<Next> const& proxy)
- {
- const_cast<adl::index_proxy<Next>&>(proxy).push(interpreter);
- }
- };
- #ifndef LUABIND_USE_VALUE_WRAPPER_TAG
- template<class AccessPolicy>
- struct value_wrapper_traits<adl::iterator_proxy<AccessPolicy> >
- #else
- template<>
- struct value_wrapper_traits<adl::iterator_proxy_tag>
- #endif
- {
- typedef boost::mpl::true_ is_specialized;
- template<class Proxy>
- static lua_State* interpreter(Proxy const& p)
- {
- return p.interpreter();
- }
- template<class Proxy>
- static void unwrap(lua_State* interpreter, Proxy const& p)
- {
- // TODO: Why const_cast?
- const_cast<Proxy&>(p).push(interpreter);
- }
- };
- namespace adl
- {
- // An object holds a reference to a Lua value residing
- // in the registry.
- class object : public object_interface<object>
- {
- public:
- object()
- {}
- explicit object(handle const& other)
- : m_handle(other)
- {}
- explicit object(from_stack const& stack_reference)
- : m_handle(stack_reference.interpreter, stack_reference.index)
- {
- }
- template<class T>
- object(lua_State* interpreter, T const& value)
- {
- detail::push(interpreter, value);
- detail::stack_pop pop(interpreter, 1);
- handle(interpreter, -1).swap(m_handle);
- }
- template<class T, class Policies>
- object(lua_State* interpreter, T const& value, Policies const&)
- {
- detail::push(interpreter, value, Policies());
- detail::stack_pop pop(interpreter, 1);
- handle(interpreter, -1).swap(m_handle);
- }
- void push(lua_State* interpreter) const;
- lua_State* interpreter() const;
- bool is_valid() const;
- template<class T>
- index_proxy<object> operator[](T const& key) const
- {
- return index_proxy<object>(
- *this, m_handle.interpreter(), key
- );
- }
- void swap(object& other)
- {
- m_handle.swap(other.m_handle);
- }
- private:
- handle m_handle;
- };
- inline void object::push(lua_State* interpreter) const
- {
- m_handle.push(interpreter);
- }
- inline lua_State* object::interpreter() const
- {
- return m_handle.interpreter();
- }
- inline bool object::is_valid() const
- {
- return m_handle.interpreter() != 0;
- }
- class argument : public object_interface<argument>
- {
- public:
- argument(from_stack const& stack_reference)
- : m_interpreter(stack_reference.interpreter)
- , m_index(stack_reference.index)
- {
- if (m_index < 0)
- m_index = lua_gettop(m_interpreter) - m_index + 1;
- }
- template<class T>
- index_proxy<argument> operator[](T const& key) const
- {
- return index_proxy<argument>(*this, m_interpreter, key);
- }
- void push(lua_State* L) const
- {
- lua_pushvalue(L, m_index);
- }
- lua_State* interpreter() const
- {
- return m_interpreter;
- }
- private:
- lua_State* m_interpreter;
- int m_index;
- };
- } // namespace adl
- using adl::object;
- using adl::argument;
- #ifndef LUABIND_USE_VALUE_WRAPPER_TAG
- template <class ValueWrapper, class Arguments>
- struct value_wrapper_traits<adl::call_proxy<ValueWrapper, Arguments> >
- #else
- template<>
- struct value_wrapper_traits<adl::call_proxy_tag>
- #endif
- {
- typedef boost::mpl::true_ is_specialized;
- template<class W, class A>
- static lua_State* interpreter(adl::call_proxy<W,A> const& proxy)
- {
- return value_wrapper_traits<W>::interpreter(*proxy.value_wrapper);
- }
- template<class W, class A>
- static void unwrap(lua_State*, adl::call_proxy<W,A> const& proxy)
- {
- object result = const_cast<adl::call_proxy<W,A>&>(proxy);
- result.push(result.interpreter());
- }
- };
- template<>
- struct value_wrapper_traits<object>
- {
- typedef boost::mpl::true_ is_specialized;
- static lua_State* interpreter(object const& value)
- {
- return value.interpreter();
- }
- static void unwrap(lua_State* interpreter, object const& value)
- {
- value.push(interpreter);
- }
- static bool check(...)
- {
- return true;
- }
- };
- template<>
- struct value_wrapper_traits<argument>
- {
- typedef boost::mpl::true_ is_specialized;
- static lua_State* interpreter(argument const& value)
- {
- return value.interpreter();
- }
- static void unwrap(lua_State* interpreter, argument const& value)
- {
- value.push(interpreter);
- }
- static bool check(...)
- {
- return true;
- }
- };
- template<class Next>
- inline void adl::index_proxy<Next>::push(lua_State* interpreter)
- {
- assert(interpreter == m_interpreter);
- value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
- lua_pushvalue(m_interpreter, m_key_index);
- lua_gettable(m_interpreter, -2);
- lua_remove(m_interpreter, -2);
- }
- template<class Next>
- inline adl::index_proxy<Next>::operator object()
- {
- detail::stack_pop pop(m_interpreter, 1);
- push(m_interpreter);
- return object(from_stack(m_interpreter, -1));
- }
- template<class AccessPolicy>
- adl::iterator_proxy<AccessPolicy>::operator object()
- {
- lua_pushvalue(m_interpreter, m_key_index);
- AccessPolicy::get(m_interpreter, m_table_index);
- detail::stack_pop pop(m_interpreter, 1);
- return object(from_stack(m_interpreter, -1));
- }
- template<class AccessPolicy>
- object detail::basic_iterator<AccessPolicy>::key() const
- {
- return object(m_key);
- }
- namespace detail
- {
- template<
- class T
- , class ValueWrapper
- , class Policies
- , class ErrorPolicy
- , class ReturnType
- >
- ReturnType object_cast_aux(
- ValueWrapper const& value_wrapper
- , T*
- , Policies*
- , ErrorPolicy*
- , ReturnType*
- )
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- value_wrapper
- );
- #ifndef LUABIND_NO_ERROR_CHECKING
- if (!interpreter)
- return ErrorPolicy::handle_error(interpreter, typeid(void));
- #endif
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value_wrapper);
- detail::stack_pop pop(interpreter, 1);
- typedef typename detail::find_conversion_policy<
- 0
- , Policies
- >::type converter_generator;
- typename mpl::apply_wrap2<converter_generator, T, lua_to_cpp>::type cv;
- if (cv.match(interpreter, LUABIND_DECORATE_TYPE(T), -1) < 0)
- {
- return ErrorPolicy::handle_error(interpreter, typeid(T));
- }
- return cv.apply(interpreter, LUABIND_DECORATE_TYPE(T), -1);
- }
- # ifdef BOOST_MSVC
- # pragma warning(push)
- # pragma warning(disable:4702) // unreachable code
- # endif
- template<class T>
- struct throw_error_policy
- {
- static T handle_error(lua_State* interpreter, type_id const& type_info)
- {
- #ifndef LUABIND_NO_EXCEPTIONS
- throw cast_failed(interpreter, type_info);
- #else
- cast_failed_callback_fun e = get_cast_failed_callback();
- if (e) e(interpreter, type_info);
- assert(0 && "object_cast failed. If you want to handle this error use "
- "luabind::set_error_callback()");
- std::terminate();
- #endif
- return *(typename boost::remove_reference<T>::type*)0;
- }
- };
- # ifdef BOOST_MSVC
- # pragma warning(pop)
- # endif
- template<class T>
- struct nothrow_error_policy
- {
- static boost::optional<T> handle_error(lua_State*, type_id const&)
- {
- return boost::optional<T>();
- }
- };
- } // namespace detail
- template<class T, class ValueWrapper>
- T object_cast(ValueWrapper const& value_wrapper)
- {
- return detail::object_cast_aux(
- value_wrapper
- , (T*)0
- , (detail::null_type*)0
- , (detail::throw_error_policy<T>*)0
- , (T*)0
- );
- }
- template<class T, class ValueWrapper, class Policies>
- T object_cast(ValueWrapper const& value_wrapper, Policies const&)
- {
- return detail::object_cast_aux(
- value_wrapper
- , (T*)0
- , (Policies*)0
- , (detail::throw_error_policy<T>*)0
- , (T*)0
- );
- }
- template<class T, class ValueWrapper>
- boost::optional<T> object_cast_nothrow(ValueWrapper const& value_wrapper)
- {
- return detail::object_cast_aux(
- value_wrapper
- , (T*)0
- , (detail::null_type*)0
- , (detail::nothrow_error_policy<T>*)0
- , (boost::optional<T>*)0
- );
- }
- template<class T, class ValueWrapper, class Policies>
- boost::optional<T> object_cast_nothrow(ValueWrapper const& value_wrapper, Policies const&)
- {
- return detail::object_cast_aux(
- value_wrapper
- , (T*)0
- , (Policies*)0
- , (detail::nothrow_error_policy<T>*)0
- , (boost::optional<T>*)0
- );
- }
- namespace detail
- {
- template<int Index>
- struct push_args_from_tuple
- {
- # ifdef LUABIND_CPP0x
- template <class Args, class Policies, class N, class E>
- static void push_args(
- lua_State* L, Args const& args, Policies const& policies, N, E)
- {
- convert_to_lua_p<N::value + 1>(L, *std::get<N::value>(args), policies);
- push_args(
- L, args, policies, std::integral_constant<int, N::value + 1>(), E());
- }
- template <class Args, class Policies, class E>
- static void push_args(lua_State* L, Args const&, Policies const&, E, E)
- {}
- template <class... Args, class Policies = null_type>
- static void apply(
- lua_State* L, std::tuple<Args...> const& args
- , Policies const policies = Policies())
- {
- push_args(
- L
- , args
- , policies
- , std::integral_constant<int, 0>()
- , std::integral_constant<int, sizeof...(Args)>()
- );
- }
- # else // LUABIND_CPP0x
- template<class H, class T, class Policies>
- inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x, const Policies& p)
- {
- convert_to_lua_p<Index>(L, *x.get_head(), p);
- push_args_from_tuple<Index+1>::apply(L, x.get_tail(), p);
- }
- template<class H, class T>
- inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x)
- {
- convert_to_lua(L, *x.get_head());
- push_args_from_tuple<Index+1>::apply(L, x.get_tail());
- }
- template<class Policies>
- inline static void apply(lua_State*, const boost::tuples::null_type&, const Policies&) {}
- inline static void apply(lua_State*, const boost::tuples::null_type&) {}
- # endif // LUABIND_CPP0x
- };
- } // namespace detail
- namespace adl
- {
- template<class ValueWrapper, class Arguments>
- struct call_proxy
- {
- call_proxy(ValueWrapper& value_wrapper, Arguments arguments)
- : value_wrapper(&value_wrapper)
- , arguments(arguments)
- {}
- call_proxy(call_proxy const& other)
- : value_wrapper(other.value_wrapper)
- , arguments(other.arguments)
- {
- other.value_wrapper = 0;
- }
- ~call_proxy()
- {
- if (value_wrapper)
- call((detail::null_type*)0);
- }
- operator object()
- {
- return call((detail::null_type*)0);
- }
- template<class Policies>
- object operator[](Policies const&)
- {
- return call((Policies*)0);
- }
- template<class Policies>
- object call(Policies*)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- *value_wrapper
- );
- value_wrapper_traits<ValueWrapper>::unwrap(
- interpreter
- , *value_wrapper
- );
- value_wrapper = 0;
- detail::push_args_from_tuple<1>::apply(interpreter, arguments, Policies());
- # ifdef LUABIND_CPP0x
- if (detail::pcall(interpreter, std::tuple_size<Arguments>::value, 1))
- # else
- if (detail::pcall(interpreter, boost::tuples::length<Arguments>::value, 1))
- # endif
- {
- #ifndef LUABIND_NO_EXCEPTIONS
- throw luabind::error(interpreter);
- #else
- error_callback_fun e = get_error_callback();
- if (e) e(interpreter);
- assert(0 && "the lua function threw an error and exceptions are disabled."
- "if you want to handle this error use luabind::set_error_callback()");
- std::terminate();
- #endif
- }
- detail::stack_pop pop(interpreter, 1);
- return object(from_stack(interpreter, -1));
- }
- mutable ValueWrapper* value_wrapper;
- Arguments arguments;
- };
- # ifndef LUABIND_CPP0x
- template<class Derived>
- call_proxy<Derived, boost::tuples::tuple<> >
- object_interface<Derived>::operator()()
- {
- return call_proxy<Derived, boost::tuples::tuple<> >(
- derived()
- , boost::tuples::tuple<>()
- );
- }
- # endif
- // Simple value_wrapper adaptor with the sole purpose of helping with
- // overload resolution. Use this as a function parameter type instead
- // of "object" or "argument" to restrict the parameter to Lua tables.
- template <class Base = object>
- struct table : Base
- {
- table(from_stack const& stack_reference)
- : Base(stack_reference)
- {}
- };
- } // namespace adl
- using adl::table;
- template <class Base>
- struct value_wrapper_traits<adl::table<Base> >
- : value_wrapper_traits<Base>
- {
- static bool check(lua_State* L, int idx)
- {
- return value_wrapper_traits<Base>::check(L, idx) &&
- lua_istable(L, idx);
- }
- };
- inline object newtable(lua_State* interpreter)
- {
- lua_newtable(interpreter);
- detail::stack_pop pop(interpreter, 1);
- return object(from_stack(interpreter, -1));
- }
- // this could be optimized by returning a proxy
- inline object globals(lua_State* interpreter)
- {
- lua_pushvalue(interpreter, LUA_GLOBALSINDEX);
- detail::stack_pop pop(interpreter, 1);
- return object(from_stack(interpreter, -1));
- }
- // this could be optimized by returning a proxy
- inline object registry(lua_State* interpreter)
- {
- lua_pushvalue(interpreter, LUA_REGISTRYINDEX);
- detail::stack_pop pop(interpreter, 1);
- return object(from_stack(interpreter, -1));
- }
- template<class ValueWrapper, class K>
- inline object gettable(ValueWrapper const& table, K const& key)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- table
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
- detail::stack_pop pop(interpreter, 2);
- detail::push(interpreter, key);
- lua_gettable(interpreter, -2);
- return object(from_stack(interpreter, -1));
- }
- template<class ValueWrapper, class K, class T>
- inline void settable(ValueWrapper const& table, K const& key, T const& value)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- table
- );
- // TODO: Exception safe?
-
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
- detail::stack_pop pop(interpreter, 1);
- detail::push(interpreter, key);
- detail::push(interpreter, value);
- lua_settable(interpreter, -3);
- }
- template<class ValueWrapper, class K>
- inline object rawget(ValueWrapper const& table, K const& key)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- table
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
- detail::stack_pop pop(interpreter, 2);
- detail::push(interpreter, key);
- lua_rawget(interpreter, -2);
- return object(from_stack(interpreter, -1));
- }
- template<class ValueWrapper, class K, class T>
- inline void rawset(ValueWrapper const& table, K const& key, T const& value)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- table
- );
- // TODO: Exception safe?
-
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
- detail::stack_pop pop(interpreter, 1);
- detail::push(interpreter, key);
- detail::push(interpreter, value);
- lua_rawset(interpreter, -3);
- }
- template<class ValueWrapper>
- inline int type(ValueWrapper const& value)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- value
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
- detail::stack_pop pop(interpreter, 1);
- return lua_type(interpreter, -1);
- }
- template <class ValueWrapper>
- inline object getmetatable(ValueWrapper const& obj)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- obj
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, obj);
- detail::stack_pop pop(interpreter, 2);
- lua_getmetatable(interpreter, -1);
- return object(from_stack(interpreter, -1));
- }
- template <class ValueWrapper1, class ValueWrapper2>
- inline void setmetatable(
- ValueWrapper1 const& obj, ValueWrapper2 const& metatable)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper1>::interpreter(
- obj
- );
- value_wrapper_traits<ValueWrapper1>::unwrap(interpreter, obj);
- detail::stack_pop pop(interpreter, 1);
- value_wrapper_traits<ValueWrapper2>::unwrap(interpreter, metatable);
- lua_setmetatable(interpreter, -2);
- }
- template <class ValueWrapper>
- inline lua_CFunction tocfunction(ValueWrapper const& value)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- value
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
- detail::stack_pop pop(interpreter, 1);
- return lua_tocfunction(interpreter, -1);
- }
- template <class T, class ValueWrapper>
- inline T* touserdata(ValueWrapper const& value)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- value
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
- detail::stack_pop pop(interpreter, 1);
- return static_cast<T*>(lua_touserdata(interpreter, -1));
- }
- template <class ValueWrapper>
- inline object getupvalue(ValueWrapper const& value, int index)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
- value
- );
- value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
- detail::stack_pop pop(interpreter, 2);
- lua_getupvalue(interpreter, -1, index);
- return object(from_stack(interpreter, -1));
- }
- template <class ValueWrapper1, class ValueWrapper2>
- inline void setupvalue(
- ValueWrapper1 const& function, int index, ValueWrapper2 const& value)
- {
- lua_State* interpreter = value_wrapper_traits<ValueWrapper1>::interpreter(
- function
- );
- value_wrapper_traits<ValueWrapper1>::unwrap(interpreter, function);
- detail::stack_pop pop(interpreter, 1);
- value_wrapper_traits<ValueWrapper2>::unwrap(interpreter, value);
- lua_setupvalue(interpreter, -2, index);
- }
- template <class GetValueWrapper>
- object property(GetValueWrapper const& get)
- {
- lua_State* interpreter = value_wrapper_traits<GetValueWrapper>::interpreter(
- get
- );
- value_wrapper_traits<GetValueWrapper>::unwrap(interpreter, get);
- lua_pushnil(interpreter);
- lua_pushcclosure(interpreter, &detail::property_tag, 2);
- detail::stack_pop pop(interpreter, 1);
- return object(from_stack(interpreter, -1));
- }
- template <class GetValueWrapper, class SetValueWrapper>
- object property(GetValueWrapper const& get, SetValueWrapper const& set)
- {
- lua_State* interpreter = value_wrapper_traits<GetValueWrapper>::interpreter(
- get
- );
- value_wrapper_traits<GetValueWrapper>::unwrap(interpreter, get);
- value_wrapper_traits<SetValueWrapper>::unwrap(interpreter, set);
- lua_pushcclosure(interpreter, &detail::property_tag, 2);
- detail::stack_pop pop(interpreter, 1);
- return object(from_stack(interpreter, -1));
- }
- } // namespace luabind
- #endif // LUABIND_OBJECT_050419_HPP
|