mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
This mega-commit implements the new usertype_metatable
while keeping everything else still intact. Blurgh, managing API versions suck...
This commit is contained in:
parent
9b65fb9f93
commit
e35fe6be85
2
Optional
2
Optional
|
@ -1 +1 @@
|
||||||
Subproject commit e62740b328e100ac76821e151cb3cfe7412bd98a
|
Subproject commit f11b4f00eb029862dd2a4d7e3497324aba8a020f
|
218
sol/bind_traits.hpp
Normal file
218
sol/bind_traits.hpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tuple.hpp"
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
namespace meta {
|
||||||
|
namespace meta_detail {
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct check_deducible_signature {
|
||||||
|
struct nat {};
|
||||||
|
template<class G>
|
||||||
|
static auto test(int) -> decltype(&G::operator(), void());
|
||||||
|
template<class>
|
||||||
|
static auto test(...) -> nat;
|
||||||
|
|
||||||
|
using type = std::is_void<decltype(test<F>(0))>;
|
||||||
|
};
|
||||||
|
} // meta_detail
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
||||||
|
|
||||||
|
namespace meta_detail {
|
||||||
|
|
||||||
|
template <std::size_t I, typename T>
|
||||||
|
struct void_tuple_element : meta::tuple_element<I, T> {};
|
||||||
|
|
||||||
|
template <std::size_t I>
|
||||||
|
struct void_tuple_element<I, std::tuple<>> { typedef void type; };
|
||||||
|
|
||||||
|
template <std::size_t I, typename T>
|
||||||
|
using void_tuple_element_t = typename void_tuple_element<I, T>::type;
|
||||||
|
|
||||||
|
template <bool has_c_variadic, typename T, typename R, typename... Args>
|
||||||
|
struct basic_traits {
|
||||||
|
private:
|
||||||
|
typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool is_member_function = std::is_void<T>::value;
|
||||||
|
static const bool has_c_var_arg = has_c_variadic;
|
||||||
|
static const std::size_t arity = sizeof...(Args);
|
||||||
|
static const std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value);
|
||||||
|
typedef types<Args...> args_list;
|
||||||
|
typedef std::tuple<Args...> args_tuple;
|
||||||
|
typedef T object_type;
|
||||||
|
typedef R return_type;
|
||||||
|
typedef tuple_types<R> returns_list;
|
||||||
|
typedef R(function_type)(Args...);
|
||||||
|
typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list;
|
||||||
|
typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type;
|
||||||
|
typedef std::conditional_t<std::is_void<T>::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type;
|
||||||
|
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
||||||
|
template<std::size_t i>
|
||||||
|
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
||||||
|
struct fx_traits : basic_traits<false, void, void> {};
|
||||||
|
|
||||||
|
// Free Functions
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||||
|
typedef R(*function_pointer_type)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> {
|
||||||
|
typedef R(*function_pointer_type)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||||
|
typedef R(*function_pointer_type)(Args..., ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> {
|
||||||
|
typedef R(*function_pointer_type)(Args..., ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
/* C-Style Variadics */
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Const Volatile */
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) const volatile;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) const volatile;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Member Function Qualifiers */
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) &;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) &;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) const &;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) const &;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) const volatile &;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) &&, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) &&, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) const &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) const &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args...) const volatile &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename R, typename... Args>
|
||||||
|
struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> {
|
||||||
|
typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Signature>
|
||||||
|
struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {};
|
||||||
|
|
||||||
|
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
||||||
|
struct callable_traits : fx_traits<std::decay_t<Signature>> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename T>
|
||||||
|
struct callable_traits<R(T::*), true> {
|
||||||
|
typedef R Arg;
|
||||||
|
typedef T object_type;
|
||||||
|
using signature_type = R(T::*);
|
||||||
|
static const bool is_member_function = false;
|
||||||
|
static const std::size_t arity = 1;
|
||||||
|
static const std::size_t free_arity = 2;
|
||||||
|
typedef std::tuple<Arg> args_tuple;
|
||||||
|
typedef R return_type;
|
||||||
|
typedef types<Arg> args_list;
|
||||||
|
typedef meta::tuple_types<R> returns_list;
|
||||||
|
typedef R(function_type)(T&, R);
|
||||||
|
typedef R(*function_pointer_type)(T&, R);
|
||||||
|
typedef R(*free_function_pointer_type)(T&, R);
|
||||||
|
template<std::size_t i>
|
||||||
|
using arg_at = void_tuple_element_t<i, args_tuple>;
|
||||||
|
};
|
||||||
|
} // meta_detail
|
||||||
|
|
||||||
|
template<typename Signature>
|
||||||
|
struct bind_traits : meta_detail::callable_traits<Signature> {};
|
||||||
|
|
||||||
|
template<typename Signature>
|
||||||
|
using function_args_t = typename bind_traits<Signature>::args_list;
|
||||||
|
|
||||||
|
template<typename Signature>
|
||||||
|
using function_signature_t = typename bind_traits<Signature>::signature_type;
|
||||||
|
|
||||||
|
template<typename Signature>
|
||||||
|
using function_return_t = typename bind_traits<Signature>::return_type;
|
||||||
|
|
||||||
|
} // meta
|
||||||
|
} // sol
|
282
sol/call.hpp
Normal file
282
sol/call.hpp
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors
|
||||||
|
|
||||||
|
// 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 SOL_CALL_HPP
|
||||||
|
#define SOL_CALL_HPP
|
||||||
|
|
||||||
|
#include "wrapper.hpp"
|
||||||
|
#include "property.hpp"
|
||||||
|
#include "stack.hpp"
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
namespace call_detail {
|
||||||
|
|
||||||
|
template <bool b, typename F>
|
||||||
|
inline decltype(auto) pick(std::integral_constant<bool, b>, F&& f) {
|
||||||
|
return std::forward<F>(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename W>
|
||||||
|
inline auto& pick(std::true_type, property_wrapper<R, W>& f) {
|
||||||
|
return f.read;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename W>
|
||||||
|
inline auto& pick(std::false_type, property_wrapper<R, W>& f) {
|
||||||
|
return f.write;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace overload_detail {
|
||||||
|
template <std::size_t... M, typename Match, typename... Args>
|
||||||
|
inline int overload_match_arity(sol::types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) {
|
||||||
|
return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args>
|
||||||
|
inline int overload_match_arity(sol::types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||||
|
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits;
|
||||||
|
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||||
|
typedef typename traits::free_args_list args_list;
|
||||||
|
typedef typename args_list::indices args_indices;
|
||||||
|
int farity = traits::free_arity;
|
||||||
|
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
||||||
|
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
|
||||||
|
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
if (traits::free_arity != fxarity) {
|
||||||
|
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
if (!stack::stack_detail::check_types<true>().check(args_list(), args_indices(), L, start, no_panic)) {
|
||||||
|
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
} // overload_detail
|
||||||
|
|
||||||
|
template <typename... Functions, typename Match, typename... Args>
|
||||||
|
inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) {
|
||||||
|
return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Functions, typename Match, typename... Args>
|
||||||
|
inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) {
|
||||||
|
int fxarity = lua_gettop(L) - (start - 1);
|
||||||
|
return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F, bool is_index, bool is_variable, typename = void>
|
||||||
|
struct agnostic_lua_call_wrapper {
|
||||||
|
static int var_call(std::true_type, lua_State* L, F f) {
|
||||||
|
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||||
|
typedef typename wrap::returns_list returns_list;
|
||||||
|
typedef typename wrap::free_args_list args_list;
|
||||||
|
return stack::call_into_lua<is_index ? 1 : 2>(returns_list(), args_list(), L, is_index ? 2 : 3, wrap::caller(), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int var_call(std::false_type, lua_State* L, F f) {
|
||||||
|
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||||
|
typedef typename wrap::free_args_list args_list;
|
||||||
|
typedef typename wrap::returns_list returns_list;
|
||||||
|
return stack::call_into_lua(returns_list(), args_list(), L, 1, wrap::caller(), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call(lua_State* L, F f) {
|
||||||
|
return var_call(std::integral_constant<bool, is_variable>(), L, f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F, bool is_index, bool is_variable>
|
||||||
|
struct agnostic_lua_call_wrapper<F, is_index, is_variable, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
|
||||||
|
static int call(lua_State* L, F f) {
|
||||||
|
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||||
|
typedef typename wrap::returns_list returns_list;
|
||||||
|
typedef typename wrap::args_list args_list;
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
typedef typename wrap::object_type object_type;
|
||||||
|
object_type* o = stack::get<object_type*>(L, 1);
|
||||||
|
if (o == nullptr) {
|
||||||
|
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
|
||||||
|
}
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f, *o);
|
||||||
|
#else
|
||||||
|
object_type& o = stack::get<object_type&>(L, 1);
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f);
|
||||||
|
#endif // Safety
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool is_index, bool is_variable, typename C>
|
||||||
|
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, C> {
|
||||||
|
static int call(lua_State* L, no_prop) {
|
||||||
|
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F, bool is_variable>
|
||||||
|
struct agnostic_lua_call_wrapper<F, false, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||||
|
typedef sol::lua_bind_traits<F> traits_type;
|
||||||
|
|
||||||
|
static int call_assign(std::true_type, lua_State* L, F f) {
|
||||||
|
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||||
|
typedef typename wrap::args_list args_list;
|
||||||
|
typedef typename wrap::object_type object_type;
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
object_type* o = stack::get<object_type*>(L, 1);
|
||||||
|
if (o == nullptr) {
|
||||||
|
if (is_variable) {
|
||||||
|
return luaL_error(L, "sol: received null for 'self' argument (bad '.' access?)");
|
||||||
|
}
|
||||||
|
return luaL_error(L, "sol: received null for 'self' argument (pass 'self' as first argument)");
|
||||||
|
}
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f, *o);
|
||||||
|
#else
|
||||||
|
object_type& o = stack::get<object_type&>(L, 1);
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, wrap::caller(), f, o);
|
||||||
|
#endif // Safety
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call_assign(std::false_type, lua_State* L, F f) {
|
||||||
|
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call_const(std::false_type, lua_State* L, F f) {
|
||||||
|
typedef typename traits_type::return_type R;
|
||||||
|
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call_const(std::true_type, lua_State* L, F f) {
|
||||||
|
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call(lua_State* L, F f) {
|
||||||
|
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F, bool is_variable>
|
||||||
|
struct agnostic_lua_call_wrapper<F, true, is_variable, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
|
||||||
|
typedef sol::lua_bind_traits<F> traits_type;
|
||||||
|
|
||||||
|
static int call(lua_State* L, F f) {
|
||||||
|
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||||
|
typedef typename wrap::object_type object_type;
|
||||||
|
typedef typename wrap::returns_list returns_list;
|
||||||
|
#ifdef SOL_SAFE_USERTYPE
|
||||||
|
object_type* o = stack::get<object_type*>(L, 1);
|
||||||
|
if (o == nullptr) {
|
||||||
|
if (is_variable) {
|
||||||
|
return luaL_error(L, "sol: 'self' argument is nullptr (bad '.' access?)");
|
||||||
|
}
|
||||||
|
return luaL_error(L, "sol: 'self' argument is nullptr (pass 'self' as first argument)");
|
||||||
|
}
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, wrap::caller(), f, *o);
|
||||||
|
#else
|
||||||
|
object_type& o = stack::get<object_type&>(L, 1);
|
||||||
|
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, wrap::caller(), f, o);
|
||||||
|
#endif // Safety
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Fs, bool is_index, bool is_variable, typename C>
|
||||||
|
struct agnostic_lua_call_wrapper<sol::overload_set<Fs...>, is_index, is_variable, C> {
|
||||||
|
typedef sol::overload_set<Fs...> F;
|
||||||
|
|
||||||
|
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||||
|
static int select_call(sol::types<Fx>, sol::index_value<I>, sol::types<R...> r, sol::types<Args...> a, lua_State* L, int, int start, F& fx) {
|
||||||
|
auto& f = std::get<I>(fx.set);
|
||||||
|
return agnostic_lua_call_wrapper<Fx, is_index, is_variable>{}.call(L, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call(lua_State* L, F& fx) {
|
||||||
|
auto mfx = [&](auto&&... args) { return select_call(std::forward<decltype(args)>(args)...); };
|
||||||
|
return overload_match_arity<Fs...>(mfx, L, lua_gettop(L), 1, fx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool is_index, bool is_variable, typename C>
|
||||||
|
struct agnostic_lua_call_wrapper<sol::no_construction, is_index, is_variable, C> {
|
||||||
|
static int call(lua_State* L, sol::no_construction&) {
|
||||||
|
return luaL_error(L, "cannot call something tagged with 'no construction'");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename F, bool is_index, bool is_variable, typename = void>
|
||||||
|
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable> {};
|
||||||
|
|
||||||
|
template <typename T, typename... Args, bool is_index, bool is_variable, typename C>
|
||||||
|
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, C> {
|
||||||
|
typedef sol::constructor_list<Args...> F;
|
||||||
|
|
||||||
|
static int call(lua_State* L, F&) {
|
||||||
|
static const auto& meta = usertype_traits<T>::metatable;
|
||||||
|
int argcount = lua_gettop(L);
|
||||||
|
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
|
||||||
|
argcount -= static_cast<int>(syntax);
|
||||||
|
|
||||||
|
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||||
|
T*& referencepointer = *pointerpointer;
|
||||||
|
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
||||||
|
referencepointer = obj;
|
||||||
|
reference userdataref(L, -1);
|
||||||
|
userdataref.pop();
|
||||||
|
|
||||||
|
function_detail::construct<T, Args...>(detail::constructor_match<T>(obj), L, argcount, 1 + static_cast<int>(syntax));
|
||||||
|
|
||||||
|
userdataref.push();
|
||||||
|
luaL_getmetatable(L, &meta[0]);
|
||||||
|
if (stack::get<type>(L) == type::nil) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return luaL_error(L, "sol: unable to get usertype metatable");
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, bool is_index, bool is_variable, typename Fx>
|
||||||
|
int call_wrapped(lua_State* L, Fx&& fx) {
|
||||||
|
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable>{}.call(L, std::forward<Fx>(fx));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct is_var_bind : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_var_bind<no_prop> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename R, typename W>
|
||||||
|
struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
|
||||||
|
|
||||||
|
} // call_detail
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_function_binding : meta::neg<is_variable_binding<T>> {};
|
||||||
|
|
||||||
|
} // sol
|
||||||
|
|
||||||
|
#endif // SOL_CALL_HPP
|
|
@ -59,7 +59,7 @@ private:
|
||||||
|
|
||||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
|
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) {
|
||||||
int stacksize = lua_gettop( lua_state() );
|
int stacksize = lua_gettop( lua_state() );
|
||||||
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
|
int firstreturn = (std::max)( 1, stacksize - static_cast<int>( n ) );
|
||||||
luacall(n, LUA_MULTRET);
|
luacall(n, LUA_MULTRET);
|
||||||
int poststacksize = lua_gettop(lua_state());
|
int poststacksize = lua_gettop(lua_state());
|
||||||
int returncount = poststacksize - (firstreturn - 1);
|
int returncount = poststacksize - (firstreturn - 1);
|
||||||
|
|
|
@ -57,7 +57,7 @@ private:
|
||||||
|
|
||||||
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const {
|
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const {
|
||||||
int stacksize = lua_gettop( base_t::lua_state( ) );
|
int stacksize = lua_gettop( base_t::lua_state( ) );
|
||||||
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
|
int firstreturn = (std::max)( 1, stacksize - static_cast<int>( n ) );
|
||||||
luacall(n, LUA_MULTRET);
|
luacall(n, LUA_MULTRET);
|
||||||
int poststacksize = lua_gettop( base_t::lua_state( ) );
|
int poststacksize = lua_gettop( base_t::lua_state( ) );
|
||||||
int returncount = poststacksize - (firstreturn - 1);
|
int returncount = poststacksize - (firstreturn - 1);
|
||||||
|
@ -100,7 +100,7 @@ namespace stack {
|
||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
struct getter<std::function<Signature>> {
|
struct getter<std::function<Signature>> {
|
||||||
typedef meta::bind_traits<Signature> fx_t;
|
typedef meta::bind_traits<Signature> fx_t;
|
||||||
typedef typename fx_t::args_type args_types;
|
typedef typename fx_t::args_list args_lists;
|
||||||
typedef meta::tuple_types<typename fx_t::return_type> return_types;
|
typedef meta::tuple_types<typename fx_t::return_type> return_types;
|
||||||
|
|
||||||
template<typename... Args, typename... Ret>
|
template<typename... Args, typename... Ret>
|
||||||
|
@ -127,7 +127,7 @@ struct getter<std::function<Signature>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::function<Signature> get(lua_State* L, int index) {
|
static std::function<Signature> get(lua_State* L, int index) {
|
||||||
return get_std_func(return_types(), args_types(), L, index);
|
return get_std_func(return_types(), args_lists(), L, index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // stack
|
} // stack
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "function_types_overload.hpp"
|
#include "function_types_overload.hpp"
|
||||||
#include "function_types_allocator.hpp"
|
#include "function_types_allocator.hpp"
|
||||||
#include "resolve.hpp"
|
#include "resolve.hpp"
|
||||||
|
#include "call.hpp"
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
template <typename Sig, typename... Ps>
|
template <typename Sig, typename... Ps>
|
||||||
|
@ -45,13 +46,6 @@ function_arguments<Sig, Args...> function_args( Args&&... args ) {
|
||||||
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
return function_arguments<Sig, Args...>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow someone to make a member variable readonly (const)
|
|
||||||
template <typename R, typename T>
|
|
||||||
auto readonly( R T::* v ) {
|
|
||||||
typedef const R C;
|
|
||||||
return static_cast<C T::*>( v );
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace stack {
|
namespace stack {
|
||||||
template<typename... Sigs>
|
template<typename... Sigs>
|
||||||
struct pusher<function_sig<Sigs...>> {
|
struct pusher<function_sig<Sigs...>> {
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct upvalue_free_function {
|
||||||
static int real_call(lua_State* L) {
|
static int real_call(lua_State* L) {
|
||||||
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
|
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
|
||||||
function_type* fx = udata.first;
|
function_type* fx = udata.first;
|
||||||
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L, 1, fx);
|
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ struct upvalue_member_function {
|
||||||
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
|
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
|
||||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
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(), L, 1, fx);
|
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int call (lua_State* L) {
|
static int call (lua_State* L) {
|
||||||
|
@ -151,7 +151,7 @@ struct upvalue_this_member_function {
|
||||||
auto& item = stack::get<T>(L, 1);
|
auto& item = stack::get<T>(L, 1);
|
||||||
return (item.*memfx)(std::forward<decltype(args)>(args)...);
|
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(), L, 2, fx);
|
int n = stack::call_into_lua<1>(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 2, fx);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,13 @@
|
||||||
#define SOL_FUNCTION_TYPES_CORE_HPP
|
#define SOL_FUNCTION_TYPES_CORE_HPP
|
||||||
|
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
|
#include "wrapper.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
namespace detail {
|
||||||
|
struct empty {};
|
||||||
|
}
|
||||||
template <typename RSig = void, typename WSig = void>
|
template <typename RSig = void, typename WSig = void>
|
||||||
struct member_property {
|
struct member_property {
|
||||||
typedef std::conditional_t<std::is_void<RSig>::value, detail::empty, RSig> R;
|
typedef std::conditional_t<std::is_void<RSig>::value, detail::empty, RSig> R;
|
||||||
|
@ -150,7 +154,7 @@ inline decltype(auto) cleanup_key() {
|
||||||
template<typename T, typename Func, typename = void>
|
template<typename T, typename Func, typename = void>
|
||||||
struct functor {
|
struct functor {
|
||||||
typedef meta::bind_traits<Func> traits_type;
|
typedef meta::bind_traits<Func> traits_type;
|
||||||
typedef typename traits_type::args_type args_type;
|
typedef typename traits_type::args_list args_list;
|
||||||
typedef typename traits_type::return_type return_type;
|
typedef typename traits_type::return_type return_type;
|
||||||
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
|
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
|
||||||
static const std::size_t arity = traits_type::arity;
|
static const std::size_t arity = traits_type::arity;
|
||||||
|
@ -179,7 +183,7 @@ struct functor {
|
||||||
template<typename T, typename Func>
|
template<typename T, typename Func>
|
||||||
struct functor<T, Func, std::enable_if_t<!std::is_member_pointer<Func>::value && std::is_base_of<T, meta::unqualified_t<typename meta::bind_traits<Func>::template arg_at<0>>>::value>> {
|
struct functor<T, Func, std::enable_if_t<!std::is_member_pointer<Func>::value && std::is_base_of<T, meta::unqualified_t<typename meta::bind_traits<Func>::template arg_at<0>>>::value>> {
|
||||||
typedef meta::bind_traits<Func> traits_type;
|
typedef meta::bind_traits<Func> traits_type;
|
||||||
typedef meta::pop_front_type_t<typename traits_type::args_type> args_type;
|
typedef meta::pop_front_type_t<typename traits_type::args_list> args_list;
|
||||||
typedef typename traits_type::return_type return_type;
|
typedef typename traits_type::return_type return_type;
|
||||||
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
|
typedef std::conditional_t<std::is_pointer<Func>::value || std::is_class<Func>::value, Func, std::add_pointer_t<Func>> function_type;
|
||||||
static const std::size_t arity = traits_type::arity - 1;
|
static const std::size_t arity = traits_type::arity - 1;
|
||||||
|
@ -211,7 +215,7 @@ struct functor<T, Func, std::enable_if_t<!std::is_member_pointer<Func>::value &&
|
||||||
template<typename T, typename RSig, typename WSig, typename C>
|
template<typename T, typename RSig, typename WSig, typename C>
|
||||||
struct functor<T, member_property<RSig, WSig>, C> {
|
struct functor<T, member_property<RSig, WSig>, C> {
|
||||||
typedef meta::bind_traits<std::conditional_t<std::is_void<WSig>::value, RSig, WSig>> traits_type;
|
typedef meta::bind_traits<std::conditional_t<std::is_void<WSig>::value, RSig, WSig>> traits_type;
|
||||||
typedef meta::pop_front_type_t<typename traits_type::args_type> args_type;
|
typedef meta::pop_front_type_t<typename traits_type::args_list> args_list;
|
||||||
typedef std::conditional_t<std::is_void<typename traits_type::return_type>::value, typename traits_type::template arg_at<0>, typename traits_type::return_type> return_type;
|
typedef std::conditional_t<std::is_void<typename traits_type::return_type>::value, typename traits_type::template arg_at<0>, typename traits_type::return_type> return_type;
|
||||||
typedef member_property<RSig, WSig> function_type;
|
typedef member_property<RSig, WSig> function_type;
|
||||||
typedef meta::neg<std::is_void<RSig>> can_read;
|
typedef meta::neg<std::is_void<RSig>> can_read;
|
||||||
|
@ -244,7 +248,7 @@ struct functor<T, member_property<RSig, WSig>, C> {
|
||||||
template<typename T, typename Func>
|
template<typename T, typename Func>
|
||||||
struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::value>> {
|
struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::value>> {
|
||||||
typedef meta::bind_traits<Func> traits_type;
|
typedef meta::bind_traits<Func> traits_type;
|
||||||
typedef typename traits_type::args_type args_type;
|
typedef typename traits_type::args_list args_list;
|
||||||
typedef typename traits_type::return_type return_type;
|
typedef typename traits_type::return_type return_type;
|
||||||
static const std::size_t arity = traits_type::arity;
|
static const std::size_t arity = traits_type::arity;
|
||||||
typedef std::true_type can_read;
|
typedef std::true_type can_read;
|
||||||
|
@ -277,7 +281,7 @@ struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::va
|
||||||
template<typename T, typename Func>
|
template<typename T, typename Func>
|
||||||
struct functor<T, Func, std::enable_if_t<std::is_member_function_pointer<Func>::value>> {
|
struct functor<T, Func, std::enable_if_t<std::is_member_function_pointer<Func>::value>> {
|
||||||
typedef meta::bind_traits<Func> traits_type;
|
typedef meta::bind_traits<Func> traits_type;
|
||||||
typedef typename traits_type::args_type args_type;
|
typedef typename traits_type::args_list args_list;
|
||||||
typedef typename traits_type::return_type return_type;
|
typedef typename traits_type::return_type return_type;
|
||||||
static const std::size_t arity = traits_type::arity;
|
static const std::size_t arity = traits_type::arity;
|
||||||
static const bool is_free = false;
|
static const bool is_free = false;
|
||||||
|
|
|
@ -30,14 +30,14 @@ template<typename Func>
|
||||||
struct free_function : public base_function {
|
struct free_function : public base_function {
|
||||||
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function;
|
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function;
|
||||||
typedef meta::function_return_t<Function> return_type;
|
typedef meta::function_return_t<Function> return_type;
|
||||||
typedef meta::function_args_t<Function> args_types;
|
typedef meta::function_args_t<Function> args_lists;
|
||||||
Function fx;
|
Function fx;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
free_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
free_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
int call(lua_State* L) {
|
int call(lua_State* L) {
|
||||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
return stack::call_into_lua(meta::tuple_types<return_type>(), args_lists(), L, 1, fx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int operator()(lua_State* L) override {
|
virtual int operator()(lua_State* L) override {
|
||||||
|
@ -51,14 +51,14 @@ struct functor_function : public base_function {
|
||||||
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function;
|
typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function;
|
||||||
typedef decltype(&Function::operator()) function_type;
|
typedef decltype(&Function::operator()) function_type;
|
||||||
typedef meta::function_return_t<function_type> return_type;
|
typedef meta::function_return_t<function_type> return_type;
|
||||||
typedef meta::function_args_t<function_type> args_types;
|
typedef meta::function_args_t<function_type> args_lists;
|
||||||
Function fx;
|
Function fx;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
functor_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
functor_function(Args&&... args): fx(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
int call(lua_State* L) {
|
int call(lua_State* L) {
|
||||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
return stack::call_into_lua(meta::tuple_types<return_type>(), args_lists(), L, 1, fx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int operator()(lua_State* L) override {
|
virtual int operator()(lua_State* L) override {
|
||||||
|
@ -71,7 +71,7 @@ template<typename T, typename Function>
|
||||||
struct member_function : public base_function {
|
struct member_function : public base_function {
|
||||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||||
typedef meta::function_return_t<function_type> return_type;
|
typedef meta::function_return_t<function_type> return_type;
|
||||||
typedef meta::function_args_t<function_type> args_types;
|
typedef meta::function_args_t<function_type> args_lists;
|
||||||
struct functor {
|
struct functor {
|
||||||
function_type invocation;
|
function_type invocation;
|
||||||
T member;
|
T member;
|
||||||
|
@ -90,7 +90,7 @@ struct member_function : public base_function {
|
||||||
member_function(F&& f, Args&&... args) : fx(std::forward<F>(f), std::forward<Args>(args)...) {}
|
member_function(F&& f, Args&&... args) : fx(std::forward<F>(f), std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
int call(lua_State* L) {
|
int call(lua_State* L) {
|
||||||
return stack::call_into_lua(meta::tuple_types<return_type>(), args_types(), L, 1, fx);
|
return stack::call_into_lua(meta::tuple_types<return_type>(), args_lists(), L, 1, fx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int operator()(lua_State* L) override {
|
virtual int operator()(lua_State* L) override {
|
||||||
|
@ -103,7 +103,7 @@ template<typename T, typename Function>
|
||||||
struct member_variable : public base_function {
|
struct member_variable : public base_function {
|
||||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||||
typedef typename meta::bind_traits<function_type>::return_type return_type;
|
typedef typename meta::bind_traits<function_type>::return_type return_type;
|
||||||
typedef typename meta::bind_traits<function_type>::args_type args_types;
|
typedef typename meta::bind_traits<function_type>::args_list args_lists;
|
||||||
function_type var;
|
function_type var;
|
||||||
T member;
|
T member;
|
||||||
typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M;
|
typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M;
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct overload_traits : lua_bind_traits<T> {
|
||||||
|
|
||||||
template <typename T, typename Func, typename X>
|
template <typename T, typename Func, typename X>
|
||||||
struct overload_traits<functor<T, Func, X>> {
|
struct overload_traits<functor<T, Func, X>> {
|
||||||
typedef typename functor<T, Func, X>::args_type args_type;
|
typedef typename functor<T, Func, X>::args_list args_list;
|
||||||
typedef typename functor<T, Func, X>::return_type return_type;
|
typedef typename functor<T, Func, X>::return_type return_type;
|
||||||
static const std::size_t arity = functor<T, Func, X>::arity;
|
static const std::size_t arity = functor<T, Func, X>::arity;
|
||||||
static const std::size_t boost = static_cast<std::size_t>(functor<T, Func, X>::is_free);
|
static const std::size_t boost = static_cast<std::size_t>(functor<T, Func, X>::is_free);
|
||||||
|
@ -51,8 +51,8 @@ template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::s
|
||||||
inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int nfxarity, int start, Args&&... args) {
|
inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int nfxarity, int start, Args&&... args) {
|
||||||
typedef overload_traits<meta::unqualified_t<Fx>> traits;
|
typedef overload_traits<meta::unqualified_t<Fx>> traits;
|
||||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||||
typedef typename traits::args_type args_type;
|
typedef typename traits::args_list args_list;
|
||||||
typedef typename args_type::indices args_indices;
|
typedef typename args_list::indices args_indices;
|
||||||
int fxarity = traits::boost + nfxarity;
|
int fxarity = traits::boost + nfxarity;
|
||||||
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
// compile-time eliminate any functions that we know ahead of time are of improper arity
|
||||||
if (meta::find_in_pack_v<index_value<traits::arity>, index_value<M>...>::value) {
|
if (meta::find_in_pack_v<index_value<traits::arity>, index_value<M>...>::value) {
|
||||||
|
@ -61,10 +61,10 @@ inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>
|
||||||
if (traits::arity != fxarity) {
|
if (traits::arity != fxarity) {
|
||||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, nfxarity, start, std::forward<Args>(args)...);
|
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, nfxarity, start, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
if (!stack::stack_detail::check_types<true>().check(args_type(), args_indices(), L, start - traits::boost, no_panic)) {
|
if (!stack::stack_detail::check_types<true>().check(args_list(), args_indices(), L, start - traits::boost, no_panic)) {
|
||||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, nfxarity, start, std::forward<Args>(args)...);
|
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, nfxarity, start, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_type(), L, fxarity, start, std::forward<Args>(args)...);
|
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
} // internals
|
} // internals
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace function_detail {
|
||||||
template <typename F, F fx>
|
template <typename F, F fx>
|
||||||
inline int call_wrapper_variable(std::false_type, lua_State* L) {
|
inline int call_wrapper_variable(std::false_type, lua_State* L) {
|
||||||
typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
|
typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
|
||||||
typedef typename traits_type::args_type args_type;
|
typedef typename traits_type::args_list args_list;
|
||||||
typedef meta::tuple_types<typename traits_type::return_type> return_type;
|
typedef meta::tuple_types<typename traits_type::return_type> return_type;
|
||||||
return stack::call_into_lua(return_type(), args_type(), L, 1, fx);
|
return stack::call_into_lua(return_type(), args_list(), L, 1, fx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename R, typename V, V, typename T>
|
template <typename R, typename V, V, typename T>
|
||||||
|
@ -86,14 +86,14 @@ namespace function_detail {
|
||||||
inline int call_wrapper_function(std::true_type, lua_State* L) {
|
inline int call_wrapper_function(std::true_type, lua_State* L) {
|
||||||
typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
|
typedef meta::bind_traits<meta::unqualified_t<F>> traits_type;
|
||||||
typedef typename traits_type::object_type T;
|
typedef typename traits_type::object_type T;
|
||||||
typedef typename traits_type::args_type args_type;
|
typedef typename traits_type::args_list args_list;
|
||||||
typedef typename traits_type::return_type return_type;
|
typedef typename traits_type::return_type return_type;
|
||||||
typedef meta::tuple_types<return_type> return_type_list;
|
typedef meta::tuple_types<return_type> return_type_list;
|
||||||
auto mfx = [&](auto&&... args) -> typename traits_type::return_type {
|
auto mfx = [&](auto&&... args) -> typename traits_type::return_type {
|
||||||
auto& member = stack::get<T>(L, 1);
|
auto& member = stack::get<T>(L, 1);
|
||||||
return (member.*fx)(std::forward<decltype(args)>(args)...);
|
return (member.*fx)(std::forward<decltype(args)>(args)...);
|
||||||
};
|
};
|
||||||
int n = stack::call_into_lua<1>(return_type_list(), args_type(), L, 2, mfx);
|
int n = stack::call_into_lua<1>(return_type_list(), args_list(), L, 2, mfx);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct usertype_function_core : public base_function {
|
||||||
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
|
||||||
typedef functor<T, function_type> fx_t;
|
typedef functor<T, function_type> fx_t;
|
||||||
typedef typename fx_t::traits_type traits_type;
|
typedef typename fx_t::traits_type traits_type;
|
||||||
typedef typename fx_t::args_type args_type;
|
typedef typename fx_t::args_list args_list;
|
||||||
typedef typename fx_t::return_type return_type;
|
typedef typename fx_t::return_type return_type;
|
||||||
|
|
||||||
fx_t fx;
|
fx_t fx;
|
||||||
|
@ -53,7 +53,7 @@ struct usertype_function : public usertype_function_core<Tp, Function> {
|
||||||
typedef usertype_function_core<Tp, Function> base_t;
|
typedef usertype_function_core<Tp, Function> base_t;
|
||||||
typedef std::remove_pointer_t<Tp> T;
|
typedef std::remove_pointer_t<Tp> T;
|
||||||
typedef typename base_t::traits_type traits_type;
|
typedef typename base_t::traits_type traits_type;
|
||||||
typedef typename base_t::args_type args_type;
|
typedef typename base_t::args_list args_list;
|
||||||
typedef typename base_t::return_type return_type;
|
typedef typename base_t::return_type return_type;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
@ -66,7 +66,7 @@ struct usertype_function : public usertype_function_core<Tp, Function> {
|
||||||
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions)");
|
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions)");
|
||||||
}
|
}
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
return static_cast<base_t&>(*this)(meta::tuple_types<return_type>(), args_type(), index_value<2>(), L);
|
return static_cast<base_t&>(*this)(meta::tuple_types<return_type>(), args_list(), index_value<2>(), L);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int operator()(lua_State* L) override {
|
virtual int operator()(lua_State* L) override {
|
||||||
|
@ -80,7 +80,7 @@ struct usertype_variable_function : public usertype_function_core<Tp, Function>
|
||||||
typedef std::remove_pointer_t<Tp> T;
|
typedef std::remove_pointer_t<Tp> T;
|
||||||
typedef typename base_t::fx_t fx_t;
|
typedef typename base_t::fx_t fx_t;
|
||||||
typedef typename base_t::traits_type traits_type;
|
typedef typename base_t::traits_type traits_type;
|
||||||
typedef typename base_t::args_type args_type;
|
typedef typename base_t::args_list args_list;
|
||||||
typedef typename base_t::return_type return_type;
|
typedef typename base_t::return_type return_type;
|
||||||
typedef typename fx_t::can_read can_read;
|
typedef typename fx_t::can_read can_read;
|
||||||
typedef typename fx_t::can_write can_write;
|
typedef typename fx_t::can_write can_write;
|
||||||
|
@ -103,7 +103,7 @@ struct usertype_variable_function : public usertype_function_core<Tp, Function>
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_writable(std::true_type, lua_State* L) {
|
int set_writable(std::true_type, lua_State* L) {
|
||||||
return static_cast<base_t&>(*this)(meta::tuple_types<void>(), args_type(), index_value<3>(), L);
|
return static_cast<base_t&>(*this)(meta::tuple_types<void>(), args_list(), index_value<3>(), L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_variable(std::false_type, lua_State* L) {
|
int set_variable(std::false_type, lua_State* L) {
|
||||||
|
|
|
@ -111,7 +111,7 @@ struct inheritance {
|
||||||
return ti != typeid(Base) || type_check(types<Bases...>(), ti);
|
return ti != typeid(Base) || type_check(types<Bases...>(), ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check(const std::type_info& ti) {
|
static bool type_check(const std::type_info& ti) {
|
||||||
return ti != typeid(T) || type_check(types<Bases...>(), ti);
|
return ti != typeid(T) || type_check(types<Bases...>(), ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,14 +125,14 @@ struct inheritance {
|
||||||
return ti != typeid(Base) ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(dynamic_cast<Base*>(static_cast<T*>(data)));
|
return ti != typeid(Base) ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(dynamic_cast<Base*>(static_cast<T*>(data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* cast(void* voiddata, const std::type_info& ti) {
|
static void* type_cast(void* voiddata, const std::type_info& ti) {
|
||||||
T* data = static_cast<T*>(voiddata);
|
T* data = static_cast<T*>(voiddata);
|
||||||
return static_cast<void*>(ti != typeid(T) ? type_cast(types<Bases...>(), data, ti) : data);
|
return static_cast<void*>(ti != typeid(T) ? type_cast(types<Bases...>(), data, ti) : data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using inheritance_check_function = decltype(&inheritance<void>::check);
|
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
||||||
using inheritance_cast_function = decltype(&inheritance<void>::cast);
|
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
|
||||||
#else
|
#else
|
||||||
template <typename T, typename... Bases>
|
template <typename T, typename... Bases>
|
||||||
struct inheritance {
|
struct inheritance {
|
||||||
|
@ -145,7 +145,7 @@ struct inheritance {
|
||||||
return ti != id_for<Base>::value || type_check(types<Bases...>(), ti);
|
return ti != id_for<Base>::value || type_check(types<Bases...>(), ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check(std::size_t ti) {
|
static bool type_check(std::size_t ti) {
|
||||||
return ti != id_for<T>::value || type_check(types<Bases...>(), ti);
|
return ti != id_for<T>::value || type_check(types<Bases...>(), ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,14 +159,14 @@ struct inheritance {
|
||||||
return ti != id_for<Base>::value ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
|
return ti != id_for<Base>::value ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* cast(void* voiddata, std::size_t ti) {
|
static void* type_cast(void* voiddata, std::size_t ti) {
|
||||||
T* data = static_cast<T*>(voiddata);
|
T* data = static_cast<T*>(voiddata);
|
||||||
return static_cast<void*>(ti != id_for<T>::value ? type_cast(types<Bases...>(), data, ti) : data);
|
return static_cast<void*>(ti != id_for<T>::value ? type_cast(types<Bases...>(), data, ti) : data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using inheritance_check_function = decltype(&inheritance<void>::check);
|
using inheritance_check_function = decltype(&inheritance<void>::type_check);
|
||||||
using inheritance_cast_function = decltype(&inheritance<void>::cast);
|
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
|
||||||
#endif // No Exceptions and/or No Runtime Type Information
|
#endif // No Exceptions and/or No Runtime Type Information
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
85
sol/property.hpp
Normal file
85
sol/property.hpp
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// 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 SOL_PROPERTY_HPP
|
||||||
|
#define SOL_PROPERTY_HPP
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
struct no_prop { };
|
||||||
|
|
||||||
|
template <typename R, typename W>
|
||||||
|
struct property_wrapper {
|
||||||
|
typedef std::integral_constant<bool, !std::is_void<R>::value> can_read;
|
||||||
|
typedef std::integral_constant<bool, !std::is_void<W>::value> can_write;
|
||||||
|
typedef std::conditional_t<can_read::value, R, no_prop> Read;
|
||||||
|
typedef std::conditional_t<can_write::value, W, no_prop> Write;
|
||||||
|
Read read;
|
||||||
|
Write write;
|
||||||
|
|
||||||
|
template <typename Rx, typename Wx>
|
||||||
|
property_wrapper(Rx&& r, Wx&& w) : read(std::forward<Rx>(r)), write(std::forward<Wx>(w)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace property_detail {
|
||||||
|
template <typename R, typename W>
|
||||||
|
inline decltype(auto) property(std::true_type, R&& read, W&& write) {
|
||||||
|
return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write));
|
||||||
|
}
|
||||||
|
template <typename W, typename R>
|
||||||
|
inline decltype(auto) property(std::false_type, W&& write, R&& read) {
|
||||||
|
return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write));
|
||||||
|
}
|
||||||
|
template <typename R>
|
||||||
|
inline decltype(auto) property(std::true_type, R&& read) {
|
||||||
|
return property_wrapper<std::decay_t<R>, void>(std::forward<R>(read), no_prop());
|
||||||
|
}
|
||||||
|
template <typename W>
|
||||||
|
inline decltype(auto) property(std::false_type, W&& write) {
|
||||||
|
return property_wrapper<void, std::decay_t<W>>(no_prop(), std::forward<W>(write));
|
||||||
|
}
|
||||||
|
} // property_detail
|
||||||
|
|
||||||
|
template <typename F, typename G>
|
||||||
|
inline decltype(auto) property(F&& f, G&& g) {
|
||||||
|
using namespace sol;
|
||||||
|
typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
|
||||||
|
typedef lua_bind_traits<meta::unqualified_t<G>> right_traits;
|
||||||
|
return property_detail::property(meta::boolean<(left_traits::arity < right_traits::arity)>(), std::forward<F>(f), std::forward<G>(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
inline decltype(auto) property(F&& f) {
|
||||||
|
using namespace sol;
|
||||||
|
typedef lua_bind_traits<meta::unqualified_t<F>> left_traits;
|
||||||
|
return property_detail::property(meta::boolean<(left_traits::arity == 0)>(), std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow someone to make a member variable readonly (const)
|
||||||
|
template <typename R, typename T>
|
||||||
|
auto readonly(R T::* v) {
|
||||||
|
typedef const R C;
|
||||||
|
return static_cast<C T::*>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // sol
|
||||||
|
|
||||||
|
#endif // SOL_PROPERTY_HPP
|
|
@ -26,6 +26,7 @@
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
#include "protected_function_result.hpp"
|
#include "protected_function_result.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
template <typename base_t>
|
template <typename base_t>
|
||||||
|
@ -86,7 +87,7 @@ private:
|
||||||
|
|
||||||
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
|
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
|
||||||
int stacksize = lua_gettop(base_t::lua_state());
|
int stacksize = lua_gettop(base_t::lua_state());
|
||||||
int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
|
int firstreturn = (std::max)(1, stacksize - static_cast<int>(n) - 1);
|
||||||
int returncount = 0;
|
int returncount = 0;
|
||||||
call_status code = call_status::ok;
|
call_status code = call_status::ok;
|
||||||
#ifndef SOL_NO_EXCEPTIONS
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
|
|
|
@ -55,20 +55,20 @@ private:
|
||||||
return stack::get<T>(L, index);
|
return stack::get<T>(L, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::optional<sol::error> tagged_get( types<sol::optional<sol::error>> ) const {
|
optional<error> tagged_get( types<optional<error>> ) const {
|
||||||
if (valid()) {
|
if (valid()) {
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
return sol::error(detail::direct_error, stack::get<std::string>(L, index));
|
return error(detail::direct_error, stack::get<std::string>(L, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::error tagged_get( types<sol::error> ) const {
|
error tagged_get( types<error> ) const {
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
if (valid()) {
|
if (valid()) {
|
||||||
type_panic(L, index, type_of(L, index), type::none);
|
type_panic(L, index, type_of(L, index), type::none);
|
||||||
}
|
}
|
||||||
#endif // Check Argument Safety
|
#endif // Check Argument Safety
|
||||||
return sol::error(detail::direct_error, stack::get<std::string>(L, index));
|
return error(detail::direct_error, stack::get<std::string>(L, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -162,6 +162,14 @@ inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, i
|
||||||
return push_reference(L, std::forward<decltype(r)>(r));
|
return push_reference(L, std::forward<decltype(r)>(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<int additionalpop = 0, bool check_args = stack_detail::default_check_arguments, typename Fx, typename... FxArgs>
|
||||||
|
inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
|
||||||
|
typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type;
|
||||||
|
typedef typename traits_type::args_list args_list;
|
||||||
|
typedef typename traits_type::returns_list returns_list;
|
||||||
|
return call_into_lua(returns_list(), args_list(), start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...)
|
||||||
|
}
|
||||||
|
|
||||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
||||||
luaL_getmetatable(L, key.c_str());
|
luaL_getmetatable(L, key.c_str());
|
||||||
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
||||||
|
|
|
@ -164,6 +164,23 @@ struct checker<T, type::lightuserdata, C> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
struct checker<userdata_value, type::userdata, C> {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State* L, int index, Handler&& handler) {
|
||||||
|
type t = type_of(L, index);
|
||||||
|
bool success = t == type::userdata;
|
||||||
|
if (!success) {
|
||||||
|
// expected type, actual type
|
||||||
|
handler(L, index, type::userdata, t);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename C>
|
||||||
|
struct checker<user<T>, type::userdata, C> : checker<user<T>, type::lightuserdata, C> {};
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename T, typename C>
|
||||||
struct checker<non_null<T>, type::userdata, C> : checker<T, lua_type_of<T>::value, C> {};
|
struct checker<non_null<T>, type::userdata, C> : checker<T, lua_type_of<T>::value, C> {};
|
||||||
|
|
||||||
|
@ -235,77 +252,63 @@ struct checker<T*, type::userdata, C> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct checker<userdata_value, type::userdata, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler) {
|
|
||||||
type t = type_of(L, index);
|
|
||||||
bool success = t == type::userdata || t == type::lightuserdata;
|
|
||||||
if (!success) {
|
|
||||||
// expected type, actual type
|
|
||||||
handler(L, index, type::lightuserdata, t);
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename T, typename C>
|
||||||
struct checker<T, type::userdata, C> {
|
struct checker<T, type::userdata, C> {
|
||||||
template <typename U, typename Handler>
|
template <typename U, typename Handler>
|
||||||
static bool check (types<U>, lua_State* L, type indextype, int index, Handler&& handler) {
|
static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler) {
|
||||||
if (indextype != type::userdata) {
|
if (indextype != type::userdata) {
|
||||||
handler(L, index, type::userdata, indextype);
|
handler(L, index, type::userdata, indextype);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (meta::any<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
if (meta::any<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||||
return true;
|
return true;
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stack_detail::check_metatable<U>(L))
|
if (stack_detail::check_metatable<U>(L))
|
||||||
return true;
|
return true;
|
||||||
if (stack_detail::check_metatable<U*>(L))
|
if (stack_detail::check_metatable<U*>(L))
|
||||||
return true;
|
return true;
|
||||||
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
||||||
return true;
|
return true;
|
||||||
#ifndef SOL_NO_EXCEPTIONS
|
#ifndef SOL_NO_EXCEPTIONS
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||||
void* basecastdata = lua_touserdata(L, -1);
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||||
bool success = detail::catch_check<T>(basecast);
|
bool success = detail::catch_check<T>(basecast);
|
||||||
#elif !defined(SOL_NO_RTTI)
|
#elif !defined(SOL_NO_RTTI)
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||||
if (stack::get<type>(L) == type::nil) {
|
if (stack::get<type>(L) == type::nil) {
|
||||||
lua_pop(L, 2);
|
lua_pop(L, 2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void* basecastdata = lua_touserdata(L, -1);
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||||
bool success = ic(typeid(T));
|
bool success = ic(typeid(T));
|
||||||
#else
|
#else
|
||||||
// Topkek
|
// Topkek
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
||||||
if (stack::get<type>(L) == type::nil) {
|
if (stack::get<type>(L) == type::nil) {
|
||||||
lua_pop(L, 2);
|
lua_pop(L, 2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void* basecastdata = lua_touserdata(L, -1);
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||||
bool success = ic(detail::id_for<T>::value);
|
bool success = ic(detail::id_for<T>::value);
|
||||||
#endif // No Runtime Type Information || Exceptions
|
#endif // No Runtime Type Information || Exceptions
|
||||||
lua_pop(L, 2);
|
lua_pop(L, 2);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
handler(L, index, type::userdata, indextype);
|
handler(L, index, type::userdata, indextype);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check (lua_State* L, int index, Handler&& handler) {
|
static bool check(lua_State* L, int index, Handler&& handler) {
|
||||||
const type indextype = type_of(L, index);
|
const type indextype = type_of(L, index);
|
||||||
return check(types<T>(), L, indextype, index, std::forward<Handler>(handler));
|
return check(types<T>(), L, indextype, index, std::forward<Handler>(handler));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -52,30 +52,44 @@ struct check_getter<optional<T>> {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
|
struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static optional<T> get( lua_State* L, int index, Handler&& handler) {
|
static optional<T> get(lua_State* L, int index, Handler&& handler) {
|
||||||
int isnum = 0;
|
int isnum = 0;
|
||||||
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
||||||
if (isnum == 0) {
|
if (isnum == 0) {
|
||||||
handler(L, index, type::number, type_of(L, index));
|
handler(L, index, type::number, type_of(L, index));
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
return static_cast<T>(value);
|
return static_cast<T>(value);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check_getter<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||||
|
template <typename Handler>
|
||||||
|
static optional<T> get(lua_State* L, int index, Handler&& handler) {
|
||||||
|
int isnum = 0;
|
||||||
|
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
||||||
|
if (isnum == 0) {
|
||||||
|
handler(L, index, type::number, type_of(L, index));
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
return static_cast<T>(value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
struct check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static optional<T> get( lua_State* L, int index, Handler&& handler) {
|
static optional<T> get(lua_State* L, int index, Handler&& handler) {
|
||||||
int isnum = 0;
|
int isnum = 0;
|
||||||
lua_Number value = lua_tonumberx(L, index, &isnum);
|
lua_Number value = lua_tonumberx(L, index, &isnum);
|
||||||
if (isnum == 0) {
|
if (isnum == 0) {
|
||||||
handler(L, index, type::number, type_of(L, index));
|
handler(L, index, type::number, type_of(L, index));
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
return static_cast<T>(value);
|
return static_cast<T>(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -202,6 +202,14 @@ inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index = -
|
||||||
return stack_detail::unchecked_get<optional<T>>(L, index);
|
return stack_detail::unchecked_get<optional<T>>(L, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline int alloc_destroy(lua_State* L) {
|
||||||
|
void* rawdata = lua_touserdata(L, up_value_index(1));
|
||||||
|
T* data = static_cast<T*>(rawdata);
|
||||||
|
std::allocator<T> alloc;
|
||||||
|
alloc.destroy(data);
|
||||||
|
}
|
||||||
|
|
||||||
} // stack_detail
|
} // stack_detail
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -62,6 +62,13 @@ struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigne
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct getter<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||||
|
static T get(lua_State* L, int index = -1) {
|
||||||
|
return static_cast<T>(lua_tointegerx(L, index, nullptr));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> {
|
struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> {
|
||||||
static T get(lua_State* L, int index = -1) {
|
static T get(lua_State* L, int index = -1) {
|
||||||
|
@ -83,6 +90,27 @@ struct getter<light_userdata_value> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct getter<light<T>> {
|
||||||
|
static light<T> get(lua_State* L, int index = -1) {
|
||||||
|
return light<T>( static_cast<T*>(lua_touserdata(L, index)) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct getter<user<T>> {
|
||||||
|
static T& get(lua_State* L, int index = -1) {
|
||||||
|
return *static_cast<T*>(lua_touserdata(L, index));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct getter<user<T*>> {
|
||||||
|
static T* get(lua_State* L, int index = -1) {
|
||||||
|
return static_cast<T*>(lua_touserdata(L, index));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct getter<type> {
|
struct getter<type> {
|
||||||
static type get(lua_State *L, int index){
|
static type get(lua_State *L, int index){
|
||||||
|
@ -106,6 +134,15 @@ struct getter<std::string> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct getter<string_detail::string_shim> {
|
||||||
|
string_detail::string_shim get(lua_State* L, int index) {
|
||||||
|
size_t len;
|
||||||
|
const char* p = lua_tolstring(L, index, &len);
|
||||||
|
return string_detail::string_shim(p, len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct getter<const char*> {
|
struct getter<const char*> {
|
||||||
static const char* get(lua_State* L, int index = -1) {
|
static const char* get(lua_State* L, int index = -1) {
|
||||||
|
@ -113,6 +150,17 @@ struct getter<const char*> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct getter<meta_function> {
|
||||||
|
static meta_function get(lua_State *L, int index) {
|
||||||
|
const char* name = getter<const char*>{}.get(L, index);
|
||||||
|
for (std::size_t i = 0; i < meta_function_names.size(); ++i)
|
||||||
|
if (meta_function_names[i] == name)
|
||||||
|
return static_cast<meta_function>(i);
|
||||||
|
return meta_function::construct;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct getter<char> {
|
struct getter<char> {
|
||||||
static char get(lua_State* L, int index = -1) {
|
static char get(lua_State* L, int index = -1) {
|
||||||
|
@ -208,9 +256,9 @@ struct getter<lua_CFunction> {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct getter<c_closure> {
|
struct getter<c_closure> {
|
||||||
static c_closure get(lua_State* L, int index = -1) {
|
static c_closure get(lua_State* L, int index = -1) {
|
||||||
return c_closure(lua_tocfunction(L, index), -1);
|
return c_closure(lua_tocfunction(L, index), -1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -31,44 +31,54 @@ namespace sol {
|
||||||
namespace stack {
|
namespace stack {
|
||||||
template<typename T, typename>
|
template<typename T, typename>
|
||||||
struct pusher {
|
struct pusher {
|
||||||
template <typename... Args>
|
template <typename K, typename... Args>
|
||||||
static int push(lua_State* L, Args&&... args) {
|
static int push_keyed(lua_State* L, metatable_registry_key<K> k, Args&&... args) {
|
||||||
// Basically, we store all user-data like this:
|
// Basically, we store all user-data like this:
|
||||||
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
||||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||||
// do the actual object. Things that are std::ref or plain T* are stored as
|
// do the actual object. Things that are std::ref or plain T* are stored as
|
||||||
// just the sizeof(T*), and nothing else.
|
// just the sizeof(T*), and nothing else.
|
||||||
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||||
T*& referencereference = *pointerpointer;
|
T*& referencereference = *pointerpointer;
|
||||||
T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
|
T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
|
||||||
referencereference = allocationtarget;
|
referencereference = allocationtarget;
|
||||||
std::allocator<T> alloc{};
|
std::allocator<T> alloc{};
|
||||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
||||||
luaL_newmetatable(L, &usertype_traits<T>::metatable[0]);
|
luaL_newmetatable(L, &k.key[0]);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <typename... Args>
|
||||||
struct pusher<detail::as_reference_tag> {
|
static int push(lua_State* L, Args&&... args) {
|
||||||
template <typename T>
|
return push_keyed(L, meta_registry_key(&usertype_traits<T*>::metatable[0]), std::forward<Args>(args)...);
|
||||||
static int push(lua_State* L, T&& obj) {
|
}
|
||||||
return stack::push(L, detail::ptr(obj));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T*> {
|
struct pusher<T*> {
|
||||||
static int push(lua_State* L, T* obj) {
|
template <typename K>
|
||||||
if (obj == nullptr)
|
static int push_keyed(lua_State* L, metatable_registry_key<K> k, T* obj) {
|
||||||
return stack::push(L, nil);
|
if (obj == nullptr)
|
||||||
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
return stack::push(L, nil);
|
||||||
*pref = obj;
|
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
||||||
luaL_getmetatable(L, &usertype_traits<T*>::metatable[0]);
|
*pref = obj;
|
||||||
lua_setmetatable(L, -2);
|
luaL_getmetatable(L, &k.key[0]);
|
||||||
return 1;
|
lua_setmetatable(L, -2);
|
||||||
}
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, T* obj) {
|
||||||
|
return push_keyed(L, meta_registry_key(&usertype_traits<T*>::metatable[0]), obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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>
|
template<typename T>
|
||||||
|
@ -127,6 +137,16 @@ struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||||
|
static int push(lua_State* L, const T& value) {
|
||||||
|
if (std::is_same<char, T>::value) {
|
||||||
|
return stack::push(L, static_cast<int>(value));
|
||||||
|
}
|
||||||
|
return stack::push(L, static_cast<std::underlying_type_t<T>>(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> {
|
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> {
|
||||||
static int push(lua_State* L, const T& value) {
|
static int push(lua_State* L, const T& value) {
|
||||||
|
@ -136,7 +156,7 @@ struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigne
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::has_key_value_pair<T>>, meta::neg<std::is_base_of<reference, T>>>::value>> {
|
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::has_key_value_pair<T>>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
||||||
static int push(lua_State* L, const T& cont) {
|
static int push(lua_State* L, const T& cont) {
|
||||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||||
int tableindex = lua_gettop(L);
|
int tableindex = lua_gettop(L);
|
||||||
|
@ -149,7 +169,7 @@ struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<me
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::neg<std::is_base_of<reference, T>>>::value>> {
|
struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> {
|
||||||
static int push(lua_State* L, const T& cont) {
|
static int push(lua_State* L, const T& cont) {
|
||||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||||
int tableindex = lua_gettop(L);
|
int tableindex = lua_gettop(L);
|
||||||
|
@ -213,12 +233,26 @@ struct pusher<lua_CFunction> {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct pusher<c_closure> {
|
struct pusher<c_closure> {
|
||||||
static int push(lua_State* L, c_closure closure) {
|
static int push(lua_State* L, c_closure cc) {
|
||||||
lua_pushcclosure(L, closure.c_function, closure.upvalues);
|
lua_pushcclosure(L, cc.c_function, cc.upvalues);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Arg, typename... Args>
|
||||||
|
struct pusher<closure<Arg, Args...>> {
|
||||||
|
template <std::size_t... I, typename T>
|
||||||
|
static int push(std::index_sequence<I...>, lua_State* L, T&& c) {
|
||||||
|
int pushcount = multi_push(L, detail::forward_get<I>(c.upvalues)...);
|
||||||
|
return stack::push(L, c_closure(c.c_function, pushcount));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static int push(lua_State* L, T&& c) {
|
||||||
|
return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct pusher<void*> {
|
struct pusher<void*> {
|
||||||
static int push(lua_State* L, void* userdata) {
|
static int push(lua_State* L, void* userdata) {
|
||||||
|
@ -235,6 +269,31 @@ struct pusher<light_userdata_value> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<light<T>> {
|
||||||
|
static int push(lua_State* L, light<T> l) {
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(l.value));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pusher<user<T>> {
|
||||||
|
template <typename... Args>
|
||||||
|
static int push(lua_State* L, Args&&... args ) {
|
||||||
|
// A dumb pusher
|
||||||
|
void* rawdata = lua_newuserdata(L, sizeof(T));
|
||||||
|
std::allocator<T> alloc;
|
||||||
|
alloc.construct(static_cast<T*>(rawdata), std::forward<Args>(args)...);
|
||||||
|
lua_CFunction cdel = stack_detail::alloc_destroy<T>;
|
||||||
|
// Make sure we have a plain GC set for this data
|
||||||
|
lua_pushlightuserdata(L, rawdata);
|
||||||
|
lua_pushcclosure(L, cdel, 1);
|
||||||
|
lua_setfield(L, -2, "__gc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct pusher<userdata_value> {
|
struct pusher<userdata_value> {
|
||||||
static int push(lua_State* L, userdata_value data) {
|
static int push(lua_State* L, userdata_value data) {
|
||||||
|
@ -276,6 +335,15 @@ struct pusher<std::string> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct pusher<meta_function> {
|
||||||
|
static int push(lua_State* L, meta_function m) {
|
||||||
|
const std::string& str = name_of(m);
|
||||||
|
lua_pushlstring(L, str.c_str(), str.size());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
48
sol/string_shim.hpp
Normal file
48
sol/string_shim.hpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
namespace string_detail {
|
||||||
|
struct string_shim {
|
||||||
|
std::size_t s;
|
||||||
|
const char* p;
|
||||||
|
|
||||||
|
string_shim(std::string& r) : string_shim(r.data(), r.size()) {}
|
||||||
|
string_shim(const char* p) : string_shim(p, std::char_traits<char>::length(p)) {}
|
||||||
|
string_shim(const char* p, std::size_t s) : s(s), p(p) {}
|
||||||
|
|
||||||
|
static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) {
|
||||||
|
int result = std::char_traits<char>::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz);
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
if (lhs_sz < rhs_sz)
|
||||||
|
return -1;
|
||||||
|
if (lhs_sz > rhs_sz)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* data() const {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const string_shim& r) const {
|
||||||
|
return compare(p, s, r.data(), r.size()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const char* r) const {
|
||||||
|
return compare(r, std::char_traits<char>::length(r), p, s) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const std::string& r) const {
|
||||||
|
return compare(r.data(), r.size(), p, s) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
159
sol/traits.hpp
159
sol/traits.hpp
|
@ -23,6 +23,7 @@
|
||||||
#define SOL_TRAITS_HPP
|
#define SOL_TRAITS_HPP
|
||||||
|
|
||||||
#include "tuple.hpp"
|
#include "tuple.hpp"
|
||||||
|
#include "bind_traits.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -54,6 +55,9 @@ struct unwrapped<std::reference_wrapper<T>> {
|
||||||
typedef T type;
|
typedef T type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using unwrapped_t = typename unwrapped<T>::type;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct remove_member_pointer;
|
struct remove_member_pointer;
|
||||||
|
|
||||||
|
@ -117,21 +121,6 @@ using enable = std::enable_if_t<all<Args...>::value, enable_t>;
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>;
|
using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
using unqualified_t = typename unqualified<T>::type;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
using unwrapped_t = typename unwrapped<T>::type;
|
|
||||||
|
|
||||||
template <std::size_t N, typename Tuple>
|
|
||||||
using tuple_element = std::tuple_element<N, unqualified_t<Tuple>>;
|
|
||||||
|
|
||||||
template <std::size_t N, typename Tuple>
|
|
||||||
using tuple_element_t = std::tuple_element_t<N, unqualified_t<Tuple>>;
|
|
||||||
|
|
||||||
template<typename V, typename... Vs>
|
template<typename V, typename... Vs>
|
||||||
struct find_in_pack_v : boolean<false> { };
|
struct find_in_pack_v : boolean<false> { };
|
||||||
|
|
||||||
|
@ -252,151 +241,11 @@ struct is_callable<T, true> {
|
||||||
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class F>
|
|
||||||
struct check_deducible_signature {
|
|
||||||
struct nat {};
|
|
||||||
template<class G>
|
|
||||||
static auto test(int) -> decltype(&G::operator(), void());
|
|
||||||
template<class>
|
|
||||||
static auto test(...) -> nat;
|
|
||||||
|
|
||||||
using type = std::is_void<decltype(test<F>(0))>;
|
|
||||||
};
|
|
||||||
} // meta_detail
|
} // meta_detail
|
||||||
|
|
||||||
template<class F>
|
|
||||||
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_callable : boolean<meta_detail::is_callable<T>::value> {};
|
struct is_callable : boolean<meta_detail::is_callable<T>::value> {};
|
||||||
|
|
||||||
namespace meta_detail {
|
|
||||||
|
|
||||||
template <std::size_t I, typename T>
|
|
||||||
struct void_tuple_element : meta::tuple_element<I, T> {};
|
|
||||||
|
|
||||||
template <std::size_t I>
|
|
||||||
struct void_tuple_element<I, std::tuple<>> { typedef void type; };
|
|
||||||
|
|
||||||
template <std::size_t I, typename T>
|
|
||||||
using void_tuple_element_t = typename void_tuple_element<I, T>::type;
|
|
||||||
|
|
||||||
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
|
||||||
struct fx_traits {
|
|
||||||
static const bool is_member_function = false;
|
|
||||||
static const std::size_t arity = 0;
|
|
||||||
typedef types<> args_type;
|
|
||||||
typedef std::tuple<> args_tuple_type;
|
|
||||||
typedef void object_type;
|
|
||||||
typedef void function_pointer_type;
|
|
||||||
typedef void function_type;
|
|
||||||
typedef void free_function_pointer_type;
|
|
||||||
typedef void signature_type;
|
|
||||||
typedef void return_type;
|
|
||||||
template<std::size_t i>
|
|
||||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Signature>
|
|
||||||
struct fx_traits<Signature, true> : fx_traits<decltype(&Signature::operator()), false> {};
|
|
||||||
|
|
||||||
template<typename T, typename R, typename... Args>
|
|
||||||
struct fx_traits<R(T::*)(Args...), false> {
|
|
||||||
static const std::size_t arity = sizeof...(Args);
|
|
||||||
static const bool is_member_function = true;
|
|
||||||
typedef T object_type;
|
|
||||||
typedef std::tuple<Args...> args_tuple_type;
|
|
||||||
typedef types<Args...> args_type;
|
|
||||||
typedef R(T::* function_pointer_type)(Args...);
|
|
||||||
typedef std::remove_pointer_t<function_pointer_type> function_type;
|
|
||||||
typedef R(*free_function_pointer_type)(Args...);
|
|
||||||
typedef R return_type;
|
|
||||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
|
||||||
template<std::size_t i>
|
|
||||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename R, typename... Args>
|
|
||||||
struct fx_traits<R(T::*)(Args...) const, false> {
|
|
||||||
static const std::size_t arity = sizeof...(Args);
|
|
||||||
static const bool is_member_function = true;
|
|
||||||
typedef T object_type;
|
|
||||||
typedef std::tuple<Args...> args_tuple_type;
|
|
||||||
typedef types<Args...> args_type;
|
|
||||||
typedef R(T::* function_pointer_type)(Args...);
|
|
||||||
typedef std::remove_pointer_t<function_pointer_type> function_type;
|
|
||||||
typedef R(*free_function_pointer_type)(Args...);
|
|
||||||
typedef R return_type;
|
|
||||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
|
||||||
template<std::size_t i>
|
|
||||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename... Args>
|
|
||||||
struct fx_traits<R(Args...), false> {
|
|
||||||
static const std::size_t arity = sizeof...(Args);
|
|
||||||
static const bool is_member_function = false;
|
|
||||||
typedef std::tuple<Args...> args_tuple_type;
|
|
||||||
typedef types<Args...> args_type;
|
|
||||||
typedef R(function_type)(Args...);
|
|
||||||
typedef R(*function_pointer_type)(Args...);
|
|
||||||
typedef R(*free_function_pointer_type)(Args...);
|
|
||||||
typedef R return_type;
|
|
||||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
|
||||||
template<std::size_t i>
|
|
||||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename... Args>
|
|
||||||
struct fx_traits<R(*)(Args...), false> {
|
|
||||||
static const std::size_t arity = sizeof...(Args);
|
|
||||||
static const bool is_member_function = false;
|
|
||||||
typedef std::tuple<Args...> args_tuple_type;
|
|
||||||
typedef types<Args...> args_type;
|
|
||||||
typedef R(function_type)(Args...);
|
|
||||||
typedef R(*function_pointer_type)(Args...);
|
|
||||||
typedef R(*free_function_pointer_type)(Args...);
|
|
||||||
typedef R return_type;
|
|
||||||
typedef std::remove_pointer_t<free_function_pointer_type> signature_type;
|
|
||||||
template<std::size_t i>
|
|
||||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
|
||||||
struct callable_traits : fx_traits<std::decay_t<Signature>> {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R, typename T>
|
|
||||||
struct callable_traits<R(T::*), true> {
|
|
||||||
typedef R Arg;
|
|
||||||
typedef T object_type;
|
|
||||||
using signature_type = R(T::*);
|
|
||||||
static const bool is_member_function = false;
|
|
||||||
static const std::size_t arity = 1;
|
|
||||||
typedef std::tuple<Arg> args_tuple_type;
|
|
||||||
typedef types<Arg> args_type;
|
|
||||||
typedef R return_type;
|
|
||||||
typedef R(function_type)(Arg);
|
|
||||||
typedef R(*function_pointer_type)(Arg);
|
|
||||||
typedef R(*free_function_pointer_type)(Arg);
|
|
||||||
template<std::size_t i>
|
|
||||||
using arg_at = void_tuple_element_t<i, args_tuple_type>;
|
|
||||||
};
|
|
||||||
} // meta_detail
|
|
||||||
|
|
||||||
template<typename Signature>
|
|
||||||
struct bind_traits : meta_detail::callable_traits<std::remove_volatile_t<Signature>> {};
|
|
||||||
|
|
||||||
template<typename Signature>
|
|
||||||
using function_args_t = typename bind_traits<Signature>::args_type;
|
|
||||||
|
|
||||||
template<typename Signature>
|
|
||||||
using function_signature_t = typename bind_traits<Signature>::signature_type;
|
|
||||||
|
|
||||||
template<typename Signature>
|
|
||||||
using function_return_t = typename bind_traits<Signature>::return_type;
|
|
||||||
|
|
||||||
struct has_begin_end_impl {
|
struct has_begin_end_impl {
|
||||||
template<typename T, typename U = unqualified_t<T>,
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
typename B = decltype(std::declval<U&>().begin()),
|
typename B = decltype(std::declval<U&>().begin()),
|
||||||
|
|
|
@ -41,6 +41,12 @@ template<typename... Args>
|
||||||
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
|
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using unqualified_t = typename unqualified<T>::type;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
using tuple_types = typename detail::tuple_types_<Args...>::type;
|
using tuple_types = typename detail::tuple_types_<Args...>::type;
|
||||||
|
|
||||||
|
@ -50,8 +56,18 @@ struct pop_front_type;
|
||||||
template<typename Arg>
|
template<typename Arg>
|
||||||
using pop_front_type_t = typename pop_front_type<Arg>::type;
|
using pop_front_type_t = typename pop_front_type<Arg>::type;
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
struct pop_front_type<types<Args...>> { typedef void front_type; typedef types<Args...> type; };
|
||||||
|
|
||||||
template<typename Arg, typename... Args>
|
template<typename Arg, typename... Args>
|
||||||
struct pop_front_type<types<Arg, Args...>> { typedef types<Args...> type; };
|
struct pop_front_type<types<Arg, Args...>> { typedef Arg front_type; typedef types<Args...> type; };
|
||||||
|
|
||||||
|
template <std::size_t N, typename Tuple>
|
||||||
|
using tuple_element = std::tuple_element<N, unqualified_t<Tuple>>;
|
||||||
|
|
||||||
|
template <std::size_t N, typename Tuple>
|
||||||
|
using tuple_element_t = std::tuple_element_t<N, unqualified_t<Tuple>>;
|
||||||
|
|
||||||
} // meta
|
} // meta
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
|
|
101
sol/types.hpp
101
sol/types.hpp
|
@ -22,9 +22,10 @@
|
||||||
#ifndef SOL_TYPES_HPP
|
#ifndef SOL_TYPES_HPP
|
||||||
#define SOL_TYPES_HPP
|
#define SOL_TYPES_HPP
|
||||||
|
|
||||||
|
#include "optional.hpp"
|
||||||
#include "compatibility.hpp"
|
#include "compatibility.hpp"
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include "optional.hpp"
|
#include "string_shim.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -83,8 +84,6 @@ inline int c_trampoline(lua_State* L, lua_CFunction f) {
|
||||||
return trampoline(L, f);
|
return trampoline(L, f);
|
||||||
}
|
}
|
||||||
#endif // Exceptions vs. No Exceptions
|
#endif // Exceptions vs. No Exceptions
|
||||||
struct empty { void operator()() {} };
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unique_usertype {};
|
struct unique_usertype {};
|
||||||
} // detail
|
} // detail
|
||||||
|
@ -174,12 +173,72 @@ struct userdata_value {
|
||||||
operator void*() const { return value; }
|
operator void*() const { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct c_closure {
|
template <typename L>
|
||||||
lua_CFunction c_function;
|
struct light {
|
||||||
int upvalues;
|
L* value;
|
||||||
c_closure(lua_CFunction f, int upvalues = 0) : c_function(f), upvalues(upvalues) {}
|
|
||||||
|
light(L& x) : value(std::addressof(x)) {}
|
||||||
|
light(L* x) : value(x) {}
|
||||||
|
light(void* x) : value(static_cast<L*>(x)) {}
|
||||||
|
operator L* () const { return value; }
|
||||||
|
operator L& () const { return *value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto make_light(T& l) {
|
||||||
|
typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L;
|
||||||
|
return light<L>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
struct user {
|
||||||
|
U value;
|
||||||
|
|
||||||
|
user(U x) : value(std::forward<U>(x)) {}
|
||||||
|
operator U* () const { return std::addressof(value); }
|
||||||
|
operator U& () const { return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto make_user(T&& u) {
|
||||||
|
typedef meta::unwrapped_t<meta::unqualified_t<T>> U;
|
||||||
|
return user<U>(std::forward<T>(u));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct metatable_registry_key {
|
||||||
|
T key;
|
||||||
|
|
||||||
|
metatable_registry_key(T key) : key(std::forward<T>(key)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto meta_registry_key(T&& key) {
|
||||||
|
typedef meta::unqualified_t<T> K;
|
||||||
|
return metatable_registry_key<K>(std::forward<T>(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Upvalues>
|
||||||
|
struct closure {
|
||||||
|
lua_CFunction c_function;
|
||||||
|
std::tuple<Upvalues...> upvalues;
|
||||||
|
closure(lua_CFunction f, Upvalues... upvalues) : c_function(f), upvalues(std::forward<Upvalues>(upvalues)...) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct closure<> {
|
||||||
|
lua_CFunction c_function;
|
||||||
|
int upvalues;
|
||||||
|
closure(lua_CFunction f, int upvalues = 0) : c_function(f), upvalues(upvalues) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef closure<> c_closure;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
closure<Args...> make_closure(lua_CFunction f, Args&&... args) {
|
||||||
|
return closure<Args...>(f, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
struct this_state {
|
struct this_state {
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
operator lua_State* () const {
|
operator lua_State* () const {
|
||||||
|
@ -262,6 +321,8 @@ enum class meta_function {
|
||||||
call_function = call,
|
call_function = call,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef meta_function meta_method;
|
||||||
|
|
||||||
const std::array<std::string, 2> meta_variable_names = { {
|
const std::array<std::string, 2> meta_variable_names = { {
|
||||||
"__index",
|
"__index",
|
||||||
"__newindex",
|
"__newindex",
|
||||||
|
@ -320,7 +381,7 @@ inline void type_error(lua_State* L, type expected, type actual) {
|
||||||
|
|
||||||
inline void type_assert(lua_State* L, int index, type expected, type actual) {
|
inline void type_assert(lua_State* L, int index, type expected, type actual) {
|
||||||
if (expected != type::poly && expected != actual) {
|
if (expected != type::poly && expected != actual) {
|
||||||
type_panic(L, index, expected, actual);
|
type_panic(L, index, expected, actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +434,7 @@ class thread;
|
||||||
struct variadic_args;
|
struct variadic_args;
|
||||||
struct this_state;
|
struct this_state;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct lua_type_of : std::integral_constant<type, type::userdata> {};
|
struct lua_type_of : std::integral_constant<type, type::userdata> {};
|
||||||
|
|
||||||
|
@ -421,6 +483,9 @@ struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string>
|
||||||
template <>
|
template <>
|
||||||
struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> {};
|
struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct lua_type_of<string_detail::string_shim> : std::integral_constant<type, type::string> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct lua_type_of<bool> : std::integral_constant<type, type::boolean> {};
|
struct lua_type_of<bool> : std::integral_constant<type, type::boolean> {};
|
||||||
|
|
||||||
|
@ -457,6 +522,12 @@ struct lua_type_of<light_userdata_value> : std::integral_constant<type, type::li
|
||||||
template <>
|
template <>
|
||||||
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> {};
|
||||||
|
|
||||||
template <typename Base>
|
template <typename Base>
|
||||||
struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {};
|
struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {};
|
||||||
|
|
||||||
|
@ -499,8 +570,15 @@ struct lua_type_of<T, std::enable_if_t<std::is_arithmetic<T>::value>> : std::int
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {};
|
struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct lua_type_of<sol::meta_function> : std::integral_constant<type, type::string> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct lua_type_of<this_state> : std::integral_constant<type, type::none> {};
|
struct lua_type_of<this_state> : std::integral_constant<type, type::none> {};
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct lua_type_of : detail::lua_type_of<T> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_primitive : std::integral_constant<bool,
|
struct is_lua_primitive : std::integral_constant<bool,
|
||||||
|
@ -544,7 +622,10 @@ struct lua_bind_traits : meta::bind_traits<Signature> {
|
||||||
private:
|
private:
|
||||||
typedef meta::bind_traits<Signature> base_t;
|
typedef meta::bind_traits<Signature> base_t;
|
||||||
public:
|
public:
|
||||||
static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_type>::value;
|
static const std::size_t true_arity = base_t::arity;
|
||||||
|
static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
|
||||||
|
static const std::size_t true_free_arity = base_t::free_arity;
|
||||||
|
static const std::size_t free_arity = base_t::free_arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -555,7 +636,7 @@ struct is_table<basic_table_core<x, T>> : std::true_type {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline type type_of() {
|
inline type type_of() {
|
||||||
return lua_type_of<meta::unqualified_t<T>>::value;
|
return lua_type_of<meta::unqualified_t<T>>::value;
|
||||||
}
|
}
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "inheritance.hpp"
|
#include "inheritance.hpp"
|
||||||
#include "raii.hpp"
|
#include "raii.hpp"
|
||||||
#include "deprecate.hpp"
|
#include "deprecate.hpp"
|
||||||
|
#include "usertype_metatable.hpp"
|
||||||
|
#include "stack.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -422,13 +424,13 @@ private:
|
||||||
#elif !defined(SOL_NO_RTTI)
|
#elif !defined(SOL_NO_RTTI)
|
||||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::check;
|
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
|
||||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::cast;
|
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
|
||||||
#else
|
#else
|
||||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::check;
|
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
|
||||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::cast;
|
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
|
||||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
187
sol/usertype_metatable.hpp
Normal file
187
sol/usertype_metatable.hpp
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// 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 SOL_USERTYPE_METATABLE_HPP
|
||||||
|
#define SOL_USERTYPE_METATABLE_HPP
|
||||||
|
|
||||||
|
#include "wrapper.hpp"
|
||||||
|
#include "call.hpp"
|
||||||
|
#include "stack.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
namespace usertype_detail {
|
||||||
|
inline bool is_index(string_detail::string_shim s) {
|
||||||
|
return s == name_of(meta_function::index) || s == name_of(meta_function::new_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_index(meta_function mf) {
|
||||||
|
return mf == meta_function::index || mf == meta_function::new_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Tuple>
|
||||||
|
struct usertype_metatable {
|
||||||
|
typedef std::make_index_sequence<std::tuple_size<Tuple>::value> indices;
|
||||||
|
typedef std::make_index_sequence<std::tuple_size<Tuple>::value / 2> half_indices;
|
||||||
|
template <std::size_t I>
|
||||||
|
struct check_binding : is_variable_binding<std::tuple_element_t<I, Tuple>> {};
|
||||||
|
Tuple functions;
|
||||||
|
bool must_index;
|
||||||
|
|
||||||
|
template <std::size_t... I>
|
||||||
|
static bool contains_variable(std::index_sequence<I...>) {
|
||||||
|
typedef meta::any<check_binding<(I * 2 + 1)>...> has_variables;
|
||||||
|
return has_variables::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t... I>
|
||||||
|
bool contains_index(std::index_sequence<I...>) const {
|
||||||
|
bool idx = false;
|
||||||
|
detail::swallow{ 0, ((idx &= usertype_detail::is_index(std::get<I * 2>(functions))), 0) ... };
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
usertype_metatable(Tuple t) : functions(std::move(t)), must_index(contains_variable(half_indices()) || contains_index(half_indices())) {}
|
||||||
|
|
||||||
|
template <bool is_index>
|
||||||
|
int find_call(std::integral_constant<bool, is_index>, std::index_sequence<>, lua_State* L, const sol::string_detail::string_shim& accessor) {
|
||||||
|
return luaL_error(L, "sol: attempt to index nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_index, std::size_t I0, std::size_t I1, std::size_t... In>
|
||||||
|
int find_call(std::integral_constant<bool, is_index> idx, std::index_sequence<I0, I1, In...>, lua_State* L, const sol::string_detail::string_shim& accessor) {
|
||||||
|
string_detail::string_shim name(std::get<I0>(functions));
|
||||||
|
if (accessor == name) {
|
||||||
|
if (is_variable_binding<decltype(std::get<I1>(functions))>::value) {
|
||||||
|
return call_with<I1, is_index, true>(L, *this);
|
||||||
|
}
|
||||||
|
return stack::push(L, c_closure(call<I1, is_index>, stack::push(L, light<usertype_metatable>(*this))));
|
||||||
|
}
|
||||||
|
return find_call(idx, std::index_sequence<In...>(), L, accessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, bool is_index = true, bool is_variable = false>
|
||||||
|
static int call(lua_State* L) {
|
||||||
|
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||||
|
return call_with<I, is_index, is_variable>(L, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, bool is_index = true, bool is_variable = false>
|
||||||
|
static int call_with(lua_State* L, usertype_metatable& um) {
|
||||||
|
auto& f = call_detail::pick(std::integral_constant<bool, is_index>(), std::get<I>(um.functions));
|
||||||
|
return call_detail::call_wrapped<T, is_index, is_variable>(L, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int index_call(lua_State* L) {
|
||||||
|
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||||
|
string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, -1);
|
||||||
|
return f.find_call(std::true_type(), std::make_index_sequence<std::tuple_size<Tuple>::value>(), L, accessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int new_index_call(lua_State* L) {
|
||||||
|
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||||
|
string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, -2);
|
||||||
|
return f.find_call(std::false_type(), std::make_index_sequence<std::tuple_size<Tuple>::value>(), L, accessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gc_call(lua_State* L) {
|
||||||
|
stack_object o(L, 1);
|
||||||
|
type x = o.get_type();
|
||||||
|
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, up_value_index(1));
|
||||||
|
f.~usertype_metatable();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace stack {
|
||||||
|
|
||||||
|
template <typename T, typename Tuple>
|
||||||
|
struct pusher<usertype_metatable<T, Tuple>> {
|
||||||
|
typedef usertype_metatable<T, Tuple> umt_t;
|
||||||
|
|
||||||
|
static void cleanup(lua_State* L, int metaidx, usertype_metatable<T, Tuple>&& um) {
|
||||||
|
const char* metakey = &usertype_traits<T>::gc_table[0];
|
||||||
|
lua_createtable(L, 1, 0);
|
||||||
|
stack_table t(L, -1);
|
||||||
|
t[meta_function::garbage_collect] = umt_t::gc_call;
|
||||||
|
stack::set_field(L, metakey, t, metaidx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t... I>
|
||||||
|
static int push(std::index_sequence<I...>, lua_State* L, usertype_metatable<T, Tuple>&& um) {
|
||||||
|
// Basic index pushing: specialize
|
||||||
|
// index and newindex to give variables and stuff
|
||||||
|
// make sure to return final T metatable table
|
||||||
|
const bool mustindex = um.must_index;
|
||||||
|
for (std::size_t i = 0; i < 3; ++i) {
|
||||||
|
// Pointer types, AKA "references" from C++
|
||||||
|
const char* metakey = nullptr;
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
metakey = &usertype_traits<T*>::metatable[0];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
metakey = &usertype_traits<T>::metatable[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
luaL_newmetatable(L, metakey);
|
||||||
|
stack_table t(L, -1);
|
||||||
|
stack::push(L, make_light(um));
|
||||||
|
luaL_Reg l[] = {
|
||||||
|
{ &std::get<I * 2>(um.functions)[0], umt_t::call<(I * 2) + 1> }...,
|
||||||
|
{ nullptr, nullptr }
|
||||||
|
};
|
||||||
|
luaL_setfuncs(L, l, 1);
|
||||||
|
|
||||||
|
if (mustindex) {
|
||||||
|
t[meta_function::index] = make_closure(umt_t::index_call, make_light(um));
|
||||||
|
t[meta_function::new_index] = make_closure(umt_t::new_index_call, make_light(um));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t[meta_function::index] = t;
|
||||||
|
}
|
||||||
|
if (i < 2) {
|
||||||
|
// We want to just leave the table
|
||||||
|
// in the registry only, otherwise we return it
|
||||||
|
t.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int metaidx = lua_gettop(L);
|
||||||
|
cleanup(L, metaidx, std::move(um));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, usertype_metatable<T, Tuple>&& um) {
|
||||||
|
return push(std::make_index_sequence<std::tuple_size<Tuple>::value / 2>(), L, std::move(um));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // stack
|
||||||
|
|
||||||
|
} // sol
|
||||||
|
|
||||||
|
#endif // SOL_USERTYPE_METATABLE_HPP
|
|
@ -41,7 +41,7 @@ namespace sol {
|
||||||
int stacktop;
|
int stacktop;
|
||||||
stack_proxy sp;
|
stack_proxy sp;
|
||||||
|
|
||||||
va_iterator() : L(nullptr), index(std::numeric_limits<int>::max()), stacktop(std::numeric_limits<int>::max()) {}
|
va_iterator() : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()) {}
|
||||||
va_iterator(lua_State* L, int index, int stacktop) : L(L), index(index), stacktop(stacktop), sp(L, index) {}
|
va_iterator(lua_State* L, int index, int stacktop) : L(L), index(index), stacktop(stacktop), sp(L, index) {}
|
||||||
|
|
||||||
reference operator*() {
|
reference operator*() {
|
||||||
|
@ -100,10 +100,10 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const va_iterator& r) const {
|
bool operator==(const va_iterator& r) const {
|
||||||
if (stacktop == std::numeric_limits<int>::max()) {
|
if (stacktop == (std::numeric_limits<int>::max)()) {
|
||||||
return r.index == r.stacktop;
|
return r.index == r.stacktop;
|
||||||
}
|
}
|
||||||
else if (r.stacktop == std::numeric_limits<int>::max()) {
|
else if (r.stacktop == (std::numeric_limits<int>::max)()) {
|
||||||
return index == stacktop;
|
return index == stacktop;
|
||||||
}
|
}
|
||||||
return index == r.index;
|
return index == r.index;
|
||||||
|
|
209
sol/wrapper.hpp
Normal file
209
sol/wrapper.hpp
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// 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 SOL_WRAPPER_HPP
|
||||||
|
#define SOL_WRAPPER_HPP
|
||||||
|
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
template <typename F, typename = void>
|
||||||
|
struct wrapper {
|
||||||
|
typedef lua_bind_traits<F> traits_type;
|
||||||
|
typedef typename traits_type::args_list args_list;
|
||||||
|
typedef typename traits_type::args_list free_args_list;
|
||||||
|
typedef typename traits_type::returns_list returns_list;
|
||||||
|
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
static decltype(auto) call(Fx&& fx, Args&&... args) {
|
||||||
|
return fx(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct caller {
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
decltype(auto) operator()(Fx&& fx, Args&&... args) const {
|
||||||
|
return call(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct wrapper<F, std::enable_if_t<std::is_function<meta::unqualified_t<std::remove_pointer_t<F>>>::value>> {
|
||||||
|
typedef lua_bind_traits<F> traits_type;
|
||||||
|
typedef typename traits_type::args_list args_list;
|
||||||
|
typedef typename traits_type::args_list free_args_list;
|
||||||
|
typedef typename traits_type::returns_list returns_list;
|
||||||
|
|
||||||
|
template <F fx, typename... Args>
|
||||||
|
static decltype(auto) invoke(Args&&... args) {
|
||||||
|
return fx(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
static decltype(auto) call(Fx&& fx, Args&&... args) {
|
||||||
|
return fx(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct caller {
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
decltype(auto) operator()(Fx&& fx, Args&&... args) const {
|
||||||
|
return call(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> {
|
||||||
|
typedef lua_bind_traits<F> traits_type;
|
||||||
|
typedef typename traits_type::object_type object_type;
|
||||||
|
typedef typename traits_type::return_type return_type;
|
||||||
|
typedef typename traits_type::args_list args_list;
|
||||||
|
typedef types<object_type&, return_type> free_args_list;
|
||||||
|
typedef typename traits_type::returns_list returns_list;
|
||||||
|
|
||||||
|
template <F fx, typename... Args>
|
||||||
|
static decltype(auto) invoke(object_type& mem, Args&&... args) {
|
||||||
|
return (mem.*fx)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fx>
|
||||||
|
static decltype(auto) call(Fx&& fx, object_type& mem) {
|
||||||
|
return (mem.*fx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fx, typename Arg, typename... Args>
|
||||||
|
static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&... args) {
|
||||||
|
(mem.*fx) = std::forward<Arg>(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct caller {
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const {
|
||||||
|
return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F, typename R, typename O, typename... FArgs>
|
||||||
|
struct member_function_wrapper {
|
||||||
|
typedef O object_type;
|
||||||
|
typedef lua_bind_traits<F> traits_type;
|
||||||
|
typedef typename traits_type::args_list args_list;
|
||||||
|
typedef types<object_type&, FArgs...> free_args_list;
|
||||||
|
typedef meta::tuple_types<R> returns_list;
|
||||||
|
|
||||||
|
template <F fx, typename... Args>
|
||||||
|
static R invoke(O& mem, Args... args) {
|
||||||
|
return (mem.*fx)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
static R call(Fx&& fx, O& mem, Args... args) {
|
||||||
|
return (mem.*fx)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct caller {
|
||||||
|
template <typename Fx, typename... Args>
|
||||||
|
decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const {
|
||||||
|
return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...)> : public member_function_wrapper<R(O:: *)(Args...), R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) const> : public member_function_wrapper<R(O:: *)(Args...) const, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) const volatile> : public member_function_wrapper<R(O:: *)(Args...) const volatile, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) &> : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) const &> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) const volatile &> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args..., ...) &> : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args..., ...) const &> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args..., ...) const volatile &> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) && > : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) const &&> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args..., ...) && > : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args..., ...) const &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename O, typename... Args>
|
||||||
|
struct wrapper<R(O:: *)(Args..., ...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // sol
|
||||||
|
|
||||||
|
#endif // SOL_WRAPPER_HPP
|
|
@ -4,7 +4,6 @@
|
||||||
#include <sol.hpp>
|
#include <sol.hpp>
|
||||||
|
|
||||||
// There isn't a single library roundtripping with codecvt works on. We'll do the nitty-gritty of it later...
|
// There isn't a single library roundtripping with codecvt works on. We'll do the nitty-gritty of it later...
|
||||||
#if 0
|
|
||||||
TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
|
@ -12,7 +11,9 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
||||||
static const char16_t utf16str[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 };
|
static const char16_t utf16str[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 };
|
||||||
static const char32_t utf32str[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 };
|
static const char32_t utf32str[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 };
|
||||||
static const wchar_t widestr[] = L"Fuck these shitty compilers";
|
static const wchar_t widestr[] = L"Fuck these shitty compilers";
|
||||||
|
static const char32_t utf32str2[] = U"🕴";
|
||||||
|
|
||||||
|
#if 0
|
||||||
lua["utf8"] = utf8str;
|
lua["utf8"] = utf8str;
|
||||||
lua["utf16"] = utf16str;
|
lua["utf16"] = utf16str;
|
||||||
lua["utf32"] = utf32str;
|
lua["utf32"] = utf32str;
|
||||||
|
@ -67,5 +68,5 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") {
|
||||||
REQUIRE(utf16_to_char32 == utf32str[0]);
|
REQUIRE(utf16_to_char32 == utf32str[0]);
|
||||||
REQUIRE(utf32_to_char32 == utf32str[0]);
|
REQUIRE(utf32_to_char32 == utf32str[0]);
|
||||||
REQUIRE(wide_to_char32 == utf32str[0]);
|
REQUIRE(wide_to_char32 == utf32str[0]);
|
||||||
}
|
|
||||||
#endif // Shit C++
|
#endif // Shit C++
|
||||||
|
}
|
||||||
|
|
|
@ -359,7 +359,7 @@ TEST_CASE("state/multi-require", "make sure that requires transfers across hand-
|
||||||
|
|
||||||
int val1 = thingy1["modfunc"]();
|
int val1 = thingy1["modfunc"]();
|
||||||
int val2 = thingy2["modfunc"]();
|
int val2 = thingy2["modfunc"]();
|
||||||
int val3 = thingy2["modfunc"]();
|
int val3 = thingy3["modfunc"]();
|
||||||
REQUIRE(val1 == 221);
|
REQUIRE(val1 == 221);
|
||||||
REQUIRE(val2 == 221);
|
REQUIRE(val2 == 221);
|
||||||
REQUIRE(val3 == 221);
|
REQUIRE(val3 == 221);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user