mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
stack implementation, plus reference semantics within lua for usertypes/data now.
I hate my life. I hate the projects I'm working on. Closes #53 Closes #56 Closes #52
This commit is contained in:
parent
204bd5d5ed
commit
9734577fdb
|
@ -32,22 +32,23 @@
|
|||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
class function : public reference {
|
||||
template <typename base_t>
|
||||
class basic_function : public base_t {
|
||||
private:
|
||||
void luacall( std::ptrdiff_t argcount, std::ptrdiff_t resultcount ) const {
|
||||
lua_callk( lua_state( ), static_cast<int>( argcount ), static_cast<int>( resultcount ), 0, nullptr );
|
||||
lua_callk( base_t::lua_state( ), static_cast<int>( argcount ), static_cast<int>( resultcount ), 0, nullptr );
|
||||
}
|
||||
|
||||
template<std::size_t... I, typename... Ret>
|
||||
auto invoke( types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n ) const {
|
||||
luacall( n, sizeof...( Ret ) );
|
||||
return stack::pop<std::tuple<Ret...>>( lua_state( ) );
|
||||
return stack::pop<std::tuple<Ret...>>( base_t::lua_state( ) );
|
||||
}
|
||||
|
||||
template<std::size_t I, typename Ret>
|
||||
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n ) const {
|
||||
luacall( n, 1 );
|
||||
return stack::pop<Ret>( lua_state( ) );
|
||||
return stack::pop<Ret>( base_t::lua_state( ) );
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
|
@ -56,21 +57,21 @@ private:
|
|||
}
|
||||
|
||||
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const {
|
||||
int stacksize = lua_gettop( lua_state( ) );
|
||||
int stacksize = lua_gettop( base_t::lua_state( ) );
|
||||
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
|
||||
luacall(n, LUA_MULTRET);
|
||||
int poststacksize = lua_gettop( lua_state( ) );
|
||||
int poststacksize = lua_gettop( base_t::lua_state( ) );
|
||||
int returncount = poststacksize - (firstreturn - 1);
|
||||
return function_result( lua_state( ), firstreturn, returncount );
|
||||
return function_result( base_t::lua_state( ), firstreturn, returncount );
|
||||
}
|
||||
|
||||
public:
|
||||
function() = default;
|
||||
function(const function&) = default;
|
||||
function& operator=(const function&) = default;
|
||||
function( function&& ) = default;
|
||||
function& operator=( function&& ) = default;
|
||||
function(lua_State* L, int index = -1): reference(L, index) {
|
||||
basic_function() = default;
|
||||
basic_function(const basic_function&) = default;
|
||||
basic_function& operator=(const basic_function&) = default;
|
||||
basic_function(basic_function&& ) = default;
|
||||
basic_function& operator=(basic_function&& ) = default;
|
||||
basic_function(lua_State* L, int index = -1): base_t(L, index) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert(L, index, type::function);
|
||||
#endif // Safety
|
||||
|
@ -88,8 +89,8 @@ public:
|
|||
|
||||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call( Args&&... args ) const {
|
||||
push( );
|
||||
int pushcount = stack::multi_push( lua_state( ), std::forward<Args>( args )... );
|
||||
base_t::push( );
|
||||
int pushcount = stack::multi_push( base_t::lua_state( ), std::forward<Args>( args )... );
|
||||
return invoke( types<Ret...>( ), std::make_index_sequence<sizeof...(Ret)>(), pushcount );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -103,7 +103,7 @@ struct pusher<function_sig<Sigs...>> {
|
|||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
|
||||
typedef meta::Bool<meta::is_specialization_of<std::reference_wrapper, meta::Unqualified<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ struct pusher<function_sig<Sigs...>> {
|
|||
|
||||
template <typename Fx, typename T, typename... Args>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
|
||||
typedef meta::Bool<meta::is_specialization_of<meta::Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
|
||||
typedef meta::Bool<meta::is_specialization_of<std::reference_wrapper, meta::Unqualified<T>>::value || std::is_pointer<T>::value> is_reference;
|
||||
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ struct constructor_match {
|
|||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
|
||||
default_construct func{};
|
||||
return stack::call_into_lua<0, false>(r, a, func, L, start, obj);
|
||||
return stack::call_into_lua<0, false>(r, a, L, start, func, obj);
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
@ -115,7 +115,7 @@ struct usertype_constructor_function : base_function {
|
|||
userdataref.pop();
|
||||
|
||||
auto& func = std::get<I>(overloads);
|
||||
stack::call_into_lua<false>(r, a, func, L, start, function_detail::implicit_wrapper<T>(obj));
|
||||
stack::call_into_lua<false>(r, a, L, start, func, function_detail::implicit_wrapper<T>(obj));
|
||||
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &meta[0]);
|
||||
|
|
|
@ -34,7 +34,7 @@ struct upvalue_free_function {
|
|||
static int real_call(lua_State* L) {
|
||||
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
|
||||
function_type* fx = udata.first;
|
||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), fx, L, 1);
|
||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 1, fx);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ struct upvalue_member_function {
|
|||
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), fx, L, 1);
|
||||
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 1, fx);
|
||||
}
|
||||
|
||||
static int call (lua_State* L) {
|
||||
|
@ -124,11 +124,11 @@ struct upvalue_this_member_function {
|
|||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
function_type& memfx = memberdata.first;
|
||||
auto fx = [&memfx](lua_State* L, auto&&... args) -> typename traits_type::return_type {
|
||||
auto fx = [&L, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||
auto& item = stack::get<T>(L, 1);
|
||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), fx, L, 2, L);
|
||||
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 2, fx);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,19 +97,19 @@ struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::va
|
|||
}
|
||||
|
||||
template<typename Arg>
|
||||
void call(types<return_type>, Arg&& arg) {
|
||||
void call(Arg&& arg) {
|
||||
T& member = *item;
|
||||
(member.*invocation) = std::forward<Arg>(arg);
|
||||
}
|
||||
|
||||
return_type call(types<return_type>) {
|
||||
return_type& call() {
|
||||
T& member = *item;
|
||||
return (member.*invocation);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
auto operator()(Args&&... args) -> decltype(std::declval<functor>().call(types<return_type>{}, std::forward<Args>(args)...)) {
|
||||
return this->call(types<return_type>{}, std::forward<Args>(args)...);
|
||||
decltype(auto) operator()(Args&&... args) {
|
||||
return this->call(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ struct functor_function : public base_function {
|
|||
functor_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
||||
|
||||
int call(lua_State* L) {
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), fx, L, 1);
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -70,7 +70,7 @@ struct member_function : public base_function {
|
|||
member_function(F&& f, Args&&... args) : fx(std::forward<F>(f), std::forward<Args>(args)...) {}
|
||||
|
||||
int call(lua_State* L) {
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), fx, L, 1);
|
||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -86,21 +86,39 @@ struct member_variable : public base_function {
|
|||
typedef typename meta::bind_traits<function_type>::args_type args_types;
|
||||
function_type var;
|
||||
T member;
|
||||
typedef std::add_lvalue_reference_t<meta::Unwrapped<std::remove_reference_t<decltype(detail::deref(member))>>> M;
|
||||
|
||||
template<typename Fx, typename... Args>
|
||||
member_variable(Fx&& fx, Args&&... args): var(std::forward<Fx>(fx)), member(std::forward<Args>(args)...) {}
|
||||
template<typename V, typename... Args>
|
||||
member_variable(V&& v, Args&&... args): var(std::forward<V>(v)), member(std::forward<Args>(args)...) {}
|
||||
|
||||
int set_assignable(std::false_type, lua_State* L, M) {
|
||||
lua_pop(L, 1);
|
||||
return luaL_error(L, "cannot write to this type: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
int set_assignable(std::true_type, lua_State* L, M mem) {
|
||||
(mem.*var) = stack::get<return_type>(L, 1);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_variable(std::true_type, lua_State* L, M mem) {
|
||||
return set_assignable(std::is_assignable<std::add_lvalue_reference_t<return_type>, return_type>(), L, mem);
|
||||
}
|
||||
|
||||
int set_variable(std::false_type, lua_State* L, M) {
|
||||
lua_pop(L, 1);
|
||||
return luaL_error(L, "cannot write to a const variable");
|
||||
}
|
||||
|
||||
int call(lua_State* L) {
|
||||
auto& mem = detail::unwrap(detail::deref(member));
|
||||
M mem = detail::unwrap(detail::deref(member));
|
||||
switch (lua_gettop(L)) {
|
||||
case 0: {
|
||||
case 0:
|
||||
stack::push(L, (mem.*var));
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
case 1:
|
||||
(mem.*var) = stack::get<return_type>(L, 1);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
return set_variable(meta::Not<std::is_const<return_type>>(), L, mem);
|
||||
default:
|
||||
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ struct overloaded_function : base_function {
|
|||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
auto& func = std::get<I>(overloads);
|
||||
return stack::call_into_lua<0, false>(r, a, func, L, start);
|
||||
return stack::call_into_lua<0, false>(r, a, L, start, func);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -113,7 +113,7 @@ struct usertype_overloaded_function : base_function {
|
|||
int call(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
auto& func = std::get<I>(overloads);
|
||||
func.item = detail::ptr(stack::get<T>(L, 1));
|
||||
return stack::call_into_lua<0, false>(r, a, func, L, start);
|
||||
return stack::call_into_lua<0, false>(r, a, L, start, func);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
|
|
@ -34,6 +34,30 @@ namespace function_detail {
|
|||
return stack::call_into_lua(return_type(), args_type(), fx, L, 1);
|
||||
}
|
||||
|
||||
template <typename R, typename V, V, typename T>
|
||||
inline int call_set_assignable(std::false_type, T&&, lua_State* L) {
|
||||
lua_pop(L, 2);
|
||||
return luaL_error(L, "cannot write to this type: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
template <typename R, typename V, V variable, typename T>
|
||||
inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) {
|
||||
(mem.*variable) = stack::get<R>(L, 2);
|
||||
lua_pop(L, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename R, typename V, V, typename T>
|
||||
inline int call_set_variable(std::false_type, lua_State* L, T&&) {
|
||||
lua_pop(L, 2);
|
||||
return luaL_error(L, "cannot write to a const variable");
|
||||
}
|
||||
|
||||
template <typename R, typename V, V variable, typename T>
|
||||
inline int call_set_variable(std::true_type, lua_State* L, T&& mem) {
|
||||
return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem));
|
||||
}
|
||||
|
||||
template <typename V, V variable>
|
||||
inline int call_wrapper_variable(std::true_type, lua_State* L) {
|
||||
typedef meta::bind_traits<meta::Unqualified<V>> traits_type;
|
||||
|
@ -41,14 +65,13 @@ namespace function_detail {
|
|||
typedef typename traits_type::return_type R;
|
||||
auto& mem = stack::get<T>(L, 1);
|
||||
switch (lua_gettop(L)) {
|
||||
case 1:
|
||||
case 1: {
|
||||
decltype(auto) r = (mem.*variable);
|
||||
lua_pop(L, 1);
|
||||
stack::push(L, (mem.*variable));
|
||||
return 1;
|
||||
stack::push_reference(L, std::forward<decltype(r)>(r));
|
||||
return 1; }
|
||||
case 2:
|
||||
(mem.*variable) = stack::get<R>(L, 2);
|
||||
lua_pop(L, 2);
|
||||
return 0;
|
||||
return call_set_variable<R, V, variable>(meta::Not<std::is_const<R>>(), L, mem);
|
||||
default:
|
||||
return luaL_error(L, "incorrect number of arguments to member variable function call");
|
||||
}
|
||||
|
@ -70,7 +93,7 @@ namespace function_detail {
|
|||
auto& member = stack::get<T>(L, 1);
|
||||
return (member.*fx)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
int n = stack::call_into_lua<1>(return_type_list(), args_type(), mfx, L, 2);
|
||||
int n = stack::call_into_lua<1>(return_type_list(), args_type(), L, 2, mfx);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,17 +55,17 @@ struct usertype_function_core : public base_function {
|
|||
// without allocating an extra userdata, apparently!
|
||||
return 1;
|
||||
}
|
||||
return stack::push(L, std::forward<Return>(r));
|
||||
return stack::push_reference(L, std::forward<Return>(r));
|
||||
}
|
||||
|
||||
template<typename Return, typename Raw = meta::Unqualified<Return>>
|
||||
std::enable_if_t<!std::is_same<T, Raw>::value, int> push(lua_State* L, Return&& r) {
|
||||
return stack::push(L, std::forward<Return>(r));
|
||||
return stack::push_reference(L, std::forward<Return>(r));
|
||||
}
|
||||
|
||||
template<typename... Args, std::size_t Start>
|
||||
int operator()(types<void> tr, types<Args...> ta, Index<Start>, lua_State* L) {
|
||||
stack::call(tr, ta, L, static_cast<int>(Start), fx);
|
||||
stack::call_into_lua(tr, ta, L, static_cast<int>(Start), fx);
|
||||
int nargs = static_cast<int>(sizeof...(Args));
|
||||
lua_pop(L, nargs);
|
||||
return 0;
|
||||
|
@ -113,6 +113,24 @@ struct usertype_variable_function : public usertype_function_core<Function, Tp>
|
|||
template<typename... Args>
|
||||
usertype_variable_function(Args&&... args): base_t(std::forward<Args>(args)...) {}
|
||||
|
||||
int set_assignable(std::false_type, lua_State* L) {
|
||||
lua_pop(L, 2);
|
||||
return luaL_error(L, "cannot write to this type: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
int set_assignable(std::true_type, lua_State* L) {
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<void>(), args_type(), Index<3>(), L);
|
||||
}
|
||||
|
||||
int set_variable(std::false_type, lua_State* L) {
|
||||
lua_pop(L, 2);
|
||||
return luaL_error(L, "cannot write to a const variable");
|
||||
}
|
||||
|
||||
int set_variable(std::true_type, lua_State* L) {
|
||||
return set_assignable(std::is_assignable<std::add_lvalue_reference_t<return_type>, return_type>(), L);
|
||||
}
|
||||
|
||||
int prelude(lua_State* L) {
|
||||
int argcount = lua_gettop(L);
|
||||
this->fx.item = stack::get<T*>(L, 1);
|
||||
|
@ -120,7 +138,7 @@ struct usertype_variable_function : public usertype_function_core<Function, Tp>
|
|||
case 2:
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<return_type>(), types<>(), Index<2>(), L);
|
||||
case 3:
|
||||
return static_cast<base_t&>(*this)(meta::tuple_types<void>(), args_type(), Index<3>(), L);
|
||||
return set_variable(meta::Not<std::is_const<return_type>>(), L);
|
||||
default:
|
||||
return luaL_error(L, "sol: cannot get/set userdata member variable with inappropriate number of arguments");
|
||||
}
|
||||
|
|
|
@ -27,23 +27,46 @@
|
|||
#include "stack.hpp"
|
||||
|
||||
namespace sol {
|
||||
class object : public reference {
|
||||
public:
|
||||
using reference::reference;
|
||||
template <typename base_t>
|
||||
class basic_object : public base_t {
|
||||
private:
|
||||
template<typename T>
|
||||
decltype(auto) as_stack(std::true_type) const {
|
||||
return stack::get<T>(lua_state(), base_t::stack_index());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
decltype(auto) as() const {
|
||||
push();
|
||||
decltype(auto) as_stack(std::false_type) const {
|
||||
base_t::push();
|
||||
return stack::pop<T>(lua_state());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool is() const {
|
||||
if (!valid())
|
||||
return false;
|
||||
bool is_stack(std::true_type) const {
|
||||
return stack::check<T>(lua_state(), base_t::stack_index(), no_panic);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool is_stack(std::false_type) const {
|
||||
auto pp = stack::push_pop(*this);
|
||||
return stack::check<T>(lua_state(), -1, no_panic);
|
||||
}
|
||||
|
||||
public:
|
||||
using base_t::base_t;
|
||||
using base_t::lua_state;
|
||||
|
||||
template<typename T>
|
||||
decltype(auto) as() const {
|
||||
return as_stack<T>( std::is_same<base_t, stack_reference>() );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool is() const {
|
||||
if (!base_t::valid())
|
||||
return false;
|
||||
return is_stack<T>(std::is_same<base_t, stack_reference>());
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const object& lhs, const nil_t&) {
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include <cstdint>
|
||||
|
||||
namespace sol {
|
||||
class protected_function : public reference {
|
||||
template <typename base_t>
|
||||
class basic_protected_function : public base_t {
|
||||
private:
|
||||
static reference& handler_storage() {
|
||||
static sol::reference h;
|
||||
|
@ -62,19 +63,19 @@ private:
|
|||
};
|
||||
|
||||
int luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, handler& h) const {
|
||||
return lua_pcallk(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr);
|
||||
return lua_pcallk(base_t::lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr);
|
||||
}
|
||||
|
||||
template<std::size_t... I, typename... Ret>
|
||||
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, handler& h) const {
|
||||
luacall(n, sizeof...(Ret), h);
|
||||
return stack::pop<std::tuple<Ret...>>(lua_state());
|
||||
return stack::pop<std::tuple<Ret...>>(base_t::lua_state());
|
||||
}
|
||||
|
||||
template<std::size_t I, typename Ret>
|
||||
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
|
||||
luacall(n, 1, h);
|
||||
return stack::pop<Ret>(lua_state());
|
||||
return stack::pop<Ret>(base_t::lua_state());
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
|
@ -83,7 +84,7 @@ private:
|
|||
}
|
||||
|
||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
|
||||
int stacksize = lua_gettop(lua_state());
|
||||
int stacksize = lua_gettop(base_t::lua_state());
|
||||
int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
|
||||
int returncount = 0;
|
||||
call_status code = call_status::ok;
|
||||
|
@ -92,49 +93,49 @@ private:
|
|||
h.stackindex = 0;
|
||||
if (h.target.valid()) {
|
||||
h.target.push();
|
||||
stack::push(lua_state(), error);
|
||||
lua_call(lua_state(), 1, 1);
|
||||
stack::push(base_t::lua_state(), error);
|
||||
lua_call(base_t::lua_state(), 1, 1);
|
||||
}
|
||||
else {
|
||||
stack::push(lua_state(), error);
|
||||
stack::push(base_t::lua_state(), error);
|
||||
}
|
||||
};
|
||||
try {
|
||||
#endif // No Exceptions
|
||||
code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
|
||||
int poststacksize = lua_gettop(lua_state());
|
||||
int poststacksize = lua_gettop(base_t::lua_state());
|
||||
returncount = poststacksize - (stacksize - 1);
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
}
|
||||
// Handle C++ errors thrown from C++ functions bound inside of lua
|
||||
catch (const char* error) {
|
||||
onexcept(error);
|
||||
firstreturn = lua_gettop(lua_state());
|
||||
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
firstreturn = lua_gettop(base_t::lua_state());
|
||||
return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
onexcept(error.what());
|
||||
firstreturn = lua_gettop(lua_state());
|
||||
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
firstreturn = lua_gettop(base_t::lua_state());
|
||||
return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
}
|
||||
catch (...) {
|
||||
onexcept("caught (...) unknown error during protected_function call");
|
||||
firstreturn = lua_gettop(lua_state());
|
||||
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
firstreturn = lua_gettop(base_t::lua_state());
|
||||
return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
}
|
||||
#endif // No Exceptions
|
||||
return protected_function_result(lua_state(), firstreturn, returncount, returncount, code);
|
||||
return protected_function_result(base_t::lua_state(), firstreturn, returncount, returncount, code);
|
||||
}
|
||||
|
||||
public:
|
||||
reference error_handler;
|
||||
|
||||
protected_function() = default;
|
||||
protected_function(const protected_function&) = default;
|
||||
protected_function& operator=(const protected_function&) = default;
|
||||
protected_function( protected_function&& ) = default;
|
||||
protected_function& operator=( protected_function&& ) = default;
|
||||
protected_function(lua_State* L, int index = -1): reference(L, index), error_handler(get_default_handler()) {
|
||||
basic_protected_function() = default;
|
||||
basic_protected_function(const basic_protected_function&) = default;
|
||||
basic_protected_function& operator=(const basic_protected_function&) = default;
|
||||
basic_protected_function(basic_protected_function&& ) = default;
|
||||
basic_protected_function& operator=(basic_protected_function&& ) = default;
|
||||
basic_protected_function(lua_State* L, int index = -1): base_t(L, index), error_handler(get_default_handler()) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert(L, index, type::function);
|
||||
#endif // Safety
|
||||
|
@ -153,8 +154,8 @@ public:
|
|||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call(Args&&... args) const {
|
||||
handler h(error_handler);
|
||||
push();
|
||||
int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...);
|
||||
base_t::push();
|
||||
int pushcount = stack::multi_push(base_t::lua_state(), std::forward<Args>(args)...);
|
||||
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace sol {
|
|||
template<typename Table, typename Key>
|
||||
struct proxy : public proxy_base<proxy<Table, Key>> {
|
||||
private:
|
||||
typedef meta::If<meta::is_specialization_of<Key, std::tuple>, Key, std::tuple<meta::If<std::is_array<meta::Unqualified<Key>>, Key&, meta::Unqualified<Key>>>> key_type;
|
||||
typedef meta::If<meta::is_specialization_of<std::tuple, Key>, Key, std::tuple<meta::If<std::is_array<meta::Unqualified<Key>>, Key&, meta::Unqualified<Key>>>> key_type;
|
||||
|
||||
template<typename T, std::size_t... I>
|
||||
decltype(auto) tuple_get(std::index_sequence<I...>) const {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define SOL_REFERENCE_HPP
|
||||
|
||||
#include "types.hpp"
|
||||
#include "stack_reference.hpp"
|
||||
|
||||
namespace sol {
|
||||
namespace stack {
|
||||
|
@ -65,9 +66,14 @@ protected:
|
|||
ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
int stack_index() const noexcept {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public:
|
||||
reference() noexcept = default;
|
||||
|
||||
reference(const stack_reference& r) noexcept : reference(r.lua_state(), r.stack_index()) {}
|
||||
reference(stack_reference&& r) noexcept : reference(r.lua_state(), r.stack_index()) {}
|
||||
reference(lua_State* L, int index = -1) noexcept : L(L) {
|
||||
lua_pushvalue(L, index);
|
||||
ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
|
|
@ -68,7 +68,7 @@ inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
|||
}
|
||||
|
||||
template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline R call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
||||
return fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I)...);
|
||||
}
|
||||
|
@ -103,13 +103,13 @@ inline void remove( lua_State* L, int index, int count ) {
|
|||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline R call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||
typedef typename types<Args...>::indices args_indices;
|
||||
return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline R call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArg
|
|||
}
|
||||
|
||||
template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
|
||||
inline R call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
|
||||
return call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||
}
|
||||
|
||||
|
@ -135,16 +135,16 @@ inline void call_from_top(types<void> tr, types<Args...> ta, lua_State* L, Fx&&
|
|||
}
|
||||
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
|
||||
inline int call_into_lua(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L, int start, FxArgs&&... fxargs) {
|
||||
call<check_args>(tr, ta, L, start, fx, std::forward<FxArgs>(fxargs)...);
|
||||
inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop;
|
||||
lua_pop(L, nargs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::Not<std::is_void<Ret0>>::value>>
|
||||
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, Fx&& fx, lua_State* L, int start, FxArgs&&... fxargs) {
|
||||
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, fx, std::forward<FxArgs>(fxargs)...);
|
||||
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
|
||||
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop;
|
||||
lua_pop(L, nargs);
|
||||
return push(L, std::forward<decltype(r)>(r));
|
||||
|
|
|
@ -182,8 +182,7 @@ struct checker<T, type::userdata, C> {
|
|||
if (meta::Or<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>>::value)
|
||||
return true;
|
||||
if (lua_getmetatable(L, index) == 0) {
|
||||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (stack_detail::check_metatable<U>(L))
|
||||
return true;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
struct as_reference_tag{};
|
||||
|
||||
using special_destruct_func = void(*)(void*);
|
||||
|
||||
template <typename T, typename Real>
|
||||
|
@ -134,6 +136,16 @@ inline int multi_push(lua_State* L, T&& t, Args&&... args) {
|
|||
return pushcount;
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
inline int push_reference(lua_State* L, T&& t, Args&&... args) {
|
||||
typedef meta::And<
|
||||
std::is_lvalue_reference<T>,
|
||||
meta::Not<std::is_const<T>>,
|
||||
meta::Not<is_lua_primitive<T>>
|
||||
> use_reference_tag;
|
||||
return pusher<std::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::Unqualified<T>>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename Handler>
|
||||
bool check(lua_State* L, int index, Handler&& handler) {
|
||||
typedef meta::Unqualified<T> Tu;
|
||||
|
|
|
@ -69,6 +69,13 @@ struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value>> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<T, std::enable_if_t<std::is_base_of<stack_reference, T>::value>> {
|
||||
static T get(lua_State* L, int index = -1) {
|
||||
return T(L, index);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<stack_reference> {
|
||||
static stack_reference get(lua_State* L, int index = -1) {
|
||||
|
@ -143,9 +150,9 @@ struct getter<lua_CFunction> {
|
|||
|
||||
template<>
|
||||
struct getter<c_closure> {
|
||||
static c_closure get(lua_State* L, int index = -1) {
|
||||
return c_closure(lua_tocfunction(L, index), -1);
|
||||
}
|
||||
static c_closure get(lua_State* L, int index = -1) {
|
||||
return c_closure(lua_tocfunction(L, index), -1);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -34,7 +34,7 @@ inline void stack_fail(int, int) {
|
|||
#else
|
||||
// Lol, what do you want, an error printout? :3c
|
||||
// There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so
|
||||
// hopefully someone will register their own stack_fail thing here
|
||||
// hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard.
|
||||
#endif // No Exceptions
|
||||
}
|
||||
} // detail
|
||||
|
@ -42,16 +42,16 @@ inline void stack_fail(int, int) {
|
|||
struct stack_guard {
|
||||
lua_State* L;
|
||||
int top;
|
||||
std::function<void(int, int)> fx;
|
||||
std::function<void(int, int)> on_mismatch;
|
||||
|
||||
stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {}
|
||||
stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), fx(std::move(fx)) {}
|
||||
stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {}
|
||||
~stack_guard() {
|
||||
int bottom = lua_gettop(L);
|
||||
if (top == bottom) {
|
||||
return;
|
||||
}
|
||||
fx(top, bottom);
|
||||
on_mismatch(top, bottom);
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
|
|
@ -55,6 +55,11 @@ struct popper<std::pair<A, B>> {
|
|||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct popper<T, std::enable_if_t<std::is_base_of<stack_reference, meta::Unqualified<T>>::value>> {
|
||||
static_assert(meta::Not<std::is_base_of<stack_reference, meta::Unqualified<T>>>::value, "You cannot pop something that derives from stack_reference: it will not remain on the stack and thusly will go out of scope!");
|
||||
};
|
||||
} // stack
|
||||
} // sol
|
||||
|
||||
|
|
|
@ -50,6 +50,14 @@ struct pusher {
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pusher<detail::as_reference_tag> {
|
||||
template <typename T>
|
||||
static int push(lua_State* L, T&& obj) {
|
||||
return stack::push(L, detail::ptr(obj));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*> {
|
||||
static int push(lua_State* L, T* obj) {
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
#ifndef SOL_STACK_REFERENCE_HPP
|
||||
#define SOL_STACK_REFERENCE_HPP
|
||||
|
||||
#include "reference.hpp"
|
||||
|
||||
namespace sol {
|
||||
class stack_reference {
|
||||
private:
|
||||
|
@ -31,6 +29,9 @@ private:
|
|||
int index = 0;
|
||||
|
||||
protected:
|
||||
int registry_index () const noexcept {
|
||||
return LUA_NOREF;
|
||||
}
|
||||
|
||||
public:
|
||||
stack_reference() noexcept = default;
|
||||
|
@ -45,6 +46,10 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
int stack_index () const noexcept {
|
||||
return index;
|
||||
}
|
||||
|
||||
type get_type() const noexcept {
|
||||
int result = lua_type(L, index);
|
||||
return static_cast<type>(result);
|
||||
|
|
|
@ -25,11 +25,28 @@
|
|||
#include "state_view.hpp"
|
||||
|
||||
namespace sol {
|
||||
inline int default_at_panic(lua_State* L) {
|
||||
#ifdef SOL_NO_EXCEPTIONS
|
||||
(void)L;
|
||||
return -1;
|
||||
#else
|
||||
const char* message = lua_tostring(L, -1);
|
||||
std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
|
||||
throw error(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
class state : private std::unique_ptr<lua_State, void(*)(lua_State*)>, public state_view {
|
||||
private:
|
||||
typedef std::unique_ptr<lua_State, void(*)(lua_State*)> unique_base;
|
||||
public:
|
||||
state(lua_CFunction panic = detail::atpanic) : unique_base(luaL_newstate(), lua_close),
|
||||
state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close),
|
||||
state_view(unique_base::get()) {
|
||||
set_panic(panic);
|
||||
stack::luajit_exception_handler(unique_base::get());
|
||||
}
|
||||
|
||||
state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close),
|
||||
state_view(unique_base::get()) {
|
||||
set_panic(panic);
|
||||
stack::luajit_exception_handler(unique_base::get());
|
||||
|
|
|
@ -27,19 +27,6 @@
|
|||
#include <memory>
|
||||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
inline int atpanic(lua_State* L) {
|
||||
#ifdef SOL_NO_EXCEPTIONS
|
||||
(void)L;
|
||||
return -1;
|
||||
#else
|
||||
const char* message = lua_tostring(L, -1);
|
||||
std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
|
||||
throw error(err);
|
||||
#endif
|
||||
}
|
||||
} // detail
|
||||
|
||||
enum class lib : char {
|
||||
base,
|
||||
package,
|
||||
|
@ -60,6 +47,9 @@ private:
|
|||
table reg;
|
||||
global_table global;
|
||||
public:
|
||||
typedef typename global_table::iterator iterator;
|
||||
typedef typename global_table::const_iterator const_iterator;
|
||||
|
||||
state_view(lua_State* L):
|
||||
L(L),
|
||||
reg(L, LUA_REGISTRYINDEX),
|
||||
|
@ -152,19 +142,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
table_iterator begin () const {
|
||||
iterator begin () const {
|
||||
return global.begin();
|
||||
}
|
||||
|
||||
table_iterator end() const {
|
||||
iterator end() const {
|
||||
return global.end();
|
||||
}
|
||||
|
||||
table_iterator cbegin() const {
|
||||
const_iterator cbegin() const {
|
||||
return global.cbegin();
|
||||
}
|
||||
|
||||
table_iterator cend() const {
|
||||
const_iterator cend() const {
|
||||
return global.cend();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,9 @@ template <std::size_t n>
|
|||
struct clean { lua_State* L; clean(lua_State* L) : L(L) {} ~clean() { lua_pop(L, static_cast<int>(n)); } };
|
||||
struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* L, int& n) : L(L), n(n) {} ~ref_clean() { lua_pop(L, static_cast<int>(n)); } };
|
||||
}
|
||||
template <bool top_level>
|
||||
class table_core : public reference {
|
||||
|
||||
template <bool top_level, typename base_t>
|
||||
class basic_table_core : public base_t {
|
||||
friend class state;
|
||||
friend class state_view;
|
||||
|
||||
|
@ -45,25 +46,25 @@ class table_core : public reference {
|
|||
template<typename Fx>
|
||||
void for_each(std::true_type, Fx&& fx) const {
|
||||
auto pp = stack::push_pop( *this );
|
||||
stack::push( lua_state( ), nil );
|
||||
while ( lua_next( this->lua_state( ), -2 ) ) {
|
||||
sol::object key( lua_state( ), -2 );
|
||||
sol::object value( lua_state( ), -1 );
|
||||
stack::push( base_t::lua_state( ), nil );
|
||||
while ( lua_next( base_t::lua_state( ), -2 ) ) {
|
||||
sol::object key( base_t::lua_state( ), -2 );
|
||||
sol::object value( base_t::lua_state( ), -1 );
|
||||
std::pair<sol::object&, sol::object&> keyvalue(key, value);
|
||||
fx( keyvalue );
|
||||
lua_pop( lua_state( ), 1 );
|
||||
lua_pop( base_t::lua_state( ), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Fx>
|
||||
void for_each(std::false_type, Fx&& fx) const {
|
||||
auto pp = stack::push_pop( *this );
|
||||
stack::push( lua_state( ), nil );
|
||||
while ( lua_next( this->lua_state( ), -2 ) ) {
|
||||
sol::object key( lua_state( ), -2 );
|
||||
sol::object value( lua_state( ), -1 );
|
||||
stack::push( base_t::lua_state( ), nil );
|
||||
while ( lua_next( base_t::lua_state( ), -2 ) ) {
|
||||
sol::object key( base_t::lua_state( ), -2 );
|
||||
sol::object value( base_t::lua_state( ), -1 );
|
||||
fx( key, value );
|
||||
lua_pop( lua_state( ), 1 );
|
||||
lua_pop( base_t::lua_state( ), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,21 +73,21 @@ class table_core : public reference {
|
|||
-> decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)){
|
||||
typedef decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) Tup;
|
||||
return Tup(
|
||||
traverse_get_optional<top_level, Ret0>(meta::is_specialization_of<meta::Unqualified<Ret0>, sol::optional>(), detail::forward_get<0>(keys)),
|
||||
traverse_get_optional<top_level, Ret1>(meta::is_specialization_of<meta::Unqualified<Ret1>, sol::optional>(), detail::forward_get<1>(keys)),
|
||||
traverse_get_optional<top_level, Ret>(meta::is_specialization_of<meta::Unqualified<Ret>, sol::optional>(), detail::forward_get<I>(keys))...
|
||||
traverse_get_optional<top_level, Ret0>(meta::is_specialization_of<sol::optional, meta::Unqualified<Ret0>>(), detail::forward_get<0>(keys)),
|
||||
traverse_get_optional<top_level, Ret1>(meta::is_specialization_of<sol::optional, meta::Unqualified<Ret1>>(), detail::forward_get<1>(keys)),
|
||||
traverse_get_optional<top_level, Ret>(meta::is_specialization_of<sol::optional, meta::Unqualified<Ret>>(), detail::forward_get<I>(keys))...
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Ret, std::size_t I, typename Keys>
|
||||
decltype(auto) tuple_get( types<Ret>, std::index_sequence<I>, Keys&& keys ) const {
|
||||
return traverse_get_optional<top_level, Ret>( meta::is_specialization_of<meta::Unqualified<Ret>, sol::optional>(), detail::forward_get<I>(keys) );
|
||||
return traverse_get_optional<top_level, Ret>( meta::is_specialization_of<sol::optional, meta::Unqualified<Ret>>(), detail::forward_get<I>(keys) );
|
||||
}
|
||||
|
||||
template<typename Pairs, std::size_t... I>
|
||||
void tuple_set( std::index_sequence<I...>, Pairs&& pairs ) {
|
||||
auto pp = stack::push_pop<top_level && (is_global<decltype(detail::forward_get<I * 2>(pairs))...>::value)>(*this);
|
||||
void(detail::swallow{ (stack::set_field<top_level>(lua_state(),
|
||||
void(detail::swallow{ (stack::set_field<top_level>(base_t::lua_state(),
|
||||
detail::forward_get<I * 2>(pairs),
|
||||
detail::forward_get<I * 2 + 1>(pairs)
|
||||
), 0)... });
|
||||
|
@ -94,28 +95,28 @@ class table_core : public reference {
|
|||
|
||||
template <bool global, typename T, typename Key>
|
||||
decltype(auto) traverse_get_deep( Key&& key ) const {
|
||||
stack::get_field<global>( lua_state( ), std::forward<Key>( key ) );
|
||||
return stack::get<T>( lua_state( ) );
|
||||
stack::get_field<global>( base_t::lua_state( ), std::forward<Key>( key ) );
|
||||
return stack::get<T>( base_t::lua_state( ) );
|
||||
}
|
||||
|
||||
template <bool global, typename T, typename Key, typename... Keys>
|
||||
decltype(auto) traverse_get_deep( Key&& key, Keys&&... keys ) const {
|
||||
stack::get_field<global>( lua_state( ), std::forward<Key>( key ) );
|
||||
stack::get_field<global>( base_t::lua_state( ), std::forward<Key>( key ) );
|
||||
return traverse_get_deep<false, T>(std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template <bool global, typename T, std::size_t I, typename Key>
|
||||
decltype(auto) traverse_get_deep_optional( int& popcount, Key&& key ) const {
|
||||
auto p = stack::probe_get_field<global>(lua_state(), std::forward<Key>(key), -1);
|
||||
auto p = stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), -1);
|
||||
popcount += p.levels;
|
||||
if (!p.success)
|
||||
return T(nullopt);
|
||||
return stack::get<T>( lua_state( ) );
|
||||
return stack::get<T>( base_t::lua_state( ) );
|
||||
}
|
||||
|
||||
template <bool global, typename T, std::size_t I, typename Key, typename... Keys>
|
||||
decltype(auto) traverse_get_deep_optional( int& popcount, Key&& key, Keys&&... keys ) const {
|
||||
auto p = I > 0 ? stack::probe_get_field<global>(lua_state(), std::forward<Key>(key), - 1) : stack::probe_get_field<global>( lua_state( ), std::forward<Key>( key ) );
|
||||
auto p = I > 0 ? stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), - 1) : stack::probe_get_field<global>( base_t::lua_state( ), std::forward<Key>( key ) );
|
||||
popcount += p.levels;
|
||||
if (!p.success)
|
||||
return T(nullopt);
|
||||
|
@ -124,52 +125,57 @@ class table_core : public reference {
|
|||
|
||||
template <bool global, typename T, typename... Keys>
|
||||
decltype(auto) traverse_get_optional( std::false_type, Keys&&... keys ) const {
|
||||
detail::clean<sizeof...(Keys)> c(lua_state());
|
||||
detail::clean<sizeof...(Keys)> c(base_t::lua_state());
|
||||
return traverse_get_deep<top_level, T>(std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template <bool global, typename T, typename... Keys>
|
||||
decltype(auto) traverse_get_optional( std::true_type, Keys&&... keys ) const {
|
||||
int popcount = 0;
|
||||
detail::ref_clean c(lua_state(), popcount);
|
||||
detail::ref_clean c(base_t::lua_state(), popcount);
|
||||
return traverse_get_deep_optional<top_level, T, 0>(popcount, std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template <bool global, typename Key, typename Value>
|
||||
void traverse_set_deep( Key&& key, Value&& value ) const {
|
||||
stack::set_field<global>( lua_state( ), std::forward<Key>( key ), std::forward<Value>(value) );
|
||||
stack::set_field<global>( base_t::lua_state( ), std::forward<Key>( key ), std::forward<Value>(value) );
|
||||
}
|
||||
|
||||
template <bool global, typename Key, typename... Keys>
|
||||
void traverse_set_deep( Key&& key, Keys&&... keys ) const {
|
||||
stack::get_field<global>( lua_state( ), std::forward<Key>( key ) );
|
||||
stack::get_field<global>( base_t::lua_state( ), std::forward<Key>( key ) );
|
||||
traverse_set_deep<false>(std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { }
|
||||
basic_table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { }
|
||||
|
||||
public:
|
||||
table_core( ) noexcept : reference( ) { }
|
||||
table_core( const table_core<true>& global ) noexcept : reference( global ) { }
|
||||
table_core( lua_State* L, int index = -1 ) : reference( L, index ) {
|
||||
typedef basic_table_iterator<base_t> iterator;
|
||||
typedef iterator const_iterator;
|
||||
|
||||
basic_table_core( ) noexcept : base_t( ) { }
|
||||
basic_table_core( const table_core<true>& global ) noexcept : base_t( global ) { }
|
||||
basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {}
|
||||
basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {}
|
||||
basic_table_core( lua_State* L, int index = -1 ) : base_t( L, index ) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert( L, index, type::table );
|
||||
#endif // Safety
|
||||
}
|
||||
|
||||
table_iterator begin () const {
|
||||
return table_iterator(*this);
|
||||
iterator begin () const {
|
||||
return iterator(*this);
|
||||
}
|
||||
|
||||
table_iterator end() const {
|
||||
return table_iterator();
|
||||
iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
table_iterator cbegin() const {
|
||||
const_iterator cbegin() const {
|
||||
return begin();
|
||||
}
|
||||
|
||||
table_iterator cend() const {
|
||||
const_iterator cend() const {
|
||||
return end();
|
||||
}
|
||||
|
||||
|
@ -202,48 +208,48 @@ public:
|
|||
template <typename T, typename... Keys>
|
||||
decltype(auto) traverse_get( Keys&&... keys ) const {
|
||||
auto pp = stack::push_pop<is_global<Keys...>::value>(*this);
|
||||
return traverse_get_optional<top_level, T>(meta::is_specialization_of<meta::Unqualified<T>, sol::optional>(), std::forward<Keys>(keys)...);
|
||||
return traverse_get_optional<top_level, T>(meta::is_specialization_of<sol::optional, meta::Unqualified<T>>(), std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template <typename... Keys>
|
||||
table_core& traverse_set( Keys&&... keys ) {
|
||||
basic_table_core& traverse_set( Keys&&... keys ) {
|
||||
auto pp = stack::push_pop<is_global<Keys...>::value>(*this);
|
||||
traverse_set_deep<top_level>(std::forward<Keys>(keys)...);
|
||||
lua_pop(lua_state(), static_cast<int>(sizeof...(Keys)-2));
|
||||
lua_pop(base_t::lua_state(), static_cast<int>(sizeof...(Keys)-2));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
table_core& set( Args&&... args ) {
|
||||
basic_table_core& set( Args&&... args ) {
|
||||
tuple_set(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
table_core& set_usertype( usertype<T>& user ) {
|
||||
basic_table_core& set_usertype( usertype<T>& user ) {
|
||||
return set_usertype(usertype_traits<T>::name, user);
|
||||
}
|
||||
|
||||
template<typename Key, typename T>
|
||||
table_core& set_usertype( Key&& key, usertype<T>& user ) {
|
||||
basic_table_core& set_usertype( Key&& key, usertype<T>& user ) {
|
||||
return set(std::forward<Key>(key), user);
|
||||
}
|
||||
|
||||
template<typename Class, typename... Args>
|
||||
table_core& new_usertype(const std::string& name, Args&&... args) {
|
||||
basic_table_core& new_usertype(const std::string& name, Args&&... args) {
|
||||
usertype<Class> utype(std::forward<Args>(args)...);
|
||||
set_usertype(name, utype);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename CTor0, typename... CTor, typename... Args>
|
||||
table_core& new_usertype(const std::string& name, Args&&... args) {
|
||||
basic_table_core& new_usertype(const std::string& name, Args&&... args) {
|
||||
constructors<types<CTor0, CTor...>> ctor{};
|
||||
return new_usertype<Class>(name, ctor, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Class, typename... CArgs, typename... Args>
|
||||
table_core& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) {
|
||||
basic_table_core& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) {
|
||||
usertype<Class> utype(ctor, std::forward<Args>(args)...);
|
||||
set_usertype(name, utype);
|
||||
return *this;
|
||||
|
@ -257,7 +263,7 @@ public:
|
|||
|
||||
size_t size( ) const {
|
||||
auto pp = stack::push_pop( *this );
|
||||
return lua_rawlen(lua_state(), -1);
|
||||
return lua_rawlen(base_t::lua_state(), -1);
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
|
@ -265,28 +271,28 @@ public:
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<table_core&, T> operator[]( T&& key ) & {
|
||||
return proxy<table_core&, T>( *this, std::forward<T>( key ) );
|
||||
proxy<basic_table_core&, T> operator[]( T&& key ) & {
|
||||
return proxy<basic_table_core&, T>( *this, std::forward<T>( key ) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<const table_core&, T> operator[]( T&& key ) const & {
|
||||
return proxy<const table_core&, T>( *this, std::forward<T>( key ) );
|
||||
proxy<const basic_table_core&, T> operator[]( T&& key ) const & {
|
||||
return proxy<const basic_table_core&, T>( *this, std::forward<T>( key ) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<table_core, T> operator[]( T&& key ) && {
|
||||
return proxy<table_core, T>( *this, std::forward<T>( key ) );
|
||||
proxy<basic_table_core, T> operator[]( T&& key ) && {
|
||||
return proxy<basic_table_core, T>( *this, std::forward<T>( key ) );
|
||||
}
|
||||
|
||||
template<typename Sig, typename Key, typename... Args>
|
||||
table_core& set_function( Key&& key, Args&&... args ) {
|
||||
basic_table_core& set_function( Key&& key, Args&&... args ) {
|
||||
set_fx( types<Sig>( ), std::forward<Key>( key ), std::forward<Args>( args )... );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Key, typename... Args>
|
||||
table_core& set_function( Key&& key, Args&&... args ) {
|
||||
basic_table_core& set_function( Key&& key, Args&&... args ) {
|
||||
set_fx( types<>( ), std::forward<Key>( key ), std::forward<Args>( args )... );
|
||||
return *this;
|
||||
}
|
||||
|
@ -297,12 +303,12 @@ private:
|
|||
set_resolved_function<R( Args... )>( std::forward<Key>( key ), std::forward<Fx>( fx ) );
|
||||
}
|
||||
|
||||
template<typename Fx, typename Key, meta::EnableIf<meta::is_specialization_of<meta::Unqualified<Fx>, overload_set>> = 0>
|
||||
template<typename Fx, typename Key, meta::EnableIf<meta::is_specialization_of<overload_set, meta::Unqualified<Fx>>> = 0>
|
||||
void set_fx( types<>, Key&& key, Fx&& fx ) {
|
||||
set(std::forward<Key>(key), std::forward<Fx>(fx));
|
||||
}
|
||||
|
||||
template<typename Fx, typename Key, typename... Args, meta::DisableIf<meta::is_specialization_of<meta::Unqualified<Fx>, overload_set>> = 0>
|
||||
template<typename Fx, typename Key, typename... Args, meta::DisableIf<meta::is_specialization_of<overload_set, meta::Unqualified<Fx>>> = 0>
|
||||
void set_fx( types<>, Key&& key, Fx&& fx, Args&&... args ) {
|
||||
set(std::forward<Key>(key), function_args(std::forward<Fx>(fx), std::forward<Args>(args)...));
|
||||
}
|
||||
|
@ -336,31 +342,31 @@ public:
|
|||
}
|
||||
|
||||
table create(int narr = 0, int nrec = 0) {
|
||||
return create(lua_state(), narr, nrec);
|
||||
return create(base_t::lua_state(), narr, nrec);
|
||||
}
|
||||
|
||||
template <typename Key, typename Value, typename... Args>
|
||||
table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
|
||||
return create(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
|
||||
return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Name>
|
||||
table create(Name&& name, int narr = 0, int nrec = 0) {
|
||||
table x = create(lua_state(), narr, nrec);
|
||||
table x = create(base_t::lua_state(), narr, nrec);
|
||||
this->set(std::forward<Name>(name), x);
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename Name, typename Key, typename Value, typename... Args>
|
||||
table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
|
||||
table x = create(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
|
||||
table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
|
||||
this->set(std::forward<Name>(name), x);
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
table create_with(Args&&... args) {
|
||||
return create_with(lua_state(), std::forward<Args>(args)...);
|
||||
return create_with(base_t::lua_state(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Name, typename... Args>
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
namespace sol {
|
||||
|
||||
class table_iterator : public std::iterator<std::input_iterator_tag, std::pair<object, object>> {
|
||||
template <typename reference_type>
|
||||
class basic_table_iterator : public std::iterator<std::input_iterator_tag, std::pair<object, object>> {
|
||||
private:
|
||||
typedef std::iterator<std::input_iterator_tag, std::pair<object, object>> base_t;
|
||||
public:
|
||||
|
@ -41,19 +42,18 @@ public:
|
|||
typedef const value_type& const_reference;
|
||||
|
||||
private:
|
||||
typedef ::sol::reference ref_t;
|
||||
std::pair<object, object> kvp;
|
||||
ref_t ref;
|
||||
reference_type ref;
|
||||
int tableidx = 0;
|
||||
std::ptrdiff_t idx = 0;
|
||||
|
||||
public:
|
||||
|
||||
table_iterator () : idx(-1) {
|
||||
basic_table_iterator () : idx(-1) {
|
||||
|
||||
}
|
||||
|
||||
table_iterator(ref_t x) : ref(std::move(x)) {
|
||||
basic_table_iterator(reference_type x) : ref(std::move(x)) {
|
||||
ref.push();
|
||||
tableidx = lua_gettop(ref.lua_state());
|
||||
stack::push(ref.lua_state(), nil);
|
||||
|
@ -64,7 +64,7 @@ public:
|
|||
--idx;
|
||||
}
|
||||
|
||||
table_iterator& operator++() {
|
||||
basic_table_iterator& operator++() {
|
||||
if (idx == -1)
|
||||
return *this;
|
||||
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
table_iterator operator++(int) {
|
||||
basic_table_iterator operator++(int) {
|
||||
auto saved = *this;
|
||||
this->operator++();
|
||||
return saved;
|
||||
|
@ -94,15 +94,15 @@ public:
|
|||
return kvp;
|
||||
}
|
||||
|
||||
bool operator== (const table_iterator& right) const {
|
||||
bool operator== (const basic_table_iterator& right) const {
|
||||
return idx == right.idx;
|
||||
}
|
||||
|
||||
bool operator!= (const table_iterator& right) const {
|
||||
bool operator!= (const basic_table_iterator& right) const {
|
||||
return idx != right.idx;
|
||||
}
|
||||
|
||||
~table_iterator() {
|
||||
~basic_table_iterator() {
|
||||
if (ref.valid()) {
|
||||
stack::remove(ref.lua_state(), tableidx, 1);
|
||||
}
|
||||
|
|
|
@ -70,10 +70,10 @@ struct remove_member_pointer<R T::* const> {
|
|||
template<typename T>
|
||||
using remove_member_pointer_t = remove_member_pointer<T>;
|
||||
|
||||
template<typename T, template<typename...> class Templ>
|
||||
template<template<typename...> class Templ, typename T>
|
||||
struct is_specialization_of : std::false_type { };
|
||||
template<typename... T, template<typename...> class Templ>
|
||||
struct is_specialization_of<Templ<T...>, Templ> : std::true_type { };
|
||||
struct is_specialization_of<Templ, Templ<T...>> : std::true_type { };
|
||||
|
||||
template<class T, class...>
|
||||
struct are_same : std::true_type { };
|
||||
|
@ -380,12 +380,12 @@ using is_c_str = Or<
|
|||
>;
|
||||
|
||||
namespace meta_detail {
|
||||
template <typename T, meta::DisableIf<meta::is_specialization_of<meta::Unqualified<T>, std::tuple>> = 0>
|
||||
template <typename T, meta::DisableIf<meta::is_specialization_of<std::tuple, meta::Unqualified<T>>> = 0>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward_as_tuple(std::forward<T>(x));
|
||||
}
|
||||
|
||||
template <typename T, meta::EnableIf<meta::is_specialization_of<meta::Unqualified<T>, std::tuple>> = 0>
|
||||
template <typename T, meta::EnableIf<meta::is_specialization_of<std::tuple, meta::Unqualified<T>>> = 0>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
|
|
|
@ -105,6 +105,12 @@ struct up_value_index {
|
|||
operator int() const { return index; }
|
||||
};
|
||||
|
||||
struct absolute_index {
|
||||
int index;
|
||||
absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {}
|
||||
operator int() const { return index; }
|
||||
};
|
||||
|
||||
struct light_userdata_value {
|
||||
void* value;
|
||||
light_userdata_value(void* data) : value(data) {}
|
||||
|
@ -203,17 +209,38 @@ class reference;
|
|||
class stack_reference;
|
||||
template<typename T>
|
||||
class usertype;
|
||||
template <bool>
|
||||
class table_core;
|
||||
template <bool, typename T>
|
||||
class basic_table_core;
|
||||
template <bool b>
|
||||
using table_core = basic_table_core<b, reference>;
|
||||
template <bool b>
|
||||
using stack_table_core = basic_table_core<b, stack_reference>;
|
||||
typedef table_core<false> table;
|
||||
typedef table_core<true> global_table;
|
||||
class function;
|
||||
class protected_function;
|
||||
typedef stack_table_core<false> stack_table;
|
||||
typedef stack_table_core<true> stack_global_table;
|
||||
template <typename T>
|
||||
class basic_function;
|
||||
template <typename T>
|
||||
class basic_protected_function;
|
||||
using function = basic_function<reference>;
|
||||
using protected_function = basic_protected_function<reference>;
|
||||
using stack_function = basic_function<stack_reference>;
|
||||
using stack_protected_function = basic_protected_function<stack_reference>;
|
||||
template <typename base_t>
|
||||
class basic_object;
|
||||
template <typename base_t>
|
||||
class basic_userdata;
|
||||
template <typename base_t>
|
||||
class basic_lightuserdata;
|
||||
using object = basic_object<reference>;
|
||||
using stack_object = basic_object<stack_reference>;
|
||||
using userdata = basic_userdata<reference>;
|
||||
using stack_userdata = basic_userdata<stack_reference>;
|
||||
using lightuserdata = basic_lightuserdata<reference>;
|
||||
using stack_lightuserdata = basic_lightuserdata<stack_reference>;
|
||||
class coroutine;
|
||||
class thread;
|
||||
class object;
|
||||
class userdata;
|
||||
class lightuserdata;
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct lua_type_of : std::integral_constant<type, type::userdata> {};
|
||||
|
@ -242,14 +269,20 @@ struct lua_type_of<table> : std::integral_constant<type, type::table> { };
|
|||
template <>
|
||||
struct lua_type_of<global_table> : std::integral_constant<type, type::table> { };
|
||||
|
||||
template <>
|
||||
struct lua_type_of<stack_table> : std::integral_constant<type, type::table> { };
|
||||
|
||||
template <>
|
||||
struct lua_type_of<stack_global_table> : std::integral_constant<type, type::table> { };
|
||||
|
||||
template <>
|
||||
struct lua_type_of<reference> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<object> : std::integral_constant<type, type::poly> {};
|
||||
template <typename Base>
|
||||
struct lua_type_of<basic_object<Base>> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <typename... Args>
|
||||
struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> {};
|
||||
|
@ -263,17 +296,20 @@ struct lua_type_of<light_userdata_value> : std::integral_constant<type, type::li
|
|||
template <>
|
||||
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<lightuserdata> : std::integral_constant<type, type::lightuserdata> {};
|
||||
template <typename Base>
|
||||
struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<userdata> : std::integral_constant<type, type::userdata> {};
|
||||
template <typename Base>
|
||||
struct lua_type_of<basic_userdata<Base>> : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<function> : std::integral_constant<type, type::function> {};
|
||||
template <typename Base>
|
||||
struct lua_type_of<basic_function<Base>> : std::integral_constant<type, type::function> {};
|
||||
|
||||
template <typename Base>
|
||||
struct lua_type_of<basic_protected_function<Base>> : std::integral_constant<type, type::function> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {};
|
||||
|
@ -281,9 +317,6 @@ struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {};
|
|||
template <>
|
||||
struct lua_type_of<thread> : std::integral_constant<type, type::thread> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<protected_function> : std::integral_constant<type, type::function> {};
|
||||
|
||||
template <typename Signature>
|
||||
struct lua_type_of<std::function<Signature>> : std::integral_constant<type, type::function>{};
|
||||
|
||||
|
@ -303,10 +336,15 @@ template <typename T>
|
|||
struct is_lua_primitive : std::integral_constant<bool,
|
||||
type::userdata != lua_type_of<meta::Unqualified<T>>::value
|
||||
|| std::is_base_of<reference, meta::Unqualified<T>>::value
|
||||
|| meta::is_specialization_of<meta::Unqualified<T>, std::tuple>::value
|
||||
|| meta::is_specialization_of<meta::Unqualified<T>, std::pair>::value
|
||||
|| std::is_base_of<stack_reference, meta::Unqualified<T>>::value
|
||||
|| meta::is_specialization_of<std::tuple, meta::Unqualified<T>>::value
|
||||
|| meta::is_specialization_of<std::pair, meta::Unqualified<T>>::value
|
||||
> { };
|
||||
|
||||
template <typename T>
|
||||
struct is_lua_primitive<std::reference_wrapper<T>> : std::true_type { };
|
||||
template <typename T>
|
||||
struct is_lua_primitive<optional<T>> : std::true_type {};
|
||||
template <typename T>
|
||||
struct is_lua_primitive<T*> : std::true_type {};
|
||||
template <>
|
||||
|
@ -319,12 +357,6 @@ struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> {};
|
|||
template <typename T>
|
||||
struct is_proxy_primitive : is_lua_primitive<T> { };
|
||||
|
||||
template <typename T>
|
||||
struct is_proxy_primitive<std::reference_wrapper<T>> : std::true_type { };
|
||||
|
||||
template <typename T>
|
||||
struct is_proxy_primitive<optional<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_unique_usertype : std::false_type {};
|
||||
|
||||
|
|
|
@ -25,28 +25,34 @@
|
|||
#include "reference.hpp"
|
||||
|
||||
namespace sol {
|
||||
class userdata : public reference {
|
||||
template <typename base_t>
|
||||
class basic_userdata : public base_t {
|
||||
public:
|
||||
userdata () noexcept = default;
|
||||
userdata(const userdata&) = default;
|
||||
userdata(userdata&&) = default;
|
||||
userdata& operator=(const userdata&) = default;
|
||||
userdata& operator=(userdata&&) = default;
|
||||
userdata(lua_State* L, int index = -1) : reference(L, index) {
|
||||
basic_userdata () noexcept = default;
|
||||
basic_userdata(const basic_userdata&) = default;
|
||||
basic_userdata(basic_userdata&&) = default;
|
||||
basic_userdata& operator=(const basic_userdata&) = default;
|
||||
basic_userdata& operator=(basic_userdata&&) = default;
|
||||
basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {}
|
||||
basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {}
|
||||
basic_userdata(lua_State* L, int index = -1) : base_t(L, index) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert(L, index, type::userdata);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
class lightuserdata : public reference {
|
||||
template <typename base_t>
|
||||
class basic_lightuserdata : public base_t {
|
||||
public:
|
||||
lightuserdata () noexcept = default;
|
||||
lightuserdata(const lightuserdata&) = default;
|
||||
lightuserdata(lightuserdata&&) = default;
|
||||
lightuserdata& operator=(const lightuserdata&) = default;
|
||||
lightuserdata& operator=(lightuserdata&&) = default;
|
||||
lightuserdata(lua_State* L, int index = -1) : reference(L, index) {
|
||||
basic_lightuserdata () noexcept = default;
|
||||
basic_lightuserdata(const basic_lightuserdata&) = default;
|
||||
basic_lightuserdata(basic_lightuserdata&&) = default;
|
||||
basic_lightuserdata& operator=(const basic_lightuserdata&) = default;
|
||||
basic_lightuserdata& operator=(basic_lightuserdata&&) = default;
|
||||
basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {}
|
||||
basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {}
|
||||
basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert(L, index, type::lightuserdata);
|
||||
#endif // Safety
|
||||
|
|
57
tests.cpp
57
tests.cpp
|
@ -801,3 +801,60 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
|
|||
|
||||
REQUIRE_THROWS(lua.script("r:func(1,2,'meow')"));
|
||||
}
|
||||
|
||||
TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
|
||||
struct bark {
|
||||
int var = 50;
|
||||
};
|
||||
struct woof {
|
||||
bark b;
|
||||
};
|
||||
|
||||
struct nested {
|
||||
const int f = 25;
|
||||
};
|
||||
|
||||
struct outer {
|
||||
nested n;
|
||||
};
|
||||
|
||||
bool caughterror = false;
|
||||
std::string msg;
|
||||
sol::state lua;
|
||||
lua.new_usertype<woof>("woof",
|
||||
"b", &woof::b);
|
||||
lua.new_usertype<bark>("bark",
|
||||
"var", &bark::var);
|
||||
lua.new_usertype<outer>("outer",
|
||||
"n", &outer::n);
|
||||
lua.set("w", woof());
|
||||
lua.set("n", nested());
|
||||
lua.set("o", outer());
|
||||
lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
|
||||
try {
|
||||
lua.script(R"(
|
||||
x = w.b
|
||||
x.var = 20
|
||||
val = w.b.var == x.var
|
||||
v = f(n);
|
||||
f(n, 50)
|
||||
)");
|
||||
}
|
||||
catch (const sol::error& e) {
|
||||
msg = e.what();
|
||||
caughterror = true;
|
||||
}
|
||||
REQUIRE(caughterror);
|
||||
REQUIRE(!msg.empty());
|
||||
woof& w = lua["w"];
|
||||
bark& x = lua["x"];
|
||||
nested& n = lua["n"];
|
||||
int v = lua["v"];
|
||||
bool val = lua["val"];
|
||||
// enforce reference semantics
|
||||
REQUIRE(std::addressof(w.b) == std::addressof(x));
|
||||
REQUIRE(n.f == 25);
|
||||
REQUIRE(v == 25);
|
||||
REQUIRE(val);
|
||||
REQUIRE_THROWS(lua.script("o.n = 25"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user