/usr/include/luabind/detail
Edit: /usr/include/luabind/detail/object.hpp (33394B)
// 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include // iterator
#include
#include // value_wrapper_traits specializations
#include
#include
#include
#include
namespace luabind {
namespace adl
{
namespace mpl = boost::mpl;
template
class object_interface;
namespace is_object_interface_aux
{
typedef char (&yes)[1];
typedef char (&no)[2];
template
yes check(object_interface*);
no check(void*);
template
struct impl
{
BOOST_STATIC_CONSTANT(bool, value =
sizeof(is_object_interface_aux::check(static_cast(0)))
== sizeof(yes)
);
typedef mpl::bool_ type;
};
} // namespace detail
template
struct is_object_interface
: is_object_interface_aux::impl::type
{};
template
struct enable_binary
# ifndef BOOST_NO_SFINAE
: boost::enable_if<
mpl::or_<
is_object_interface
, is_object_interface
>
, R
>
{};
# else
{
typedef R type;
};
# endif
template
int binary_interpreter(lua_State*& L, T const& lhs, U const& rhs
, boost::mpl::true_, boost::mpl::true_)
{
L = value_wrapper_traits::interpreter(lhs);
lua_State* L2 = value_wrapper_traits::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
int binary_interpreter(lua_State*& L, T const& x, U const&
, boost::mpl::true_, boost::mpl::false_)
{
L = value_wrapper_traits::interpreter(x);
return 0;
}
template
int binary_interpreter(lua_State*& L, T const&, U const& x, boost::mpl::false_, boost::mpl::true_)
{
L = value_wrapper_traits::interpreter(x);
return 0;
}
template
int binary_interpreter(lua_State*& L, T const& x, U const& y)
{
return binary_interpreter(
L
, x
, y
, is_value_wrapper()
, is_value_wrapper()
);
}
#define LUABIND_BINARY_OP_DEF(op, fn) \
template \
typename enable_binary::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); \
push(L, lhs); \
detail::stack_pop pop2(L, 1); \
push(L, rhs); \
\
return lua_compare(L, -1, -2, fn) != 0; \
}
LUABIND_BINARY_OP_DEF(==, LUA_OPEQ)
LUABIND_BINARY_OP_DEF(<, LUA_OPLT)
inline int value_to_string(lua_State* L)
{
assert(lua_gettop(L) == 1);
luaL_tolstring(L, 1, 0);
return 1;
}
template
std::ostream& operator<<(std::ostream& os
, object_interface const& v)
{
using namespace luabind;
lua_State* L = value_wrapper_traits::interpreter(
static_cast(v));
detail::stack_pop pop(L, 1);
lua_pushcfunction(L, &value_to_string);
value_wrapper_traits::unwrap(L
, static_cast(v));
if (lua_pcall(L, 1, 1, 0) != LUA_OK)
{
lua_pop(L, 1); // Pop error.
os.setstate(std::ios::failbit);
return os;
}
size_t len;
char const* p = lua_tolstring(L, -1, &len);
std::copy(p, p + len, std::ostream_iterator(os));
return os;
}
#undef LUABIND_BINARY_OP_DEF
template
typename enable_binary::type
operator>(LHS const& lhs, RHS const& rhs)
{
return !(lhs < rhs || lhs == rhs);
}
template
typename enable_binary::type
operator<=(LHS const& lhs, RHS const& rhs)
{
return lhs < rhs || lhs == rhs;
}
template
typename enable_binary::type
operator>=(LHS const& lhs, RHS const& rhs)
{
return !(lhs < rhs);
}
template
typename enable_binary::type
operator!=(LHS const& lhs, RHS const& rhs)
{
return !(lhs == rhs);
}
template
struct call_proxy;
template
class index_proxy;
class object;
template
class object_interface
{
struct safe_bool_type {};
public:
call_proxy > operator()();
template
call_proxy<
Derived
, boost::tuples::tuple
> operator()(A0 const& a0)
{
typedef boost::tuples::tuple arguments;
return call_proxy(
derived()
, arguments(&a0)
);
}
template
call_proxy<
Derived
, boost::tuples::tuple
> operator()(A0 const& a0, A1 const& a1)
{
typedef boost::tuples::tuple arguments;
return call_proxy(
derived()
, arguments(&a0, &a1)
);
}
// The rest of the overloads are PP-generated.
#define BOOST_PP_ITERATION_PARAMS_1 (3, \
(3, LUABIND_MAX_ARITY, ))
#include BOOST_PP_ITERATE()
operator safe_bool_type*() const
{
lua_State* L = value_wrapper_traits::interpreter(derived());
if (!L)
return 0;
value_wrapper_traits::unwrap(L, derived());
detail::stack_pop pop(L, 1);
return lua_toboolean(L, -1) == 1 ? reinterpret_cast(1) : 0;
}
private:
Derived& derived()
{
return *static_cast(this);
}
Derived const& derived() const
{
return *static_cast(this);
}
};
#ifdef LUABIND_USE_VALUE_WRAPPER_TAG
struct iterator_proxy_tag;
#endif
template
class iterator_proxy
: public object_interface >
{
public:
#ifdef LUABIND_USE_VALUE_WRAPPER_TAG
typedef iterator_proxy_tag value_wrapper_tag;
#endif
iterator_proxy(lua_State* L, handle const& table, handle const& key)
: m_interpreter(L)
, m_table_index(lua_gettop(L) + 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
iterator_proxy& operator=(T const& value)
{
lua_pushvalue(m_interpreter, m_key_index);
push(m_interpreter, value);
AccessPolicy::set(m_interpreter, m_table_index);
return *this;
}
template
index_proxy > operator[](Key const& key)
{
return index_proxy >(
*this, m_interpreter, key
);
}
// This is non-const to prevent conversion on lvalues.
operator object();
lua_State* interpreter() const
{
return m_interpreter;
}
void push(lua_State* L) const
{
assert(L == m_interpreter);
(void)L;
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 basic_iterator
: public boost::iterator_facade<
basic_iterator
, adl::iterator_proxy
, boost::single_pass_traversal_tag
, adl::iterator_proxy
>
{
public:
basic_iterator()
: m_interpreter(0)
{}
template
explicit basic_iterator(ValueWrapper const& value_wrapper)
: m_interpreter(
value_wrapper_traits::interpreter(value_wrapper)
)
{
detail::stack_pop pop(m_interpreter, 1);
value_wrapper_traits::unwrap(m_interpreter, value_wrapper);
lua_pushnil(m_interpreter);
if (lua_next(m_interpreter, -2) != 0)
{
detail::stack_pop pop2(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_compare(m_interpreter, -2, -1, LUA_OPEQ) != 0;
}
adl::iterator_proxy dereference() const
{
return adl::iterator_proxy(m_interpreter, m_table, m_key);
}
lua_State* m_interpreter;
handle m_table;
handle m_key;
};
#if BOOST_VERSION < 105700
// Needed because of some strange ADL issues.
#define LUABIND_OPERATOR_ADL_WKND(op) \
inline bool operator op( \
basic_iterator const& x \
, basic_iterator const& y) \
{ \
return boost::operator op(x, y); \
} \
\
inline bool operator op( \
basic_iterator const& x \
, basic_iterator const& y) \
{ \
return boost::operator op(x, y); \
}
LUABIND_OPERATOR_ADL_WKND(==)
LUABIND_OPERATOR_ADL_WKND(!=)
#undef LUABIND_OPERATOR_ADL_WKND
#endif // BOOST_VERSION < 105700
} // namespace detail
namespace adl
{
#ifdef LUABIND_USE_VALUE_WRAPPER_TAG
struct index_proxy_tag;
#endif
template
class index_proxy
: public object_interface >
{
public:
#ifdef LUABIND_USE_VALUE_WRAPPER_TAG
typedef index_proxy_tag value_wrapper_tag;
#endif
typedef index_proxy this_type;
template
index_proxy(Next const& next, lua_State* L, Key const& key)
: m_next(next)
, m_interpreter(L)
, m_key_index(lua_gettop(L) + 1)
{
luabind::push(m_interpreter, key);
}
index_proxy(index_proxy const& other)
: m_next(other.m_next)
, m_interpreter(other.m_interpreter)
, m_key_index(other.m_key_index)
{
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::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
this_type& operator=(T const& value)
{
value_wrapper_traits::unwrap(m_interpreter, m_next);
detail::stack_pop pop(m_interpreter, 1);
lua_pushvalue(m_interpreter, m_key_index);
luabind::push(m_interpreter, value);
lua_settable(m_interpreter, -3);
return *this;
}
this_type& operator=(this_type const& value)
{
value_wrapper_traits::unwrap(m_interpreter, m_next);
detail::stack_pop pop(m_interpreter, 1);
lua_pushvalue(m_interpreter, m_key_index);
luabind::push(m_interpreter, value);
lua_settable(m_interpreter, -3);
return *this;
}
template
index_proxy operator[](T const& key)
{
return index_proxy(*this, m_interpreter, key);
}
void push(lua_State* L);
lua_State* interpreter() const
{
return m_interpreter;
}
private:
struct hidden_type {};
// this_type& operator=(index_proxy const&);
Next const& m_next;
mutable lua_State* m_interpreter;
int m_key_index;
};
} // namespace adl
typedef detail::basic_iterator iterator;
typedef detail::basic_iterator raw_iterator;
#ifndef LUABIND_USE_VALUE_WRAPPER_TAG
template
struct value_wrapper_traits >
#else
template<>
struct value_wrapper_traits
#endif
{
typedef boost::mpl::true_ is_specialized;
template
static lua_State* interpreter(adl::index_proxy const& proxy)
{
return proxy.interpreter();
}
template
static void unwrap(lua_State* interpreter, adl::index_proxy const& proxy)
{
const_cast&>(proxy).push(interpreter);
}
};
#ifndef LUABIND_USE_VALUE_WRAPPER_TAG
template
struct value_wrapper_traits >
#else
template<>
struct value_wrapper_traits
#endif
{
typedef boost::mpl::true_ is_specialized;
template
static lua_State* interpreter(Proxy const& p)
{
return p.interpreter();
}
template
static void unwrap(lua_State* interpreter, Proxy const& p)
{
p.push(interpreter);
}
};
namespace adl
{
// An object holds a reference to a Lua value residing
// in the registry.
class object : public object_interface