mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Remove as many of the std::string error handlers as possible to avoid memory leaks in C mode
Add some checks for container usertypes that masquerade as convertible from tables Make sure shared_ptr-like types that are copyable are returned directly (but do not do this for move-only types)
This commit is contained in:
parent
88355fcdf8
commit
ce32549bc6
|
@ -147,7 +147,8 @@ namespace sol {
|
||||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||||
typedef typename traits::free_args_list args_list;
|
typedef typename traits::free_args_list args_list;
|
||||||
// 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
if constexpr (!traits::runtime_variadics_t::value
|
||||||
|
&& meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
||||||
return overload_match_arity(types<Fxs...>(),
|
return overload_match_arity(types<Fxs...>(),
|
||||||
std::index_sequence<In...>(),
|
std::index_sequence<In...>(),
|
||||||
std::index_sequence<M...>(),
|
std::index_sequence<M...>(),
|
||||||
|
@ -237,7 +238,8 @@ namespace sol {
|
||||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||||
typedef typename traits::free_args_list args_list;
|
typedef typename traits::free_args_list args_list;
|
||||||
// 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
if constexpr (!traits::runtime_variadics_t::value
|
||||||
|
&& meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
||||||
return overload_match_arity(types<Fx1, Fxs...>(),
|
return overload_match_arity(types<Fx1, Fxs...>(),
|
||||||
std::index_sequence<I1, In...>(),
|
std::index_sequence<I1, In...>(),
|
||||||
std::index_sequence<M...>(),
|
std::index_sequence<M...>(),
|
||||||
|
@ -373,6 +375,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
|
if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
|
||||||
|
(void)f;
|
||||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -502,8 +505,13 @@ namespace sol {
|
||||||
else {
|
else {
|
||||||
using returns_list = typename wrap::returns_list;
|
using returns_list = typename wrap::returns_list;
|
||||||
using caller = typename wrap::caller;
|
using caller = typename wrap::caller;
|
||||||
return stack::call_into_lua<checked, clean_stack>(
|
return stack::call_into_lua<checked, clean_stack>(returns_list(),
|
||||||
returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...);
|
types<>(),
|
||||||
|
L,
|
||||||
|
boost + (is_variable ? 3 : 2),
|
||||||
|
caller(),
|
||||||
|
std::forward<Fx>(fx),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -727,8 +735,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename F, typename... Args>
|
template <typename F, typename... Args>
|
||||||
static int call(lua_State* L, F&& f, Args&&... args) {
|
static int call(lua_State* L, F&& f, Args&&... args) {
|
||||||
constexpr bool is_specialized = meta::any<
|
constexpr bool is_specialized = meta::any<std::is_same<U, detail::no_prop>,
|
||||||
std::is_same<U, detail::no_prop>,
|
|
||||||
meta::is_specialization_of<U, var_wrapper>,
|
meta::is_specialization_of<U, var_wrapper>,
|
||||||
meta::is_specialization_of<U, constructor_wrapper>,
|
meta::is_specialization_of<U, constructor_wrapper>,
|
||||||
meta::is_specialization_of<U, constructor_list>,
|
meta::is_specialization_of<U, constructor_list>,
|
||||||
|
@ -861,7 +868,8 @@ namespace sol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true>
|
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls,
|
||||||
|
bool clean_stack = true>
|
||||||
inline int call_user(lua_State* L) {
|
inline int call_user(lua_State* L) {
|
||||||
auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start));
|
auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start));
|
||||||
return call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
|
return call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "demangle.hpp"
|
#include "demangle.hpp"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -46,21 +48,20 @@ namespace sol {
|
||||||
constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
|
constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
|
||||||
constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call";
|
constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call";
|
||||||
|
|
||||||
inline void accumulate_and_mark(const std::string& n, std::string& addendum, int& marker) {
|
inline void accumulate_and_mark(const std::string& n, std::string& aux_message, int& marker) {
|
||||||
if (marker > 0) {
|
if (marker > 0) {
|
||||||
addendum += ", ";
|
aux_message += ", ";
|
||||||
}
|
}
|
||||||
addendum += n;
|
aux_message += n;
|
||||||
++marker;
|
++marker;
|
||||||
}
|
}
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
inline std::string associated_type_name(lua_State* L, int index, type t) {
|
inline std::string associated_type_name(lua_State* L, int index, type t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case type::poly:
|
case type::poly:
|
||||||
return "anything";
|
return "anything";
|
||||||
case type::userdata:
|
case type::userdata: {
|
||||||
{
|
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
luaL_checkstack(L, 2, "not enough space to push get the type name");
|
luaL_checkstack(L, 2, "not enough space to push get the type name");
|
||||||
#endif // make sure stack doesn't overflow
|
#endif // make sure stack doesn't overflow
|
||||||
|
@ -81,63 +82,67 @@ namespace sol {
|
||||||
return lua_typename(L, static_cast<int>(t));
|
return lua_typename(L, static_cast<int>(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int type_panic_string(lua_State* L, int index, type expected, type actual, const std::string& message = "") noexcept(false) {
|
inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept {
|
||||||
const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s";
|
const char* err = message.size() == 0
|
||||||
std::string actualname = associated_type_name(L, index, actual);
|
? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s")
|
||||||
return luaL_error(L, err, index,
|
: "stack index %d, expected %s, received %s: %s %s";
|
||||||
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)),
|
const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected));
|
||||||
actualname.c_str(),
|
{
|
||||||
message.c_str());
|
std::string actual_name = associated_type_name(L, index, actual);
|
||||||
|
lua_pushfstring(L, err, index, type_name, actual_name.c_str(), message.data(), aux_message.data());
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) {
|
||||||
|
push_type_panic_string(L, index, expected, actual, message, "");
|
||||||
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) {
|
inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) {
|
||||||
const char* err = message == nullptr || (std::char_traits<char>::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s";
|
push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, "");
|
||||||
std::string actualname = associated_type_name(L, index, actual);
|
return lua_error(L);
|
||||||
return luaL_error(L, err, index,
|
|
||||||
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)),
|
|
||||||
actualname.c_str(),
|
|
||||||
message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct type_panic_t {
|
struct type_panic_t {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) {
|
||||||
return type_panic_c_str(L, index, expected, actual, nullptr);
|
return type_panic_c_str(L, index, expected, actual, nullptr);
|
||||||
}
|
}
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const char* message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
return type_panic_c_str(L, index, expected, actual, message);
|
return type_panic_c_str(L, index, expected, actual, message.data());
|
||||||
}
|
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
|
||||||
return type_panic_string(L, index, expected, actual, message);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const type_panic_t type_panic = {};
|
const type_panic_t type_panic = {};
|
||||||
|
|
||||||
struct constructor_handler {
|
struct constructor_handler {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
std::string str = "(type check failed in constructor)";
|
push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)");
|
||||||
return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str);
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F = void>
|
template <typename F = void>
|
||||||
struct argument_handler {
|
struct argument_handler {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
std::string str = "(bad argument to variable or function call)";
|
push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)");
|
||||||
return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str );
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
template <typename R, typename... Args>
|
||||||
struct argument_handler<types<R, Args...>> {
|
struct argument_handler<types<R, Args...>> {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
std::string addendum = "(bad argument into '";
|
{
|
||||||
addendum += detail::demangle<R>();
|
std::string aux_message = "(bad argument into '";
|
||||||
addendum += "(";
|
aux_message += detail::demangle<R>();
|
||||||
|
aux_message += "(";
|
||||||
int marker = 0;
|
int marker = 0;
|
||||||
(void)detail::swallow{int(), (detail::accumulate_and_mark(detail::demangle<Args>(), addendum, marker), int())...};
|
(void)detail::swallow{ int(), (detail::accumulate_and_mark(detail::demangle<Args>(), aux_message, marker), int())... };
|
||||||
addendum += ")')";
|
aux_message += ")')";
|
||||||
return type_panic_string(L, index, expected, actual, message.empty() ? addendum : message + " " + addendum);
|
push_type_panic_string(L, index, expected, actual, message, aux_message);
|
||||||
|
}
|
||||||
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,9 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline decltype(auto) deref_non_pointer(T&& item) {
|
inline decltype(auto) deref_move_only(T&& item) {
|
||||||
using Tu = meta::unqualified_t<T>;
|
using Tu = meta::unqualified_t<T>;
|
||||||
if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu>) {
|
if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) {
|
||||||
return *std::forward<T>(item);
|
return *std::forward<T>(item);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -491,7 +491,7 @@ namespace sol {
|
||||||
captured_type;
|
captured_type;
|
||||||
typedef typename meta::iterator_tag<iterator>::type iterator_category;
|
typedef typename meta::iterator_tag<iterator>::type iterator_category;
|
||||||
typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
|
typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
|
||||||
typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_non_pointer(std::declval<captured_type>()))> push_type;
|
typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_move_only(std::declval<captured_type>()))> push_type;
|
||||||
typedef std::is_copy_assignable<V> is_copyable;
|
typedef std::is_copy_assignable<V> is_copyable;
|
||||||
typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable;
|
typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable;
|
||||||
typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type;
|
typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type;
|
||||||
|
@ -564,12 +564,12 @@ namespace sol {
|
||||||
template <typename Iter>
|
template <typename Iter>
|
||||||
static detail::error_result get_associative(std::true_type, lua_State* L, Iter& it) {
|
static detail::error_result get_associative(std::true_type, lua_State* L, Iter& it) {
|
||||||
decltype(auto) v = *it;
|
decltype(auto) v = *it;
|
||||||
return stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(v.second));
|
return stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(v.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Iter>
|
template <typename Iter>
|
||||||
static detail::error_result get_associative(std::false_type, lua_State* L, Iter& it) {
|
static detail::error_result get_associative(std::false_type, lua_State* L, Iter& it) {
|
||||||
return stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(*it));
|
return stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(*it));
|
||||||
}
|
}
|
||||||
|
|
||||||
static detail::error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
|
static detail::error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
|
||||||
|
@ -1144,7 +1144,7 @@ namespace sol {
|
||||||
else {
|
else {
|
||||||
p = stack::push_reference(L, it->first);
|
p = stack::push_reference(L, it->first);
|
||||||
}
|
}
|
||||||
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(it->second));
|
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(it->second));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -1165,7 +1165,7 @@ namespace sol {
|
||||||
else {
|
else {
|
||||||
p = stack::stack_detail::push_reference(L, k + 1);
|
p = stack::stack_detail::push_reference(L, k + 1);
|
||||||
}
|
}
|
||||||
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(*it));
|
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(*it));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -1391,7 +1391,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
int p;
|
int p;
|
||||||
p = stack::push(L, k + 1);
|
p = stack::push(L, k + 1);
|
||||||
p += stack::push_reference(L, detail::deref_non_pointer(*it));
|
p += stack::push_reference(L, detail::deref_move_only(*it));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -1424,7 +1424,7 @@ namespace sol {
|
||||||
if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) {
|
if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) {
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
return stack::push_reference(L, detail::deref_non_pointer(self[idx]));
|
return stack::push_reference(L, detail::deref_move_only(self[idx]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int index_get(lua_State* L) {
|
static int index_get(lua_State* L) {
|
||||||
|
|
|
@ -175,10 +175,7 @@ namespace sol { namespace u_detail {
|
||||||
index_call_storage* p_ics = nullptr;
|
index_call_storage* p_ics = nullptr;
|
||||||
usertype_storage_base* p_usb = nullptr;
|
usertype_storage_base* p_usb = nullptr;
|
||||||
void* p_derived_usb = nullptr;
|
void* p_derived_usb = nullptr;
|
||||||
lua_CFunction idx_call = nullptr,
|
lua_CFunction idx_call = nullptr, new_idx_call = nullptr, meta_idx_call = nullptr, meta_new_idx_call = nullptr;
|
||||||
new_idx_call = nullptr,
|
|
||||||
meta_idx_call = nullptr,
|
|
||||||
meta_new_idx_call = nullptr;
|
|
||||||
change_indexing_mem_func change_indexing;
|
change_indexing_mem_func change_indexing;
|
||||||
|
|
||||||
void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
|
void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
|
||||||
|
@ -196,14 +193,7 @@ namespace sol { namespace u_detail {
|
||||||
int fast_index_table_push = fast_index_table.push();
|
int fast_index_table_push = fast_index_table.push();
|
||||||
stack_reference t(L, -fast_index_table_push);
|
stack_reference t(L, -fast_index_table_push);
|
||||||
if (poison_indexing) {
|
if (poison_indexing) {
|
||||||
(usb.*change_indexing)(L,
|
(usb.*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
|
||||||
smt,
|
|
||||||
p_derived_usb,
|
|
||||||
t,
|
|
||||||
idx_call,
|
|
||||||
new_idx_call,
|
|
||||||
meta_idx_call,
|
|
||||||
meta_new_idx_call);
|
|
||||||
}
|
}
|
||||||
if (is_destruction
|
if (is_destruction
|
||||||
&& (smt == submetatable_type::reference || smt == submetatable_type::const_reference || smt == submetatable_type::named
|
&& (smt == submetatable_type::reference || smt == submetatable_type::const_reference || smt == submetatable_type::named
|
||||||
|
@ -264,14 +254,7 @@ namespace sol { namespace u_detail {
|
||||||
stack::set_field(L, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index());
|
stack::set_field(L, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index());
|
||||||
stack::set_field(L, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index());
|
stack::set_field(L, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index());
|
||||||
// change indexing, forcefully
|
// change indexing, forcefully
|
||||||
(p_usb->*change_indexing)(L,
|
(p_usb->*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
|
||||||
smt,
|
|
||||||
p_derived_usb,
|
|
||||||
t,
|
|
||||||
idx_call,
|
|
||||||
new_idx_call,
|
|
||||||
meta_idx_call,
|
|
||||||
meta_new_idx_call);
|
|
||||||
t.pop();
|
t.pop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -279,7 +262,8 @@ namespace sol { namespace u_detail {
|
||||||
struct binding_data_equals {
|
struct binding_data_equals {
|
||||||
void* binding_data;
|
void* binding_data;
|
||||||
|
|
||||||
binding_data_equals(void* b) : binding_data(b) {}
|
binding_data_equals(void* b) : binding_data(b) {
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()(const std::unique_ptr<binding_base>& ptr) const {
|
bool operator()(const std::unique_ptr<binding_base>& ptr) const {
|
||||||
return binding_data == ptr->data();
|
return binding_data == ptr->data();
|
||||||
|
@ -644,6 +628,7 @@ namespace sol { namespace u_detail {
|
||||||
using Binding = binding<KeyU, ValueU, T>;
|
using Binding = binding<KeyU, ValueU, T>;
|
||||||
using is_var_bind = is_variable_binding<ValueU>;
|
using is_var_bind = is_variable_binding<ValueU>;
|
||||||
if constexpr (std::is_same_v<KeyU, call_construction>) {
|
if constexpr (std::is_same_v<KeyU, call_construction>) {
|
||||||
|
(void)key;
|
||||||
std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
|
std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
|
||||||
Binding& b = *p_binding;
|
Binding& b = *p_binding;
|
||||||
this->storage.push_back(std::move(p_binding));
|
this->storage.push_back(std::move(p_binding));
|
||||||
|
@ -689,9 +674,10 @@ namespace sol { namespace u_detail {
|
||||||
void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
|
void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
|
||||||
index_call_storage ics;
|
index_call_storage ics;
|
||||||
ics.binding_data = b.data();
|
ics.binding_data = b.data();
|
||||||
ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value> : &Binding::template index_call_with_<true, is_var_bind::value>;
|
ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value>
|
||||||
ics.new_index
|
: &Binding::template index_call_with_<true, is_var_bind::value>;
|
||||||
= is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value> : &Binding::template index_call_with_<false, is_var_bind::value>;
|
ics.new_index = is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value>
|
||||||
|
: &Binding::template index_call_with_<false, is_var_bind::value>;
|
||||||
|
|
||||||
string_for_each_metatable_func for_each_fx;
|
string_for_each_metatable_func for_each_fx;
|
||||||
for_each_fx.is_destruction = is_destruction;
|
for_each_fx.is_destruction = is_destruction;
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-10-02 08:43:39.434050 UTC
|
// Generated 2019-11-09 04:52:35.824332 UTC
|
||||||
// This header was generated with sol v3.0.3 (revision 908074e)
|
// This header was generated with sol v3.0.3 (revision 88355fc)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-10-02 08:43:38.869924 UTC
|
// Generated 2019-11-09 04:52:35.317324 UTC
|
||||||
// This header was generated with sol v3.0.3 (revision 908074e)
|
// This header was generated with sol v3.0.3 (revision 88355fc)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
|
@ -1228,9 +1228,9 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline decltype(auto) deref_non_pointer(T&& item) {
|
inline decltype(auto) deref_move_only(T&& item) {
|
||||||
using Tu = meta::unqualified_t<T>;
|
using Tu = meta::unqualified_t<T>;
|
||||||
if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu>) {
|
if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) {
|
||||||
return *std::forward<T>(item);
|
return *std::forward<T>(item);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -8266,6 +8266,8 @@ namespace sol {
|
||||||
|
|
||||||
// beginning of sol/error_handler.hpp
|
// beginning of sol/error_handler.hpp
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -8285,21 +8287,20 @@ namespace sol {
|
||||||
constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
|
constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment";
|
||||||
constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call";
|
constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call";
|
||||||
|
|
||||||
inline void accumulate_and_mark(const std::string& n, std::string& addendum, int& marker) {
|
inline void accumulate_and_mark(const std::string& n, std::string& aux_message, int& marker) {
|
||||||
if (marker > 0) {
|
if (marker > 0) {
|
||||||
addendum += ", ";
|
aux_message += ", ";
|
||||||
}
|
}
|
||||||
addendum += n;
|
aux_message += n;
|
||||||
++marker;
|
++marker;
|
||||||
}
|
}
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
inline std::string associated_type_name(lua_State* L, int index, type t) {
|
inline std::string associated_type_name(lua_State* L, int index, type t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case type::poly:
|
case type::poly:
|
||||||
return "anything";
|
return "anything";
|
||||||
case type::userdata:
|
case type::userdata: {
|
||||||
{
|
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
luaL_checkstack(L, 2, "not enough space to push get the type name");
|
luaL_checkstack(L, 2, "not enough space to push get the type name");
|
||||||
#endif // make sure stack doesn't overflow
|
#endif // make sure stack doesn't overflow
|
||||||
|
@ -8320,63 +8321,67 @@ namespace sol {
|
||||||
return lua_typename(L, static_cast<int>(t));
|
return lua_typename(L, static_cast<int>(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int type_panic_string(lua_State* L, int index, type expected, type actual, const std::string& message = "") noexcept(false) {
|
inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept {
|
||||||
const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s";
|
const char* err = message.size() == 0
|
||||||
std::string actualname = associated_type_name(L, index, actual);
|
? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s")
|
||||||
return luaL_error(L, err, index,
|
: "stack index %d, expected %s, received %s: %s %s";
|
||||||
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)),
|
const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected));
|
||||||
actualname.c_str(),
|
{
|
||||||
message.c_str());
|
std::string actual_name = associated_type_name(L, index, actual);
|
||||||
|
lua_pushfstring(L, err, index, type_name, actual_name.c_str(), message.data(), aux_message.data());
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) {
|
||||||
|
push_type_panic_string(L, index, expected, actual, message, "");
|
||||||
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) {
|
inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) {
|
||||||
const char* err = message == nullptr || (std::char_traits<char>::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s";
|
push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, "");
|
||||||
std::string actualname = associated_type_name(L, index, actual);
|
return lua_error(L);
|
||||||
return luaL_error(L, err, index,
|
|
||||||
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)),
|
|
||||||
actualname.c_str(),
|
|
||||||
message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct type_panic_t {
|
struct type_panic_t {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) {
|
||||||
return type_panic_c_str(L, index, expected, actual, nullptr);
|
return type_panic_c_str(L, index, expected, actual, nullptr);
|
||||||
}
|
}
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const char* message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
return type_panic_c_str(L, index, expected, actual, message);
|
return type_panic_c_str(L, index, expected, actual, message.data());
|
||||||
}
|
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
|
||||||
return type_panic_string(L, index, expected, actual, message);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const type_panic_t type_panic = {};
|
const type_panic_t type_panic = {};
|
||||||
|
|
||||||
struct constructor_handler {
|
struct constructor_handler {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
std::string str = "(type check failed in constructor)";
|
push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)");
|
||||||
return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str);
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F = void>
|
template <typename F = void>
|
||||||
struct argument_handler {
|
struct argument_handler {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
std::string str = "(bad argument to variable or function call)";
|
push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)");
|
||||||
return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str );
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
template <typename R, typename... Args>
|
||||||
struct argument_handler<types<R, Args...>> {
|
struct argument_handler<types<R, Args...>> {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) {
|
||||||
std::string addendum = "(bad argument into '";
|
{
|
||||||
addendum += detail::demangle<R>();
|
std::string aux_message = "(bad argument into '";
|
||||||
addendum += "(";
|
aux_message += detail::demangle<R>();
|
||||||
|
aux_message += "(";
|
||||||
int marker = 0;
|
int marker = 0;
|
||||||
(void)detail::swallow{int(), (detail::accumulate_and_mark(detail::demangle<Args>(), addendum, marker), int())...};
|
(void)detail::swallow{ int(), (detail::accumulate_and_mark(detail::demangle<Args>(), aux_message, marker), int())... };
|
||||||
addendum += ")')";
|
aux_message += ")')";
|
||||||
return type_panic_string(L, index, expected, actual, message.empty() ? addendum : message + " " + addendum);
|
push_type_panic_string(L, index, expected, actual, message, aux_message);
|
||||||
|
}
|
||||||
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16241,7 +16246,8 @@ namespace sol {
|
||||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||||
typedef typename traits::free_args_list args_list;
|
typedef typename traits::free_args_list args_list;
|
||||||
// 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
if constexpr (!traits::runtime_variadics_t::value
|
||||||
|
&& meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
||||||
return overload_match_arity(types<Fxs...>(),
|
return overload_match_arity(types<Fxs...>(),
|
||||||
std::index_sequence<In...>(),
|
std::index_sequence<In...>(),
|
||||||
std::index_sequence<M...>(),
|
std::index_sequence<M...>(),
|
||||||
|
@ -16331,7 +16337,8 @@ namespace sol {
|
||||||
typedef meta::tuple_types<typename traits::return_type> return_types;
|
typedef meta::tuple_types<typename traits::return_type> return_types;
|
||||||
typedef typename traits::free_args_list args_list;
|
typedef typename traits::free_args_list args_list;
|
||||||
// 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 constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
if constexpr (!traits::runtime_variadics_t::value
|
||||||
|
&& meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) {
|
||||||
return overload_match_arity(types<Fx1, Fxs...>(),
|
return overload_match_arity(types<Fx1, Fxs...>(),
|
||||||
std::index_sequence<I1, In...>(),
|
std::index_sequence<I1, In...>(),
|
||||||
std::index_sequence<M...>(),
|
std::index_sequence<M...>(),
|
||||||
|
@ -16467,6 +16474,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
|
if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
|
||||||
|
(void)f;
|
||||||
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -16596,8 +16604,13 @@ namespace sol {
|
||||||
else {
|
else {
|
||||||
using returns_list = typename wrap::returns_list;
|
using returns_list = typename wrap::returns_list;
|
||||||
using caller = typename wrap::caller;
|
using caller = typename wrap::caller;
|
||||||
return stack::call_into_lua<checked, clean_stack>(
|
return stack::call_into_lua<checked, clean_stack>(returns_list(),
|
||||||
returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...);
|
types<>(),
|
||||||
|
L,
|
||||||
|
boost + (is_variable ? 3 : 2),
|
||||||
|
caller(),
|
||||||
|
std::forward<Fx>(fx),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -16821,8 +16834,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename F, typename... Args>
|
template <typename F, typename... Args>
|
||||||
static int call(lua_State* L, F&& f, Args&&... args) {
|
static int call(lua_State* L, F&& f, Args&&... args) {
|
||||||
constexpr bool is_specialized = meta::any<
|
constexpr bool is_specialized = meta::any<std::is_same<U, detail::no_prop>,
|
||||||
std::is_same<U, detail::no_prop>,
|
|
||||||
meta::is_specialization_of<U, var_wrapper>,
|
meta::is_specialization_of<U, var_wrapper>,
|
||||||
meta::is_specialization_of<U, constructor_wrapper>,
|
meta::is_specialization_of<U, constructor_wrapper>,
|
||||||
meta::is_specialization_of<U, constructor_list>,
|
meta::is_specialization_of<U, constructor_list>,
|
||||||
|
@ -16955,7 +16967,8 @@ namespace sol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, bool clean_stack = true>
|
template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls,
|
||||||
|
bool clean_stack = true>
|
||||||
inline int call_user(lua_State* L) {
|
inline int call_user(lua_State* L) {
|
||||||
auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start));
|
auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start));
|
||||||
return call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
|
return call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx);
|
||||||
|
@ -19522,7 +19535,7 @@ namespace sol {
|
||||||
captured_type;
|
captured_type;
|
||||||
typedef typename meta::iterator_tag<iterator>::type iterator_category;
|
typedef typename meta::iterator_tag<iterator>::type iterator_category;
|
||||||
typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
|
typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
|
||||||
typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_non_pointer(std::declval<captured_type>()))> push_type;
|
typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_move_only(std::declval<captured_type>()))> push_type;
|
||||||
typedef std::is_copy_assignable<V> is_copyable;
|
typedef std::is_copy_assignable<V> is_copyable;
|
||||||
typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable;
|
typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable;
|
||||||
typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type;
|
typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type;
|
||||||
|
@ -19595,12 +19608,12 @@ namespace sol {
|
||||||
template <typename Iter>
|
template <typename Iter>
|
||||||
static detail::error_result get_associative(std::true_type, lua_State* L, Iter& it) {
|
static detail::error_result get_associative(std::true_type, lua_State* L, Iter& it) {
|
||||||
decltype(auto) v = *it;
|
decltype(auto) v = *it;
|
||||||
return stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(v.second));
|
return stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(v.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Iter>
|
template <typename Iter>
|
||||||
static detail::error_result get_associative(std::false_type, lua_State* L, Iter& it) {
|
static detail::error_result get_associative(std::false_type, lua_State* L, Iter& it) {
|
||||||
return stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(*it));
|
return stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(*it));
|
||||||
}
|
}
|
||||||
|
|
||||||
static detail::error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
|
static detail::error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
|
||||||
|
@ -20175,7 +20188,7 @@ namespace sol {
|
||||||
else {
|
else {
|
||||||
p = stack::push_reference(L, it->first);
|
p = stack::push_reference(L, it->first);
|
||||||
}
|
}
|
||||||
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(it->second));
|
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(it->second));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -20196,7 +20209,7 @@ namespace sol {
|
||||||
else {
|
else {
|
||||||
p = stack::stack_detail::push_reference(L, k + 1);
|
p = stack::stack_detail::push_reference(L, k + 1);
|
||||||
}
|
}
|
||||||
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_non_pointer(*it));
|
p += stack::stack_detail::push_reference<push_type>(L, detail::deref_move_only(*it));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -20422,7 +20435,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
int p;
|
int p;
|
||||||
p = stack::push(L, k + 1);
|
p = stack::push(L, k + 1);
|
||||||
p += stack::push_reference(L, detail::deref_non_pointer(*it));
|
p += stack::push_reference(L, detail::deref_move_only(*it));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -20455,7 +20468,7 @@ namespace sol {
|
||||||
if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) {
|
if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) {
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
return stack::push_reference(L, detail::deref_non_pointer(self[idx]));
|
return stack::push_reference(L, detail::deref_move_only(self[idx]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int index_get(lua_State* L) {
|
static int index_get(lua_State* L) {
|
||||||
|
@ -21254,10 +21267,7 @@ namespace sol { namespace u_detail {
|
||||||
index_call_storage* p_ics = nullptr;
|
index_call_storage* p_ics = nullptr;
|
||||||
usertype_storage_base* p_usb = nullptr;
|
usertype_storage_base* p_usb = nullptr;
|
||||||
void* p_derived_usb = nullptr;
|
void* p_derived_usb = nullptr;
|
||||||
lua_CFunction idx_call = nullptr,
|
lua_CFunction idx_call = nullptr, new_idx_call = nullptr, meta_idx_call = nullptr, meta_new_idx_call = nullptr;
|
||||||
new_idx_call = nullptr,
|
|
||||||
meta_idx_call = nullptr,
|
|
||||||
meta_new_idx_call = nullptr;
|
|
||||||
change_indexing_mem_func change_indexing;
|
change_indexing_mem_func change_indexing;
|
||||||
|
|
||||||
void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
|
void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) {
|
||||||
|
@ -21275,14 +21285,7 @@ namespace sol { namespace u_detail {
|
||||||
int fast_index_table_push = fast_index_table.push();
|
int fast_index_table_push = fast_index_table.push();
|
||||||
stack_reference t(L, -fast_index_table_push);
|
stack_reference t(L, -fast_index_table_push);
|
||||||
if (poison_indexing) {
|
if (poison_indexing) {
|
||||||
(usb.*change_indexing)(L,
|
(usb.*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
|
||||||
smt,
|
|
||||||
p_derived_usb,
|
|
||||||
t,
|
|
||||||
idx_call,
|
|
||||||
new_idx_call,
|
|
||||||
meta_idx_call,
|
|
||||||
meta_new_idx_call);
|
|
||||||
}
|
}
|
||||||
if (is_destruction
|
if (is_destruction
|
||||||
&& (smt == submetatable_type::reference || smt == submetatable_type::const_reference || smt == submetatable_type::named
|
&& (smt == submetatable_type::reference || smt == submetatable_type::const_reference || smt == submetatable_type::named
|
||||||
|
@ -21343,14 +21346,7 @@ namespace sol { namespace u_detail {
|
||||||
stack::set_field(L, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index());
|
stack::set_field(L, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index());
|
||||||
stack::set_field(L, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index());
|
stack::set_field(L, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index());
|
||||||
// change indexing, forcefully
|
// change indexing, forcefully
|
||||||
(p_usb->*change_indexing)(L,
|
(p_usb->*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call);
|
||||||
smt,
|
|
||||||
p_derived_usb,
|
|
||||||
t,
|
|
||||||
idx_call,
|
|
||||||
new_idx_call,
|
|
||||||
meta_idx_call,
|
|
||||||
meta_new_idx_call);
|
|
||||||
t.pop();
|
t.pop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -21358,7 +21354,8 @@ namespace sol { namespace u_detail {
|
||||||
struct binding_data_equals {
|
struct binding_data_equals {
|
||||||
void* binding_data;
|
void* binding_data;
|
||||||
|
|
||||||
binding_data_equals(void* b) : binding_data(b) {}
|
binding_data_equals(void* b) : binding_data(b) {
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()(const std::unique_ptr<binding_base>& ptr) const {
|
bool operator()(const std::unique_ptr<binding_base>& ptr) const {
|
||||||
return binding_data == ptr->data();
|
return binding_data == ptr->data();
|
||||||
|
@ -21723,6 +21720,7 @@ namespace sol { namespace u_detail {
|
||||||
using Binding = binding<KeyU, ValueU, T>;
|
using Binding = binding<KeyU, ValueU, T>;
|
||||||
using is_var_bind = is_variable_binding<ValueU>;
|
using is_var_bind = is_variable_binding<ValueU>;
|
||||||
if constexpr (std::is_same_v<KeyU, call_construction>) {
|
if constexpr (std::is_same_v<KeyU, call_construction>) {
|
||||||
|
(void)key;
|
||||||
std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
|
std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value));
|
||||||
Binding& b = *p_binding;
|
Binding& b = *p_binding;
|
||||||
this->storage.push_back(std::move(p_binding));
|
this->storage.push_back(std::move(p_binding));
|
||||||
|
@ -21768,9 +21766,10 @@ namespace sol { namespace u_detail {
|
||||||
void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
|
void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
|
||||||
index_call_storage ics;
|
index_call_storage ics;
|
||||||
ics.binding_data = b.data();
|
ics.binding_data = b.data();
|
||||||
ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value> : &Binding::template index_call_with_<true, is_var_bind::value>;
|
ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value>
|
||||||
ics.new_index
|
: &Binding::template index_call_with_<true, is_var_bind::value>;
|
||||||
= is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value> : &Binding::template index_call_with_<false, is_var_bind::value>;
|
ics.new_index = is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value>
|
||||||
|
: &Binding::template index_call_with_<false, is_var_bind::value>;
|
||||||
|
|
||||||
string_for_each_metatable_func for_each_fx;
|
string_for_each_metatable_func for_each_fx;
|
||||||
for_each_fx.is_destruction = is_destruction;
|
for_each_fx.is_destruction = is_destruction;
|
||||||
|
|
47
tests/runtime_tests/source/container.usertype_check.cpp
Normal file
47
tests/runtime_tests/source/container.usertype_check.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2019 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.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
struct user_container_type : public std::vector<int> {
|
||||||
|
typedef std::vector<int> base_t;
|
||||||
|
using base_t::base_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("usertype/container checking fake container", "A container should not respond yes in .is<> to every table in Lua") {
|
||||||
|
sol::state lua;
|
||||||
|
sol::stack_guard luasg(lua);
|
||||||
|
|
||||||
|
sol::optional<sol::error> err0 = lua.safe_script("a = {}");
|
||||||
|
REQUIRE_FALSE(err0.has_value());
|
||||||
|
|
||||||
|
sol::object a = lua["a"];
|
||||||
|
REQUIRE(a.is<user_container_type>());
|
||||||
|
REQUIRE_FALSE(a.is<user_container_type&>());
|
||||||
|
REQUIRE_FALSE(a.is<user_container_type&&>());
|
||||||
|
REQUIRE_FALSE(a.is<const user_container_type&>());
|
||||||
|
REQUIRE_FALSE(a.is<const user_container_type&&>());
|
||||||
|
}
|
|
@ -27,6 +27,17 @@
|
||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
struct unique_user_Display {
|
||||||
|
int value = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<unique_user_Display>> unique_user_foo() {
|
||||||
|
return { std::make_shared<unique_user_Display>(), std::make_shared<unique_user_Display>(), std::make_shared<unique_user_Display>() };
|
||||||
|
}
|
||||||
|
|
||||||
|
int unique_user_bar(std::shared_ptr<unique_user_Display> item) {
|
||||||
|
return item->value;
|
||||||
|
}
|
||||||
|
|
||||||
struct factory_test {
|
struct factory_test {
|
||||||
private:
|
private:
|
||||||
|
@ -171,3 +182,15 @@ TEST_CASE("usertype/unique void pointers", "can compile shared_ptr<void> types a
|
||||||
auto result = lua.safe_script("f(s)", sol::script_pass_on_error);
|
auto result = lua.safe_script("f(s)", sol::script_pass_on_error);
|
||||||
REQUIRE(result.valid());
|
REQUIRE(result.valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/unique containers", "copyable unique usertypes in containers are just fine and do not deref/decay") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
|
||||||
|
lua["foo"] = unique_user_foo;
|
||||||
|
lua["bar"] = unique_user_bar;
|
||||||
|
sol::optional<sol::error> err0 = lua.safe_script("v3 = foo()");
|
||||||
|
REQUIRE_FALSE(err0.has_value());
|
||||||
|
sol::optional<sol::error> err1 = lua.safe_script("assert(bar(v3[1]) == 5)");
|
||||||
|
REQUIRE_FALSE(err1.has_value());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user