mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Fixes the key value being left on the stack when using iterators (the other case that's not "and we're not actually using this for iteration", asides from the empty table case).
Closes #111 - fixed Closes #110 - need to test exactly how much extra speed was gained Closes #108 - seems to be fixed, albeit std::mutex is a butt on VC++
This commit is contained in:
parent
79db8b3858
commit
220ff5a475
78
sol/call.hpp
78
sol/call.hpp
@ -85,7 +85,6 @@ namespace call_detail {
|
||||
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)...);
|
||||
@ -150,14 +149,16 @@ namespace call_detail {
|
||||
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);
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua<is_index ? 1 : 2>(returns_list(), args_list(), L, is_index ? 2 : 3, 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);
|
||||
typedef typename wrap::caller caller;
|
||||
return stack::call_into_lua(returns_list(), args_list(), L, 1, caller(), f);
|
||||
}
|
||||
|
||||
static int call(lua_State* L, F f) {
|
||||
@ -171,20 +172,36 @@ namespace call_detail {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::caller caller;
|
||||
|
||||
#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);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, 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);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f);
|
||||
#endif // Safety
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, lua_r_CFunction f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool is_index, bool is_variable, typename C>
|
||||
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, lua_CFunction f) {
|
||||
return f(L);
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
@ -200,6 +217,7 @@ namespace call_detail {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::args_list args_list;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::caller caller;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
@ -208,14 +226,14 @@ namespace call_detail {
|
||||
}
|
||||
return luaL_error(L, "sol: received nil 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);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, 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);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
|
||||
#endif // Safety
|
||||
}
|
||||
|
||||
static int call_assign(std::false_type, lua_State* L, F f) {
|
||||
static int call_assign(std::false_type, lua_State* L, F) {
|
||||
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
|
||||
}
|
||||
|
||||
@ -224,7 +242,7 @@ namespace call_detail {
|
||||
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) {
|
||||
static int call_const(std::true_type, lua_State* L, F) {
|
||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||
}
|
||||
|
||||
@ -241,6 +259,7 @@ namespace call_detail {
|
||||
typedef wrapper<meta::unqualified_t<F>> wrap;
|
||||
typedef typename wrap::object_type object_type;
|
||||
typedef typename wrap::returns_list returns_list;
|
||||
typedef typename wrap::caller caller;
|
||||
#ifdef SOL_SAFE_USERTYPE
|
||||
object_type* o = stack::get<object_type*>(L, 1);
|
||||
if (o == nullptr) {
|
||||
@ -249,30 +268,14 @@ namespace call_detail {
|
||||
}
|
||||
return luaL_error(L, "sol: 'self' argument is nil (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);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, 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);
|
||||
return stack::call_into_lua<is_variable ? 2 : 1>(returns_list(), types<>(), L, is_variable ? 3 : 2, 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<no_construction, is_index, is_variable, C> {
|
||||
static int call(lua_State* L, no_construction&) {
|
||||
@ -325,7 +328,7 @@ namespace call_detail {
|
||||
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, C> {
|
||||
typedef sol::constructor_wrapper<Cxs...> F;
|
||||
|
||||
struct matchfx {
|
||||
struct onmatch {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
@ -355,7 +358,7 @@ namespace call_detail {
|
||||
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
|
||||
int syntaxval = static_cast<int>(syntax);
|
||||
int argcount = lua_gettop(L) - syntaxval;
|
||||
return construct<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(matchfx{}, L, argcount, 1 + syntaxval, f);
|
||||
return construct<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
|
||||
}
|
||||
|
||||
};
|
||||
@ -380,6 +383,23 @@ namespace call_detail {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Fs, bool is_index, bool is_variable, typename C>
|
||||
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, C> {
|
||||
typedef overload_set<Fs...> F;
|
||||
|
||||
struct on_match {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) {
|
||||
auto& f = std::get<I>(fx.set);
|
||||
return lua_call_wrapper<T, Fx, is_index, is_variable>{}.call(L, f);
|
||||
}
|
||||
};
|
||||
|
||||
static int call(lua_State* L, F& fx) {
|
||||
return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx);
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
|
@ -35,7 +35,7 @@ inline std::string dump_types(lua_State* L) {
|
||||
if(i != 1) {
|
||||
visual += " | ";
|
||||
}
|
||||
visual += type_name(L, stack::get<type>(L, i));
|
||||
visual += type_name(L, stack::get<type>(L, static_cast<int>(i)));
|
||||
}
|
||||
return visual;
|
||||
}
|
||||
|
@ -223,12 +223,12 @@ inline decltype(auto) pop(lua_State* L) {
|
||||
return popper<meta::unqualified_t<T>>{}.pop(L);
|
||||
}
|
||||
|
||||
template <bool global = false, bool raw = true, typename Key>
|
||||
template <bool global = false, bool raw = false, typename Key>
|
||||
void get_field(lua_State* L, Key&& key) {
|
||||
field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key));
|
||||
}
|
||||
|
||||
template <bool global = false, bool raw = true, typename Key>
|
||||
template <bool global = false, bool raw = false, typename Key>
|
||||
void get_field(lua_State* L, Key&& key, int tableindex) {
|
||||
field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex);
|
||||
}
|
||||
|
@ -213,32 +213,32 @@ struct field_setter<void*, false, true, C> {
|
||||
|
||||
template <typename... Args, bool b, bool raw, typename C>
|
||||
struct field_setter<std::tuple<Args...>, b, raw, C> {
|
||||
template <bool g, std::size_t I, typename Key, typename Value>
|
||||
void apply(std::index_sequence<I>, lua_State* L, Key&& keys, Value&& value, int tableindex) {
|
||||
I < 1 ?
|
||||
set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value), tableindex) :
|
||||
set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value));
|
||||
}
|
||||
template <bool g, std::size_t I, typename Key, typename Value>
|
||||
void apply(std::index_sequence<I>, lua_State* L, Key&& keys, Value&& value, int tableindex) {
|
||||
I < 1 ?
|
||||
set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value), tableindex) :
|
||||
set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value));
|
||||
}
|
||||
|
||||
template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value>
|
||||
void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) {
|
||||
I0 < 1 ? get_field<g>(L, detail::forward_get<I0>(keys), tableindex) : get_field<g>(L, detail::forward_get<I0>(keys), -1);
|
||||
apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1);
|
||||
}
|
||||
template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value>
|
||||
void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) {
|
||||
I0 < 1 ? get_field<g, raw>(L, detail::forward_get<I0>(keys), tableindex) : get_field<g, raw>(L, detail::forward_get<I0>(keys), -1);
|
||||
apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1);
|
||||
}
|
||||
|
||||
template <typename Keys, typename Value>
|
||||
void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) {
|
||||
apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex);
|
||||
}
|
||||
template <typename Keys, typename Value>
|
||||
void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) {
|
||||
apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename A, typename B, bool b, bool raw, typename C>
|
||||
struct field_setter<std::pair<A, B>, b, raw, C> {
|
||||
template <typename Keys, typename Value>
|
||||
void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) {
|
||||
get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex);
|
||||
set_field<false, raw>(L, detail::forward_get<1>(keys), std::forward<Value>(value));
|
||||
}
|
||||
template <typename Keys, typename Value>
|
||||
void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) {
|
||||
get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex);
|
||||
set_field<false, raw>(L, detail::forward_get<1>(keys), std::forward<Value>(value));
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
} // sol
|
||||
|
@ -32,7 +32,7 @@ namespace stack {
|
||||
template<typename T, typename>
|
||||
struct pusher {
|
||||
template <typename K, typename... Args>
|
||||
static int push_keyed(lua_State* L, metatable_registry_key<K> k, Args&&... args) {
|
||||
static int push_keyed(lua_State* L, K&& k, Args&&... args) {
|
||||
// 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
|
||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||
@ -44,32 +44,32 @@ struct pusher {
|
||||
referencereference = allocationtarget;
|
||||
std::allocator<T> alloc{};
|
||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
||||
luaL_newmetatable(L, &k.key[0]);
|
||||
luaL_newmetatable(L, &k[0]);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
return push_keyed(L, meta_registry_key(&usertype_traits<T*>::metatable[0]), std::forward<Args>(args)...);
|
||||
return push_keyed(L, usertype_traits<T>::metatable, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*> {
|
||||
template <typename K>
|
||||
static int push_keyed(lua_State* L, metatable_registry_key<K> k, T* obj) {
|
||||
static int push_keyed(lua_State* L, K&& k, T* obj) {
|
||||
if (obj == nullptr)
|
||||
return stack::push(L, nil);
|
||||
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
||||
*pref = obj;
|
||||
luaL_getmetatable(L, &k.key[0]);
|
||||
luaL_getmetatable(L, &k[0]);
|
||||
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);
|
||||
return push_keyed(L, usertype_traits<T*>::metatable, obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -329,10 +329,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<bool read_only = true, typename... Args>
|
||||
state_view& new_enum(const std::string& name, Args&&... args) {
|
||||
global.new_enum<read_only>(name, std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename... CArgs, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) {
|
||||
global.new_usertype<Class>(name, ctor, std::forward<Args>(args)...);
|
||||
return *this;
|
||||
global.new_usertype<Class>(name, ctor, std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
|
@ -33,6 +33,9 @@ namespace detail {
|
||||
template <std::size_t n>
|
||||
struct clean { lua_State* L; clean(lua_State* L) : L(L) {} ~clean() { lua_pop(L, static_cast<int>(n)); } };
|
||||
struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* L, int& n) : L(L), n(n) {} ~ref_clean() { lua_pop(L, static_cast<int>(n)); } };
|
||||
inline int fail_on_newindex(lua_State* L) {
|
||||
return luaL_error(L, "sol: cannot modify the elements of an enumeration table");
|
||||
}
|
||||
}
|
||||
|
||||
template <bool top_level, typename base_t>
|
||||
@ -269,6 +272,23 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<bool read_only = true, typename... Args>
|
||||
basic_table_core& new_enum(const std::string& name, Args&&... args) {
|
||||
if (read_only) {
|
||||
table idx = create_with(std::forward<Args>(args)...);
|
||||
table x = create_with(
|
||||
meta_function::new_index, detail::fail_on_newindex,
|
||||
meta_function::index, idx
|
||||
);
|
||||
table target = create_named(name);
|
||||
target[metatable_key] = x;
|
||||
}
|
||||
else {
|
||||
create_named(name, std::forward<Args>(args)... );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Fx>
|
||||
void for_each( Fx&& fx ) const {
|
||||
typedef meta::is_invokable<Fx( std::pair<sol::object, sol::object> )> is_paired;
|
||||
|
@ -45,11 +45,12 @@ private:
|
||||
std::pair<object, object> kvp;
|
||||
reference_type ref;
|
||||
int tableidx = 0;
|
||||
int keyidx = 0;
|
||||
std::ptrdiff_t idx = 0;
|
||||
|
||||
public:
|
||||
|
||||
basic_table_iterator () : idx(-1) {
|
||||
basic_table_iterator () : idx(-1), keyidx(-1) {
|
||||
|
||||
}
|
||||
|
||||
@ -70,6 +71,7 @@ public:
|
||||
|
||||
if (lua_next(ref.lua_state(), tableidx) == 0) {
|
||||
idx = -1;
|
||||
keyidx = -1;
|
||||
return *this;
|
||||
}
|
||||
++idx;
|
||||
@ -77,6 +79,7 @@ public:
|
||||
kvp.second = object(ref.lua_state(), -1);
|
||||
lua_pop(ref.lua_state(), 1);
|
||||
// leave key on the stack
|
||||
keyidx = lua_gettop(ref.lua_state());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -103,9 +106,12 @@ public:
|
||||
}
|
||||
|
||||
~basic_table_iterator() {
|
||||
if (ref.valid()) {
|
||||
stack::remove(ref.lua_state(), tableidx, 1);
|
||||
}
|
||||
if (keyidx != -1) {
|
||||
stack::remove(ref.lua_state(), keyidx, 1);
|
||||
}
|
||||
if (ref.valid()) {
|
||||
stack::remove(ref.lua_state(), tableidx, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -125,6 +125,23 @@ namespace sol {
|
||||
l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc };
|
||||
++index;
|
||||
}
|
||||
if (baseclasscast != nullptr)
|
||||
return index;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
static_assert(sizeof(void*) <= sizeof(detail::throw_cast), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = baseclasscast = (void*)&detail::throw_as<T>;
|
||||
#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_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>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T>::type_cast;
|
||||
#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_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>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T>::type_cast;
|
||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@ -143,7 +160,7 @@ namespace sol {
|
||||
return endindex;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
static_assert(sizeof(void*) <= sizeof(detail::throw_cast), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscast = (void*)&detail::throw_as<T>;
|
||||
baseclasscheck = baseclasscast = (void*)&detail::throw_as<T>;
|
||||
#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_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
@ -186,7 +203,7 @@ namespace sol {
|
||||
}
|
||||
|
||||
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) {
|
||||
int find_call(std::integral_constant<bool, is_index>, std::index_sequence<>, lua_State* L, const sol::string_detail::string_shim&) {
|
||||
if (is_index)
|
||||
return indexfunc(L);
|
||||
else
|
||||
@ -308,7 +325,7 @@ namespace sol {
|
||||
lua_createtable(L, 0, 1);
|
||||
stack_reference metabehind(L, -1);
|
||||
if (um.callconstructfunc != nullptr) {
|
||||
stack::set_field(L, sol::meta_function::call_function, um.callconstructfunc, metabehind.stack_index());
|
||||
stack::set_field(L, sol::meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
@ -112,12 +112,12 @@ namespace sol {
|
||||
typedef meta::tuple_types<R> returns_list;
|
||||
|
||||
template <F fx, typename... Args>
|
||||
static R invoke(O& mem, Args... 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) {
|
||||
static R call(Fx&& fx, O& mem, Args&&... args) {
|
||||
return (mem.*fx)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,31 @@ TEST_CASE("tables/as-enum-classes", "Making sure enums can be put in and gotten
|
||||
REQUIRE(dir == direction::up);
|
||||
}
|
||||
|
||||
TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as values") {
|
||||
enum class direction {
|
||||
up,
|
||||
down,
|
||||
left,
|
||||
right
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_enum( "direction",
|
||||
"up", direction::up,
|
||||
"down", direction::down,
|
||||
"left", direction::left,
|
||||
"right", direction::right
|
||||
);
|
||||
|
||||
direction d = lua["direction"]["left"];
|
||||
REQUIRE(d == direction::left);
|
||||
REQUIRE_THROWS(lua.script("direction.left = 50"));
|
||||
d = lua["direction"]["left"];
|
||||
REQUIRE(d == direction::left);
|
||||
}
|
||||
|
||||
TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a lua table") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
@ -174,7 +174,51 @@ struct self_test {
|
||||
}
|
||||
};
|
||||
|
||||
struct ext_getset {
|
||||
|
||||
int bark = 24;
|
||||
const int meow = 56;
|
||||
|
||||
ext_getset() = default;
|
||||
ext_getset(int v) : bark(v) {}
|
||||
ext_getset(ext_getset&&) = default;
|
||||
ext_getset(const ext_getset&) = delete;
|
||||
ext_getset& operator=(ext_getset&&) = default;
|
||||
ext_getset& operator=(const ext_getset&) = delete;
|
||||
~ext_getset() {
|
||||
|
||||
}
|
||||
|
||||
std::string x() {
|
||||
return "bark bark bark";
|
||||
}
|
||||
|
||||
int x2(std::string x) {
|
||||
return static_cast<int>(x.length());
|
||||
}
|
||||
|
||||
void set(sol::variadic_args, sol::this_state, int x) {
|
||||
bark = x;
|
||||
}
|
||||
|
||||
int get(sol::this_state, sol::variadic_args) {
|
||||
return bark;
|
||||
}
|
||||
|
||||
static void s_set(int) {
|
||||
|
||||
}
|
||||
|
||||
static int s_get(int x) {
|
||||
return x + 20;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void des(T& e) {
|
||||
e.~T();
|
||||
}
|
||||
|
||||
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
|
||||
sol::state lua;
|
||||
@ -864,3 +908,89 @@ TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed
|
||||
REQUIRE_THROWS(lua.script("t = thing.new()"));
|
||||
}
|
||||
|
||||
TEST_CASE("usertype/coverage", "try all the things") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<ext_getset>("ext_getset",
|
||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>(),
|
||||
sol::meta_function::garbage_collect, sol::destructor(des<ext_getset>),
|
||||
"x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) { return m.meow + 50 + y + x.length(); }),
|
||||
"bark", &ext_getset::bark,
|
||||
"meow", &ext_getset::meow,
|
||||
"readonlybark", sol::readonly(&ext_getset::bark),
|
||||
"set", &ext_getset::set,
|
||||
"get", &ext_getset::get,
|
||||
"sset", &ext_getset::s_set,
|
||||
"sget", &ext_getset::s_get,
|
||||
"propbark", sol::property(&ext_getset::set, &ext_getset::get),
|
||||
"readonlypropbark", sol::property(&ext_getset::get),
|
||||
"writeonlypropbark", sol::property(&ext_getset::set)
|
||||
);
|
||||
|
||||
lua.script(R"(
|
||||
e = ext_getset()
|
||||
w = e:x(e:x(), e:x(e:x()))
|
||||
print(w)
|
||||
)");
|
||||
|
||||
int w = lua["w"];
|
||||
REQUIRE(w == 27);
|
||||
|
||||
lua.script(R"(
|
||||
e:set(500)
|
||||
e.sset(24)
|
||||
x = e:get()
|
||||
y = e.sget(20)
|
||||
)");
|
||||
|
||||
int x = lua["x"];
|
||||
int y = lua["y"];
|
||||
REQUIRE(x == 500);
|
||||
REQUIRE(y == 40);
|
||||
|
||||
lua.script(R"(
|
||||
e.bark = 5001
|
||||
a = e:get()
|
||||
print(e.bark)
|
||||
print(a)
|
||||
|
||||
e.propbark = 9700
|
||||
b = e:get()
|
||||
print(e.propbark)
|
||||
print(b)
|
||||
)");
|
||||
int a = lua["a"];
|
||||
int b = lua["b"];
|
||||
|
||||
REQUIRE(a == 5001);
|
||||
REQUIRE(b == 9700);
|
||||
|
||||
lua.script(R"(
|
||||
c = e.readonlybark
|
||||
d = e.meow
|
||||
print(e.readonlybark)
|
||||
print(c)
|
||||
print(e.meow)
|
||||
print(d)
|
||||
)");
|
||||
|
||||
int c = lua["c"];
|
||||
int d = lua["d"];
|
||||
REQUIRE(a == 5001);
|
||||
REQUIRE(b == 9700);
|
||||
|
||||
lua.script(R"(
|
||||
e.writeonlypropbark = 500
|
||||
z = e.readonlypropbark
|
||||
print(e.readonlybark)
|
||||
print(e.bark)
|
||||
)");
|
||||
|
||||
int z = lua["z"];
|
||||
REQUIRE(z == 500);
|
||||
|
||||
REQUIRE_THROWS(lua.script("e.readonlybark = 24"));
|
||||
REQUIRE_THROWS(lua.script("e.readonlypropbark = 500"));
|
||||
REQUIRE_THROWS(lua.script("y = e.writeonlypropbark"));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user