mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Full fixes for everything.
This commit is contained in:
parent
b6f40935c8
commit
ee13a7812f
|
@ -85,6 +85,7 @@ function (MAKE_EXAMPLE example_source_file example_suffix target_sol)
|
||||||
else()
|
else()
|
||||||
target_compile_options(${example_name}
|
target_compile_options(${example_name}
|
||||||
PRIVATE -std=c++1z
|
PRIVATE -std=c++1z
|
||||||
|
-ftemplate-backtrace-limit=0
|
||||||
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
|
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
|
||||||
-Wno-noexcept-type
|
-Wno-noexcept-type
|
||||||
-Wno-unknown-warning -Wno-unknown-warning-option)
|
-Wno-unknown-warning -Wno-unknown-warning-option)
|
||||||
|
|
|
@ -44,4 +44,6 @@ int main() {
|
||||||
std::cout << "result2: " << result2 << std::endl;
|
std::cout << "result2: " << result2 << std::endl;
|
||||||
std::cout << "result3: " << result3 << std::endl;
|
std::cout << "result3: " << result3 << std::endl;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@ struct two_things {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
bool check(sol::types<two_things>, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking) {
|
bool sol_lua_check(sol::types<two_things>, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking) {
|
||||||
// indices can be negative to count backwards from the top of the stack,
|
// indices can be negative to count backwards from the top of the stack,
|
||||||
// rather than the bottom up
|
// rather than the bottom up
|
||||||
// to deal with this, we adjust the index to
|
// to deal with this, we adjust the index to
|
||||||
|
@ -22,7 +22,7 @@ bool check(sol::types<two_things>, lua_State* L, int index, Handler&& handler, s
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
two_things get(sol::types<two_things>, lua_State* L, int index, sol::stack::record& tracking) {
|
two_things sol_lua_get(sol::types<two_things>, lua_State* L, int index, sol::stack::record& tracking) {
|
||||||
int absolute_index = lua_absindex(L, index);
|
int absolute_index = lua_absindex(L, index);
|
||||||
// Get the first element
|
// Get the first element
|
||||||
int a = sol::stack::get<int>(L, absolute_index);
|
int a = sol::stack::get<int>(L, absolute_index);
|
||||||
|
@ -34,7 +34,7 @@ two_things get(sol::types<two_things>, lua_State* L, int index, sol::stack::reco
|
||||||
return two_things{ a, b };
|
return two_things{ a, b };
|
||||||
}
|
}
|
||||||
|
|
||||||
int push(sol::types<two_things>, lua_State* L, const two_things& things) {
|
int sol_lua_push(sol::types<two_things>, lua_State* L, const two_things& things) {
|
||||||
int amount = sol::stack::push(L, things.a);
|
int amount = sol::stack::push(L, things.a);
|
||||||
// amount will be 1: int pushes 1 item
|
// amount will be 1: int pushes 1 item
|
||||||
amount += sol::stack::push(L, things.b);
|
amount += sol::stack::push(L, things.b);
|
||||||
|
|
|
@ -29,6 +29,14 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA
|
||||||
|
struct lua_State;
|
||||||
|
#else
|
||||||
|
extern "C" {
|
||||||
|
struct lua_State;
|
||||||
|
}
|
||||||
|
#endif // C++ Mangling for Lua vs. Not
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
template <bool b>
|
template <bool b>
|
||||||
|
|
|
@ -46,14 +46,14 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto setup_table(std::true_type) {
|
auto setup_table(std::true_type) {
|
||||||
auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, tbl.stack_index());
|
auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>, global_table>>(lua_state(), key, tbl.stack_index());
|
||||||
lua_pop(lua_state(), p.levels);
|
lua_pop(lua_state(), p.levels);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_valid(std::false_type) {
|
bool is_valid(std::false_type) {
|
||||||
auto pp = stack::push_pop(tbl);
|
auto pp = stack::push_pop(tbl);
|
||||||
auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state()));
|
auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>, global_table>>(lua_state(), key, lua_gettop(lua_state()));
|
||||||
lua_pop(lua_state(), p.levels);
|
lua_pop(lua_state(), p.levels);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
proxy& set(T&& item) {
|
proxy& set(T&& item) {
|
||||||
tuple_set(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>(), std::forward<T>(item));
|
tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,15 +79,16 @@ namespace sol {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, meta::enable<meta::neg<is_lua_reference_or_proxy<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler>
|
template <typename U>
|
||||||
proxy& operator=(U&& other) {
|
proxy& operator=(U&& other) {
|
||||||
|
using uTu = meta::unwrap_unqualified_t<U>;
|
||||||
|
if constexpr (!is_lua_reference_or_proxy_v<uTu> && meta::is_callable_v<uTu>) {
|
||||||
return set_function(std::forward<U>(other));
|
return set_function(std::forward<U>(other));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <typename U, meta::disable<meta::neg<is_lua_reference_or_proxy<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler>
|
|
||||||
proxy& operator=(U&& other) {
|
|
||||||
return set(std::forward<U>(other));
|
return set(std::forward<U>(other));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
proxy& operator=(std::initializer_list<T> other) {
|
proxy& operator=(std::initializer_list<T> other) {
|
||||||
|
@ -193,26 +194,26 @@ namespace sol {
|
||||||
|
|
||||||
template <typename Table, typename Key, typename T>
|
template <typename Table, typename Key, typename T>
|
||||||
inline bool operator==(T&& left, const proxy<Table, Key>& right) {
|
inline bool operator==(T&& left, const proxy<Table, Key>& right) {
|
||||||
typedef decltype(stack::get<T>(nullptr, 0)) U;
|
using G = decltype(stack::get<T>(nullptr, 0));
|
||||||
return right.template get<optional<U>>() == left;
|
return right.template get<optional<G>>() == left;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table, typename Key, typename T>
|
template <typename Table, typename Key, typename T>
|
||||||
inline bool operator==(const proxy<Table, Key>& right, T&& left) {
|
inline bool operator==(const proxy<Table, Key>& right, T&& left) {
|
||||||
typedef decltype(stack::get<T>(nullptr, 0)) U;
|
using G = decltype(stack::get<T>(nullptr, 0));
|
||||||
return right.template get<optional<U>>() == left;
|
return right.template get<optional<G>>() == left;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table, typename Key, typename T>
|
template <typename Table, typename Key, typename T>
|
||||||
inline bool operator!=(T&& left, const proxy<Table, Key>& right) {
|
inline bool operator!=(T&& left, const proxy<Table, Key>& right) {
|
||||||
typedef decltype(stack::get<T>(nullptr, 0)) U;
|
using G = decltype(stack::get<T>(nullptr, 0));
|
||||||
return right.template get<optional<U>>() != left;
|
return right.template get<optional<G>>() != left;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table, typename Key, typename T>
|
template <typename Table, typename Key, typename T>
|
||||||
inline bool operator!=(const proxy<Table, Key>& right, T&& left) {
|
inline bool operator!=(const proxy<Table, Key>& right, T&& left) {
|
||||||
typedef decltype(stack::get<T>(nullptr, 0)) U;
|
using G = decltype(stack::get<T>(nullptr, 0));
|
||||||
return right.template get<optional<U>>() != left;
|
return right.template get<optional<G>>() != left;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table, typename Key>
|
template <typename Table, typename Key>
|
||||||
|
|
|
@ -35,18 +35,7 @@ namespace sol { namespace stack {
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
if (!check<T>(L, index, std::forward<Handler>(handler))) {
|
if constexpr (is_lua_reference_v<T>) {
|
||||||
tracking.use(static_cast<int>(!lua_isnone(L, index)));
|
|
||||||
return nullopt;
|
|
||||||
}
|
|
||||||
return stack_detail::unchecked_get<T>(L, index, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct qualified_check_getter<T, std::enable_if_t<is_lua_reference<T>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
// actually check if it's none here, otherwise
|
// actually check if it's none here, otherwise
|
||||||
// we'll have a none object inside an optional!
|
// we'll have a none object inside an optional!
|
||||||
bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
|
bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
|
||||||
|
@ -58,6 +47,14 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
return stack_detail::unchecked_get<T>(L, index, tracking);
|
return stack_detail::unchecked_get<T>(L, index, tracking);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (!check<T>(L, index, std::forward<Handler>(handler))) {
|
||||||
|
tracking.use(static_cast<int>(!lua_isnone(L, index)));
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
return stack_detail::unchecked_get<T>(L, index, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -45,18 +45,8 @@ namespace stack {
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
|
if constexpr (!meta::meta_detail::is_adl_sol_lua_check_v<T> && !meta::meta_detail::is_adl_sol_lua_get_v<T>) {
|
||||||
tracking.use(static_cast<int>(!lua_isnone(L, index)));
|
if constexpr (is_lua_reference_v<T>) {
|
||||||
return nullopt;
|
|
||||||
}
|
|
||||||
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_check_getter<T, std::enable_if_t<is_lua_reference<T>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
// actually check if it's none here, otherwise
|
// actually check if it's none here, otherwise
|
||||||
// we'll have a none object inside an optional!
|
// we'll have a none object inside an optional!
|
||||||
bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
|
bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, no_panic);
|
||||||
|
@ -68,12 +58,10 @@ namespace stack {
|
||||||
}
|
}
|
||||||
return stack_detail::unchecked_get<T>(L, index, tracking);
|
return stack_detail::unchecked_get<T>(L, index, tracking);
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_same_v<T, bool>) {
|
||||||
|
return lua_toboolean(L, index) != 0;
|
||||||
template <typename T>
|
}
|
||||||
struct unqualified_check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
|
else if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>) {
|
||||||
template <typename Handler>
|
|
||||||
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
#if SOL_LUA_VERSION >= 503
|
#if SOL_LUA_VERSION >= 503
|
||||||
if (lua_isinteger(L, index) != 0) {
|
if (lua_isinteger(L, index) != 0) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
|
@ -99,29 +87,7 @@ namespace stack {
|
||||||
handler(L, index, type::number, t, "not an integer");
|
handler(L, index, type::number, t, "not an integer");
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr(std::is_floating_point_v<T>) {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_check_getter<T, std::enable_if_t<std::is_enum<T>::value && !meta::any_same<T, meta_function, type>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
int isnum = 0;
|
|
||||||
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
|
||||||
if (isnum == 0) {
|
|
||||||
type t = type_of(L, index);
|
|
||||||
tracking.use(static_cast<int>(t != type::none));
|
|
||||||
handler(L, index, type::number, t, "not a valid enumeration value");
|
|
||||||
return nullopt;
|
|
||||||
}
|
|
||||||
tracking.use(1);
|
|
||||||
return static_cast<T>(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
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) {
|
||||||
|
@ -133,12 +99,40 @@ namespace stack {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
return static_cast<T>(value);
|
return static_cast<T>(value);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_enum_v<T> && !meta::any_same_v<T, meta_function, type>) {
|
||||||
|
int isnum = 0;
|
||||||
|
lua_Integer value = lua_tointegerx(L, index, &isnum);
|
||||||
|
if (isnum == 0) {
|
||||||
|
type t = type_of(L, index);
|
||||||
|
tracking.use(static_cast<int>(t != type::none));
|
||||||
|
handler(L, index, type::number, t, "not a valid enumeration value");
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
tracking.use(1);
|
||||||
|
return static_cast<T>(value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
|
||||||
|
tracking.use(static_cast<int>(!lua_isnone(L, index)));
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) {
|
||||||
|
tracking.use(static_cast<int>(!lua_isnone(L, index)));
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_getter<optional<T>> {
|
struct unqualified_getter<optional<T>> {
|
||||||
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||||
return check_get<T>(L, index, no_panic, tracking);
|
return stack::unqualified_check_get<T>(L, index, no_panic, tracking);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,22 +29,15 @@
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace stack {
|
namespace stack {
|
||||||
|
|
||||||
template <typename X>
|
template <typename X, type expected, typename>
|
||||||
struct qualified_checker<X, type::userdata, std::enable_if_t<
|
struct qualified_checker {
|
||||||
is_unique_usertype<X>::value
|
|
||||||
&& !std::is_reference<X>::value
|
|
||||||
>> {
|
|
||||||
typedef unique_usertype_traits<meta::unqualified_t<X>> u_traits;
|
|
||||||
typedef typename u_traits::type T;
|
|
||||||
typedef typename u_traits::template rebind_base<void> rebind_t;
|
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(std::false_type, lua_State* L, int index, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
|
if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<X>) {
|
||||||
}
|
using u_traits = unique_usertype_traits<meta::unqualified_t<X>>;
|
||||||
|
using T = typename u_traits::type;
|
||||||
template <typename Handler>
|
using rebind_t = typename u_traits::template rebind_base<void>;
|
||||||
static bool check(std::true_type, lua_State* L, int index, Handler&& handler, record& tracking) {
|
if constexpr (!std::is_void_v<rebind_t>) {
|
||||||
// we have a unique pointer type that can be
|
// we have a unique pointer type that can be
|
||||||
// rebound to a base/derived type
|
// rebound to a base/derived type
|
||||||
const type indextype = type_of(L, index);
|
const type indextype = type_of(L, index);
|
||||||
|
@ -71,17 +64,11 @@ namespace stack {
|
||||||
handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
|
handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <typename Handler>
|
return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return check(meta::neg<std::is_void<rebind_t>>(), L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
else if constexpr (!std::is_reference_v<X> && is_container_v<X>) {
|
||||||
template <typename X>
|
|
||||||
struct qualified_checker<X, type::userdata, std::enable_if_t<is_container<meta::unqualified_t<X>>::value && !std::is_reference<X>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
if (type_of(L, index) == type::userdata) {
|
if (type_of(L, index) == type::userdata) {
|
||||||
return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
|
return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
|
@ -89,6 +76,10 @@ namespace stack {
|
||||||
return stack::unqualified_check<nested<X>>(L, index, std::forward<Handler>(handler), tracking);
|
return stack::unqualified_check<nested<X>>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace sol::stack
|
} // namespace sol::stack
|
||||||
|
|
|
@ -90,29 +90,16 @@ namespace sol { namespace stack {
|
||||||
struct unqualified_checker {
|
struct unqualified_checker {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
const type indextype = type_of(L, index);
|
bool success = lua_isboolean(L, index) == 1;
|
||||||
bool success = expected == indextype;
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
// expected type, actual type, message
|
// expected type, actual type
|
||||||
handler(L, index, expected, indextype, "");
|
handler(L, index, expected, type_of(L, index), "");
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>) {
|
||||||
|
|
||||||
template <typename T, type expected, typename C>
|
|
||||||
struct qualified_checker {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return stack::unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
#if SOL_LUA_VERSION >= 503
|
#if SOL_LUA_VERSION >= 503
|
||||||
#if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS
|
#if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS
|
||||||
|
@ -170,12 +157,7 @@ namespace sol { namespace stack {
|
||||||
return success;
|
return success;
|
||||||
#endif // Lua Version 5.3 versus others
|
#endif // Lua Version 5.3 versus others
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_floating_point_v<T>) {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
#if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS
|
#if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS
|
||||||
bool success = lua_isnumber(L, index) == 1;
|
bool success = lua_isnumber(L, index) == 1;
|
||||||
|
@ -194,12 +176,50 @@ namespace sol { namespace stack {
|
||||||
return success;
|
return success;
|
||||||
#endif // Strings are Numbers
|
#endif // Strings are Numbers
|
||||||
}
|
}
|
||||||
};
|
else if constexpr(meta::any_same_v<T, type, this_state, this_main_state, this_environment, variadic_args>) {
|
||||||
|
tracking.use(0);
|
||||||
template <type expected, typename C>
|
return true;
|
||||||
struct unqualified_checker<lua_nil_t, expected, C> {
|
}
|
||||||
template <typename Handler>
|
else if constexpr (is_unique_usertype_v<T>) {
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
using proper_T = typename unique_usertype_traits<T>::type;
|
||||||
|
const type indextype = type_of(L, index);
|
||||||
|
tracking.use(1);
|
||||||
|
if (indextype != type::userdata) {
|
||||||
|
handler(L, index, type::userdata, indextype, "value is not a userdata");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int metatableindex = lua_gettop(L);
|
||||||
|
if (stack_detail::check_metatable<detail::unique_usertype<proper_T>>(L, metatableindex)) {
|
||||||
|
void* memory = lua_touserdata(L, index);
|
||||||
|
memory = detail::align_usertype_unique_destructor(memory);
|
||||||
|
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
|
||||||
|
bool success = &detail::usertype_unique_alloc_destroy<proper_T, T> == pdx;
|
||||||
|
if (!success) {
|
||||||
|
memory = detail::align_usertype_unique_tag<true>(memory);
|
||||||
|
#if 0
|
||||||
|
// New version
|
||||||
|
#else
|
||||||
|
const char*& name_tag = *static_cast<const char**>(memory);
|
||||||
|
success = usertype_traits<T>::qualified_name() == name_tag;
|
||||||
|
#endif
|
||||||
|
if (!success) {
|
||||||
|
handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
handler(L, index, type::userdata, indextype, "unrecognized userdata (not pushed by sol?)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if constexpr (meta::any_same_v<T, lua_nil_t,
|
||||||
|
#if defined(SOL_CXX_17_FEATURES) && SOL_CXX_17_FEATURES
|
||||||
|
std::nullopt_t,
|
||||||
|
#endif
|
||||||
|
nullopt_t>) {
|
||||||
bool success = lua_isnil(L, index);
|
bool success = lua_isnil(L, index);
|
||||||
if (success) {
|
if (success) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
|
@ -213,97 +233,54 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_same_v<T, env_key_t>) {
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct unqualified_checker<detail::non_lua_nil_t, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return !stack::unqualified_check<lua_nil_t>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <type expected, typename C>
|
|
||||||
struct unqualified_checker<nullopt_t, expected, C> : unqualified_checker<lua_nil_t> {};
|
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct unqualified_checker<this_state, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State*, int, Handler&&, record& tracking) {
|
|
||||||
tracking.use(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct unqualified_checker<this_main_state, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State*, int, Handler&&, record& tracking) {
|
|
||||||
tracking.use(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct unqualified_checker<this_environment, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State*, int, Handler&&, record& tracking) {
|
|
||||||
tracking.use(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct unqualified_checker<variadic_args, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State*, int, Handler&&, record& tracking) {
|
|
||||||
tracking.use(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename C>
|
|
||||||
struct unqualified_checker<type, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State*, int, Handler&&, record& tracking) {
|
|
||||||
tracking.use(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<T, type::poly, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
|
||||||
bool success = is_lua_reference<T>::value || !lua_isnone(L, index);
|
|
||||||
if (!success) {
|
|
||||||
// expected type, actual type
|
|
||||||
handler(L, index, type::poly, type_of(L, index), "");
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<T, type::lightuserdata, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
type t = type_of(L, index);
|
type t = type_of(L, index);
|
||||||
bool success = t == type::userdata || t == type::lightuserdata;
|
if (t == type::table || t == type::none || t == type::lua_nil || t == type::userdata) {
|
||||||
if (!success) {
|
return true;
|
||||||
// expected type, actual type
|
|
||||||
handler(L, index, type::lightuserdata, t, "");
|
|
||||||
}
|
}
|
||||||
return success;
|
handler(L, index, type::table, t, "value cannot not have a valid environment");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_same_v<T, detail::non_lua_nil_t>) {
|
||||||
|
return !stack::unqualified_check<lua_nil_t>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
template <typename C>
|
}
|
||||||
struct unqualified_checker<userdata_value, type::userdata, C> {
|
else if constexpr(meta::is_specialization_of_v<T, basic_environment>) {
|
||||||
template <typename Handler>
|
tracking.use(1);
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
type t = type_of(L, -1);
|
||||||
|
if (t == type::table || t == type::none || t == type::lua_nil) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (t != type::userdata) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
handler(L, index, type::table, t, "value does not have a valid metatable");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, metatable_key_t>) {
|
||||||
|
tracking.use(1);
|
||||||
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
type t = type_of(L, -1);
|
||||||
|
if (t == type::table || t == type::none || t == type::lua_nil) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (t != type::userdata) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
handler(L, index, expected, t, "value does not have a valid metatable");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if constexpr (expected == type::userdata) {
|
||||||
|
if constexpr (meta::any_same_v<T, userdata_value> || meta::is_specialization_of_v<T, basic_userdata>) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
type t = type_of(L, index);
|
type t = type_of(L, index);
|
||||||
bool success = t == type::userdata;
|
bool success = t == type::userdata;
|
||||||
|
@ -313,33 +290,54 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (meta::is_specialization_of_v<T, user>) {
|
||||||
|
unqualified_checker<lightuserdata_value> c;
|
||||||
template <typename B, typename C>
|
(void)c;
|
||||||
struct unqualified_checker<basic_userdata<B>, type::userdata, C> {
|
return c.check(L, index, std::forward<Handler>(handler), tracking);
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return stack::check<userdata_value>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
}
|
||||||
};
|
else {
|
||||||
|
if constexpr (std::is_pointer_v<T>) {
|
||||||
template <typename T, typename C>
|
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
struct unqualified_checker<user<T>, type::userdata, C> : unqualified_checker<user<T>, type::lightuserdata, C> {};
|
}
|
||||||
|
else if constexpr (meta::is_specialization_of_v<T, std::reference_wrapper>) {
|
||||||
template <typename T, typename C>
|
using T_internal = typename T::type;
|
||||||
struct unqualified_checker<non_null<T>, type::userdata, C> : unqualified_checker<T, lua_type_of<T>::value, C> {};
|
return stack::check<T_internal>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
template <typename C>
|
else {
|
||||||
struct unqualified_checker<lua_CFunction, type::function, C> : stack_detail::basic_check<type::function, lua_iscfunction> {};
|
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
template <typename C>
|
}
|
||||||
struct unqualified_checker<std::remove_pointer_t<lua_CFunction>, type::function, C> : unqualified_checker<lua_CFunction, type::function, C> {};
|
}
|
||||||
template <typename C>
|
}
|
||||||
struct unqualified_checker<c_closure, type::function, C> : unqualified_checker<lua_CFunction, type::function, C> {};
|
else if constexpr (expected == type::poly) {
|
||||||
|
tracking.use(1);
|
||||||
template <typename T, typename C>
|
bool success = is_lua_reference_v<T> || !lua_isnone(L, index);
|
||||||
struct unqualified_checker<T, type::function, C> {
|
if (!success) {
|
||||||
template <typename Handler>
|
// expected type, actual type
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
handler(L, index, type::poly, type_of(L, index), "");
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
else if constexpr (expected == type::lightuserdata) {
|
||||||
|
tracking.use(1);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else if constexpr (expected == type::function) {
|
||||||
|
if constexpr (meta::any_same_v<T, lua_CFunction, std::remove_pointer_t<lua_CFunction>, c_closure>) {
|
||||||
|
tracking.use(1);
|
||||||
|
bool success = lua_iscfunction(L, index) == 1;
|
||||||
|
if (!success) {
|
||||||
|
// expected type, actual type
|
||||||
|
handler(L, index, expected, type_of(L, index), "");
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
else {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
type t = type_of(L, index);
|
type t = type_of(L, index);
|
||||||
if (t == type::lua_nil || t == type::none || t == type::function) {
|
if (t == type::lua_nil || t == type::none || t == type::function) {
|
||||||
|
@ -372,12 +370,8 @@ namespace sol { namespace stack {
|
||||||
lua_pop(L, 2);
|
lua_pop(L, 2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
else if constexpr (expected == type::table) {
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<T, type::table, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
type t = type_of(L, index);
|
type t = type_of(L, index);
|
||||||
if (t == type::table) {
|
if (t == type::table) {
|
||||||
|
@ -389,68 +383,24 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
else {
|
||||||
|
|
||||||
template <type expected, typename C>
|
|
||||||
struct unqualified_checker<metatable_key_t, expected, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
const type indextype = type_of(L, index);
|
||||||
return true;
|
bool success = expected == indextype;
|
||||||
|
if (!success) {
|
||||||
|
// expected type, actual type, message
|
||||||
|
handler(L, index, expected, indextype, "");
|
||||||
}
|
}
|
||||||
type t = type_of(L, -1);
|
return success;
|
||||||
if (t == type::table || t == type::none || t == type::lua_nil) {
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (t != type::userdata) {
|
|
||||||
lua_pop(L, 1);
|
|
||||||
handler(L, index, expected, t, "value does not have a valid metatable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename C>
|
template <typename T>
|
||||||
struct unqualified_checker<env_key_t, type::poly, C> {
|
struct unqualified_checker<non_null<T>, type::userdata> : unqualified_checker<T, lua_type_of_v<T>> {};
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
|
||||||
type t = type_of(L, index);
|
|
||||||
if (t == type::table || t == type::none || t == type::lua_nil || t == type::userdata) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
handler(L, index, type::table, t, "value cannot not have a valid environment");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename E, typename C>
|
template <typename T>
|
||||||
struct unqualified_checker<basic_environment<E>, type::poly, C> {
|
struct unqualified_checker<detail::as_value_tag<T>, type::userdata> {
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
tracking.use(1);
|
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
type t = type_of(L, -1);
|
|
||||||
if (t == type::table || t == type::none || t == type::lua_nil) {
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (t != type::userdata) {
|
|
||||||
lua_pop(L, 1);
|
|
||||||
handler(L, index, type::table, t, "value does not have a valid metatable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<detail::as_value_tag<T>, type::userdata, C> {
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
const type indextype = type_of(L, index);
|
const type indextype = type_of(L, index);
|
||||||
|
@ -507,8 +457,8 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename T>
|
||||||
struct unqualified_checker<detail::as_pointer_tag<T>, type::userdata, C> {
|
struct unqualified_checker<detail::as_pointer_tag<T>, type::userdata> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||||
if (indextype == type::lua_nil) {
|
if (indextype == type::lua_nil) {
|
||||||
|
@ -525,88 +475,24 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename... Args>
|
||||||
struct unqualified_checker<T, type::userdata, C> {
|
struct unqualified_checker<std::tuple<Args...>, type::poly> {
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<T*, type::userdata, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return check_usertype<T*>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename X>
|
|
||||||
struct unqualified_checker<X, type::userdata, std::enable_if_t<is_unique_usertype<X>::value>> {
|
|
||||||
typedef typename unique_usertype_traits<X>::type T;
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
const type indextype = type_of(L, index);
|
|
||||||
tracking.use(1);
|
|
||||||
if (indextype != type::userdata) {
|
|
||||||
handler(L, index, type::userdata, indextype, "value is not a userdata");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int metatableindex = lua_gettop(L);
|
|
||||||
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex)) {
|
|
||||||
void* memory = lua_touserdata(L, index);
|
|
||||||
memory = detail::align_usertype_unique_destructor(memory);
|
|
||||||
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
|
|
||||||
bool success = &detail::usertype_unique_alloc_destroy<T, X> == pdx;
|
|
||||||
if (!success) {
|
|
||||||
memory = detail::align_usertype_unique_tag<true>(memory);
|
|
||||||
#if 0
|
|
||||||
// New version
|
|
||||||
#else
|
|
||||||
const char*& name_tag = *static_cast<const char**>(memory);
|
|
||||||
success = usertype_traits<X>::qualified_name() == name_tag;
|
|
||||||
#endif
|
|
||||||
if (!success) {
|
|
||||||
handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
handler(L, index, type::userdata, indextype, "unrecognized userdata (not pushed by sol?)");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<std::reference_wrapper<T>, type::userdata, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return stack::check<T>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args, typename C>
|
|
||||||
struct unqualified_checker<std::tuple<Args...>, type::poly, C> {
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
return stack::multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking);
|
return stack::multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, typename B, typename C>
|
template <typename A, typename B>
|
||||||
struct unqualified_checker<std::pair<A, B>, type::poly, C> {
|
struct unqualified_checker<std::pair<A, B>, type::poly> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
return stack::multi_check<A, B>(L, index, std::forward<Handler>(handler), tracking);
|
return stack::multi_check<A, B>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename T>
|
||||||
struct unqualified_checker<optional<T>, type::poly, C> {
|
struct unqualified_checker<optional<T>, type::poly> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&&, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&&, record& tracking) {
|
||||||
type t = type_of(L, index);
|
type t = type_of(L, index);
|
||||||
|
@ -618,14 +504,14 @@ namespace sol { namespace stack {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return stack::check<T>(L, index, no_panic, tracking);
|
return stack::unqualified_check<T>(L, index, no_panic, tracking);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename T>
|
||||||
struct unqualified_checker<std::optional<T>, type::poly, C> {
|
struct unqualified_checker<std::optional<T>, type::poly> {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&&, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&&, record& tracking) {
|
||||||
type t = type_of(L, index);
|
type t = type_of(L, index);
|
||||||
|
@ -643,8 +529,8 @@ namespace sol { namespace stack {
|
||||||
|
|
||||||
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
|
||||||
|
|
||||||
template <typename... Tn, typename C>
|
template <typename... Tn>
|
||||||
struct unqualified_checker<std::variant<Tn...>, type::poly, C> {
|
struct unqualified_checker<std::variant<Tn...>, type::poly> {
|
||||||
typedef std::variant<Tn...> V;
|
typedef std::variant<Tn...> V;
|
||||||
typedef std::variant_size<V> V_size;
|
typedef std::variant_size<V> V_size;
|
||||||
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
|
typedef std::integral_constant<bool, V_size::value == 0> V_is_empty;
|
||||||
|
|
|
@ -594,15 +594,11 @@ namespace sol {
|
||||||
struct popper;
|
struct popper;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct unqualified_pusher;
|
struct unqualified_pusher;
|
||||||
template <typename T, type = lua_type_of<T>::value, typename = void>
|
template <typename X, type t = lua_type_of_v<X>, typename C = void>
|
||||||
struct unqualified_checker;
|
struct unqualified_checker;
|
||||||
template <typename T, type = lua_type_of<T>::value, typename = void>
|
template <typename X, type t = lua_type_of_v<X>, typename C = void>
|
||||||
struct qualified_checker;
|
struct qualified_checker;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct qualified_interop_checker;
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct unqualified_interop_checker;
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct unqualified_check_getter;
|
struct unqualified_check_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct qualified_check_getter;
|
struct qualified_check_getter;
|
||||||
|
@ -634,116 +630,50 @@ namespace sol {
|
||||||
} // namespace stack
|
} // namespace stack
|
||||||
|
|
||||||
namespace meta { namespace meta_detail {
|
namespace meta { namespace meta_detail {
|
||||||
template <typename T>
|
|
||||||
struct is_adl_sol_lua_get {
|
|
||||||
private:
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_yes_t test(
|
|
||||||
std::remove_reference_t<decltype(sol_lua_get(types<C>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>()))>*);
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_adl_sol_lua_interop_get {
|
using adl_sol_lua_get_test_t = decltype(sol_lua_get(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>()));
|
||||||
private:
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_yes_t test(
|
|
||||||
std::remove_reference_t<decltype(sol_lua_interop_get(types<C>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>()))>*);
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_adl_sol_lua_check {
|
using adl_sol_lua_interop_get_test_t
|
||||||
private:
|
= decltype(sol_lua_interop_get(types<T>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>()));
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_yes_t test(std::remove_reference_t<decltype(
|
|
||||||
sol_lua_check(types<C>(), static_cast<lua_State*>(nullptr), -1, no_panic, std::declval<stack::record&>()))>*);
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_adl_sol_lua_interop_check {
|
using adl_sol_lua_check_test_t = decltype(sol_lua_check(types<T>(), static_cast<lua_State*>(nullptr), -1, no_panic, std::declval<stack::record&>()));
|
||||||
private:
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_yes_t test(std::remove_reference_t<decltype(
|
|
||||||
sol_lua_interop_check(types<C>(), static_cast<lua_State*>(nullptr), -1, type::none, no_panic, std::declval<stack::record&>()))>*);
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_adl_sol_lua_check_get {
|
using adl_sol_lua_interop_check_test_t
|
||||||
private:
|
= decltype(sol_lua_interop_check(types<T>(), static_cast<lua_State*>(nullptr), -1, type::none, no_panic, std::declval<stack::record&>()));
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_yes_t test(std::remove_reference_t<decltype(
|
|
||||||
sol_lua_check_get(types<C>(), static_cast<lua_State*>(nullptr), -1, no_panic, std::declval<stack::record&>()))>*);
|
|
||||||
template <typename C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
template <typename T>
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
using adl_sol_lua_check_get_test_t = decltype(sol_lua_check_get(types<T>(), static_cast<lua_State*>(nullptr), -1, no_panic, std::declval<stack::record&>()));
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
struct is_adl_sol_lua_push {
|
using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast<lua_State*>(nullptr), std::declval<Args>()...));
|
||||||
private:
|
|
||||||
template <typename... C>
|
|
||||||
static meta::sfinae_yes_t test(std::remove_reference_t<decltype(sol_lua_push(static_cast<lua_State*>(nullptr), std::declval<C>()...))>*);
|
|
||||||
template <typename... C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<Args...>(nullptr)), meta::sfinae_yes_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
struct is_adl_sol_lua_push_exact {
|
using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(types<T>(), static_cast<lua_State*>(nullptr), std::declval<Args>()...));
|
||||||
private:
|
|
||||||
template <typename... C>
|
|
||||||
static meta::sfinae_yes_t test(
|
|
||||||
std::remove_reference_t<decltype(sol_lua_push(types<T>(), static_cast<lua_State*>(nullptr), std::declval<C>()...))>*);
|
|
||||||
template <typename... C>
|
|
||||||
static meta::sfinae_no_t test(...);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<Args...>(nullptr)), meta::sfinae_yes_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_adl_sol_lua_get_v = is_adl_sol_lua_get<T>::value;
|
inline constexpr bool is_adl_sol_lua_get_v = meta::is_detected_v<adl_sol_lua_get_test_t, T>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_adl_sol_lua_interop_get_v = is_adl_sol_lua_interop_get<T>::value;
|
inline constexpr bool is_adl_sol_lua_interop_get_v = meta::is_detected_v<adl_sol_lua_interop_get_test_t, T>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_adl_sol_lua_check_v = is_adl_sol_lua_check<T>::value;
|
inline constexpr bool is_adl_sol_lua_check_v = meta::is_detected_v<adl_sol_lua_check_test_t, T>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_adl_sol_lua_interop_check_v = is_adl_sol_lua_interop_check<T>::value;
|
inline constexpr bool is_adl_sol_lua_interop_check_v = meta::is_detected_v<adl_sol_lua_interop_check_test_t, T>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_adl_sol_lua_check_get_v = is_adl_sol_lua_check_get<T>::value;
|
inline constexpr bool is_adl_sol_lua_check_get_v = meta::is_detected_v<adl_sol_lua_check_get_test_t, T>;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
inline constexpr bool is_adl_sol_lua_push_v = is_adl_sol_lua_push<Args...>::value;
|
inline constexpr bool is_adl_sol_lua_push_v = meta::is_detected_v<adl_sol_lua_push_test_t, Args...>;
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
inline constexpr bool is_adl_sol_lua_push_exact_v = is_adl_sol_lua_push_exact<T, Args...>::value;
|
inline constexpr bool is_adl_sol_lua_push_exact_v = meta::is_detected_v<adl_sol_lua_push_exact_test_t, T, Args...>;
|
||||||
}} // namespace meta::meta_detail
|
}} // namespace meta::meta_detail
|
||||||
|
|
||||||
|
|
||||||
|
@ -791,7 +721,7 @@ namespace sol {
|
||||||
using strip_extensible_t = typename strip_extensible<T>::type;
|
using strip_extensible_t = typename strip_extensible<T>::type;
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
static int get_size_hint(const C& c) {
|
static int get_size_hint(C& c) {
|
||||||
return static_cast<int>(c.size());
|
return static_cast<int>(c.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,9 +763,12 @@ namespace sol {
|
||||||
return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
|
return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unqualified_interop_getter<Tu> g{};
|
(void)L;
|
||||||
(void)g;
|
(void)index;
|
||||||
return g.get(L, index, unadjusted_pointer, tracking);
|
(void)unadjusted_pointer;
|
||||||
|
(void)tracking;
|
||||||
|
using Ti = stack_detail::strip_extensible_t<Tu>;
|
||||||
|
return std::pair<bool, Ti*>{ false, nullptr };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,9 +778,7 @@ namespace sol {
|
||||||
return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
|
return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qualified_interop_getter<T> g{};
|
return unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
|
||||||
(void)g;
|
|
||||||
return g.get(L, index, unadjusted_pointer, tracking);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,10 +789,12 @@ namespace sol {
|
||||||
return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unqualified_interop_checker<Tu> c;
|
(void)L;
|
||||||
// VC++ has a bad warning here: shut it up
|
(void)index;
|
||||||
(void)c;
|
(void)index_type;
|
||||||
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
|
(void)handler;
|
||||||
|
(void)tracking;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,10 +804,7 @@ namespace sol {
|
||||||
return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qualified_interop_checker<T> c;
|
return unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
// VC++ has a bad warning here: shut it up
|
|
||||||
(void)c;
|
|
||||||
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace stack_detail
|
} // namespace stack_detail
|
||||||
|
@ -1435,11 +1365,11 @@ namespace sol {
|
||||||
return stack::push(L, false);
|
return stack::push(L, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto maybel = stack::unqualified_check_get<T&>(L, 1);
|
auto maybel = stack::unqualified_check_get<T>(L, 1);
|
||||||
if (!maybel) {
|
if (!maybel) {
|
||||||
return stack::push(L, false);
|
return stack::push(L, false);
|
||||||
}
|
}
|
||||||
auto mayber = stack::unqualified_check_get<T&>(L, 2);
|
auto mayber = stack::unqualified_check_get<T>(L, 2);
|
||||||
if (!mayber) {
|
if (!mayber) {
|
||||||
return stack::push(L, false);
|
return stack::push(L, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,78 +29,6 @@
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace stack {
|
namespace stack {
|
||||||
|
|
||||||
template <typename X>
|
|
||||||
struct qualified_getter<X, std::enable_if_t<
|
|
||||||
!std::is_reference<X>::value
|
|
||||||
&& is_unique_usertype<meta::unqualified_t<X>>::value
|
|
||||||
&& !std::is_void<typename unique_usertype_traits<meta::unqualified_t<X>>::template rebind_base<void>>::value
|
|
||||||
>> {
|
|
||||||
typedef unique_usertype_traits<meta::unqualified_t<X>> u_traits;
|
|
||||||
typedef typename u_traits::type T;
|
|
||||||
typedef typename u_traits::actual_type Real;
|
|
||||||
typedef typename u_traits::template rebind_base<void> rebind_t;
|
|
||||||
|
|
||||||
static Real get(lua_State* L, int index, record& tracking) {
|
|
||||||
tracking.use(1);
|
|
||||||
void* memory = lua_touserdata(L, index);
|
|
||||||
memory = detail::align_usertype_unique_destructor(memory);
|
|
||||||
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
|
|
||||||
if (&detail::usertype_unique_alloc_destroy<T, X> == pdx) {
|
|
||||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
|
||||||
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
|
||||||
Real* mem = static_cast<Real*>(memory);
|
|
||||||
return *mem;
|
|
||||||
}
|
|
||||||
Real r(nullptr);
|
|
||||||
if constexpr (!derive<T>::value) {
|
|
||||||
// TODO: abort / terminate, maybe only in debug modes?
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
|
||||||
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
|
||||||
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
|
||||||
string_view ti = usertype_traits<T>::qualified_name();
|
|
||||||
string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
|
||||||
int cast_operation = ic(memory, &r, ti, rebind_ti);
|
|
||||||
switch (cast_operation) {
|
|
||||||
case 1: {
|
|
||||||
// it's a perfect match,
|
|
||||||
// alias memory directly
|
|
||||||
Real* mem = static_cast<Real*>(memory);
|
|
||||||
return *mem;
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
// it's a base match, return the
|
|
||||||
// aliased creation
|
|
||||||
return std::move(r);
|
|
||||||
default:
|
|
||||||
// uh oh..
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO: abort / terminate, maybe only in debug modes?
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct qualified_getter<T, std::enable_if_t<
|
|
||||||
!std::is_reference<T>::value
|
|
||||||
&& is_container<meta::unqualified_t<T>>::value
|
|
||||||
&& std::is_default_constructible<meta::unqualified_t<T>>::value
|
|
||||||
&& !is_lua_primitive<T>::value
|
|
||||||
&& !is_transparent_argument<T>::value
|
|
||||||
>> {
|
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
|
||||||
if (type_of(L, index) == type::userdata) {
|
|
||||||
return stack_detail::unchecked_unqualified_get<T>(L, index, tracking);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return stack_detail::unchecked_unqualified_get<sol::nested<T>>(L, index, tracking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} // namespace sol::stack
|
} // namespace sol::stack
|
||||||
|
|
||||||
|
|
|
@ -118,45 +118,16 @@ namespace sol { namespace stack {
|
||||||
|
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct unqualified_getter {
|
struct unqualified_getter {
|
||||||
static T& get(lua_State* L, int index, record& tracking) {
|
|
||||||
return unqualified_getter<detail::as_value_tag<T>>{}.get(L, index, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct qualified_getter {
|
|
||||||
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||||
return stack::unqualified_get<T>(L, index, tracking);
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename U, typename>
|
|
||||||
struct unqualified_interop_getter {
|
|
||||||
using T = stack_detail::strip_extensible_t<U>;
|
|
||||||
|
|
||||||
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
|
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename>
|
|
||||||
struct qualified_interop_getter {
|
|
||||||
static decltype(auto) get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
|
|
||||||
return stack_detail::unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
return static_cast<T>(lua_tonumber(L, index));
|
return lua_toboolean(L, index) != 0;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_enum_v<T>) {
|
||||||
|
tracking.use(1);
|
||||||
template <typename T>
|
return static_cast<T>(lua_tointegerx(L, index, nullptr));
|
||||||
struct unqualified_getter<T, std::enable_if_t<std::is_integral<T>::value>> {
|
}
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
else if constexpr (std::is_integral_v<T>) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
#if SOL_LUA_VERSION >= 503
|
#if SOL_LUA_VERSION >= 503
|
||||||
if (lua_isinteger(L, index) != 0) {
|
if (lua_isinteger(L, index) != 0) {
|
||||||
|
@ -165,13 +136,92 @@ namespace sol { namespace stack {
|
||||||
#endif
|
#endif
|
||||||
return static_cast<T>(llround(lua_tonumber(L, index)));
|
return static_cast<T>(llround(lua_tonumber(L, index)));
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_floating_point_v<T>) {
|
||||||
|
tracking.use(1);
|
||||||
|
return static_cast<T>(lua_tonumber(L, index));
|
||||||
|
}
|
||||||
|
else if constexpr (is_lua_reference_v<T>) {
|
||||||
|
tracking.use(1);
|
||||||
|
return T(L, index);
|
||||||
|
}
|
||||||
|
else if constexpr (is_unique_usertype_v<T>) {
|
||||||
|
using Real = typename unique_usertype_traits<T>::actual_type;
|
||||||
|
|
||||||
|
tracking.use(1);
|
||||||
|
void* memory = lua_touserdata(L, index);
|
||||||
|
memory = detail::align_usertype_unique<Real>(memory);
|
||||||
|
Real* mem = static_cast<Real*>(memory);
|
||||||
|
return *mem;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename X, typename>
|
||||||
struct unqualified_getter<T, std::enable_if_t<std::is_enum<T>::value>> {
|
struct qualified_getter {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<X>;
|
||||||
|
if constexpr (!std::is_reference_v<X> && is_container_v<Tu>
|
||||||
|
&& std::is_default_constructible_v<Tu> && !is_lua_primitive_v<Tu> && !is_transparent_argument_v<Tu>) {
|
||||||
|
if (type_of(L, index) == type::userdata) {
|
||||||
|
return static_cast<Tu>(stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu>
|
||||||
|
&& !std::is_void_v<typename unique_usertype_traits<Tu>::template rebind_base<void>>) {
|
||||||
|
using u_traits = unique_usertype_traits<Tu>;
|
||||||
|
using T = typename u_traits::type;
|
||||||
|
using Real = typename u_traits::actual_type;
|
||||||
|
using rebind_t = typename u_traits::template rebind_base<void>;
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
return static_cast<T>(lua_tointegerx(L, index, nullptr));
|
void* memory = lua_touserdata(L, index);
|
||||||
|
memory = detail::align_usertype_unique_destructor(memory);
|
||||||
|
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
|
||||||
|
if (&detail::usertype_unique_alloc_destroy<T, X> == pdx) {
|
||||||
|
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||||
|
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
||||||
|
Real* mem = static_cast<Real*>(memory);
|
||||||
|
return static_cast<Real>(*mem);
|
||||||
|
}
|
||||||
|
Real r(nullptr);
|
||||||
|
if constexpr (!derive<T>::value) {
|
||||||
|
// TODO: abort / terminate, maybe only in debug modes?
|
||||||
|
return static_cast<Real>(r);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||||
|
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
||||||
|
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
||||||
|
string_view ti = usertype_traits<T>::qualified_name();
|
||||||
|
string_view rebind_ti = usertype_traits<rebind_t>::qualified_name();
|
||||||
|
int cast_operation = ic(memory, &r, ti, rebind_ti);
|
||||||
|
switch (cast_operation) {
|
||||||
|
case 1: {
|
||||||
|
// it's a perfect match,
|
||||||
|
// alias memory directly
|
||||||
|
Real* mem = static_cast<Real*>(memory);
|
||||||
|
return static_cast<Real>(*mem);
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
// it's a base match, return the
|
||||||
|
// aliased creation
|
||||||
|
return static_cast<Real>(std::move(r));
|
||||||
|
default:
|
||||||
|
// uh oh..
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// TODO: abort / terminate, maybe only in debug modes?
|
||||||
|
return static_cast<Real>(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack::unqualified_get<Tu>(L, index, tracking);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -487,20 +537,10 @@ namespace sol { namespace stack {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_getter<nested<T>, std::enable_if_t<!is_container<T>::value>> {
|
struct unqualified_getter<nested<T>> {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static T get(lua_State* L, int index, record& tracking) {
|
||||||
unqualified_getter<T> g;
|
|
||||||
// VC++ has a bad warning here: shut it up
|
|
||||||
(void)g;
|
|
||||||
return g.get(L, index, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_getter<nested<T>, std::enable_if_t<is_container<T>::value>> {
|
|
||||||
using Tu = meta::unqualified_t<T>;
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (is_container_v<Tu>) {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
|
||||||
if constexpr (meta::is_associative<Tu>::value) {
|
if constexpr (meta::is_associative<Tu>::value) {
|
||||||
typedef typename T::value_type P;
|
typedef typename T::value_type P;
|
||||||
typedef typename P::first_type K;
|
typedef typename P::first_type K;
|
||||||
|
@ -518,13 +558,26 @@ namespace sol { namespace stack {
|
||||||
return g.get(types<nested<V>>(), L, index, tracking);
|
return g.get(types<nested<V>>(), L, index, tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
unqualified_getter<Tu> g;
|
||||||
|
// VC++ has a bad warning here: shut it up
|
||||||
|
(void)g;
|
||||||
|
return g.get(L, index, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_getter<T, std::enable_if_t<is_lua_reference<T>::value>> {
|
struct unqualified_getter<as_container_t<T>> {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||||
tracking.use(1);
|
return stack::unqualified_get<T>(L, index, tracking);
|
||||||
return T(L, index);
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct unqualified_getter<as_container_t<T>*> {
|
||||||
|
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
||||||
|
return stack::unqualified_get<T*>(L, index, tracking);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -581,14 +634,6 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct unqualified_getter<bool> {
|
|
||||||
static bool get(lua_State* L, int index, record& tracking) {
|
|
||||||
tracking.use(1);
|
|
||||||
return lua_toboolean(L, index) != 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct unqualified_getter<std::string> {
|
struct unqualified_getter<std::string> {
|
||||||
static std::string get(lua_State* L, int index, record& tracking) {
|
static std::string get(lua_State* L, int index, record& tracking) {
|
||||||
|
@ -894,20 +939,6 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_getter<T, std::enable_if_t<is_unique_usertype<T>::value>> {
|
|
||||||
typedef typename unique_usertype_traits<T>::type P;
|
|
||||||
typedef typename unique_usertype_traits<T>::actual_type Real;
|
|
||||||
|
|
||||||
static Real& get(lua_State* L, int index, record& tracking) {
|
|
||||||
tracking.use(1);
|
|
||||||
void* memory = lua_touserdata(L, index);
|
|
||||||
memory = detail::align_usertype_unique<Real>(memory);
|
|
||||||
Real* mem = static_cast<Real*>(memory);
|
|
||||||
return *mem;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Tn>
|
template <typename... Tn>
|
||||||
struct unqualified_getter<std::tuple<Tn...>> {
|
struct unqualified_getter<std::tuple<Tn...>> {
|
||||||
typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R;
|
typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R;
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace sol {
|
||||||
namespace stack_detail {
|
namespace stack_detail {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool integer_value_fits(const T& value) {
|
inline bool integer_value_fits(const T& value) {
|
||||||
if constexpr (sizeof(T) < sizeof(lua_Integer) || (std::is_signed<T>::value && sizeof(T) == sizeof(lua_Integer))) {
|
if constexpr (sizeof(T) < sizeof(lua_Integer) || (std::is_signed_v<T> && sizeof(T) == sizeof(lua_Integer))) {
|
||||||
(void)value;
|
(void)value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,21 @@ namespace sol {
|
||||||
return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max));
|
return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int msvc_is_ass_with_if_constexpr_push_enum(std::true_type, lua_State* L, const T& value) {
|
||||||
|
if constexpr (std::is_same_v<std::underlying_type_t<T>, char>) {
|
||||||
|
return stack::push(L, static_cast<int>(value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack::push(L, static_cast<std::underlying_type_t<T>>(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int msvc_is_ass_with_if_constexpr_push_enum(std::false_type, lua_State*, const T&) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int push_environment_of(lua_State* L, int index = -1) {
|
inline int push_environment_of(lua_State* L, int index = -1) {
|
||||||
|
@ -112,19 +127,19 @@ namespace sol {
|
||||||
return push_fx(L, fx, std::forward<Args>(args)...);
|
return push_fx(L, fx, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>>>
|
template <typename Arg, typename... Args>
|
||||||
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
|
if constexpr (std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>) {
|
||||||
|
return push_fx(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...);
|
return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int push(lua_State* L) {
|
static int push(lua_State* L) {
|
||||||
return push_keyed(L, usertype_traits<T>::metatable());
|
return push_keyed(L, usertype_traits<T>::metatable());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
static int push(lua_State* L, detail::with_function_tag, Args&&... args) {
|
|
||||||
return push_fx(L, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -150,14 +165,14 @@ namespace sol {
|
||||||
return push_fx(L, fx, obj);
|
return push_fx(L, fx, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>>>
|
template <typename Arg, typename... Args>
|
||||||
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
|
if constexpr (std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>) {
|
||||||
|
return push_fx(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return push_keyed(L, usertype_traits<U*>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...);
|
return push_keyed(L, usertype_traits<U*>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
static int push(lua_State* L, detail::with_function_tag, Args&&... args) {
|
|
||||||
return push_fx(L, std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,42 +184,25 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename>
|
namespace stack_detail {
|
||||||
struct unqualified_pusher {
|
|
||||||
template <typename... Args>
|
|
||||||
static int push(lua_State* L, Args&&... args) {
|
|
||||||
return stack::push<detail::as_value_tag<T>>(L, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<T*,
|
struct uu_pusher {
|
||||||
meta::disable_if_t<meta::any<is_container<meta::unqualified_t<T>>, std::is_function<meta::unqualified_t<T>>,
|
using u_traits = unique_usertype_traits<T>;
|
||||||
is_lua_reference<meta::unqualified_t<T>>>::value>> {
|
using P = typename u_traits::type;
|
||||||
template <typename... Args>
|
using Real = typename u_traits::actual_type;
|
||||||
static int push(lua_State* L, Args&&... args) {
|
using rebind_t = typename u_traits::template rebind_base<void>;
|
||||||
return stack::push<detail::as_pointer_tag<T>>(L, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename Arg, typename... Args>
|
||||||
struct unqualified_pusher<T, std::enable_if_t<is_unique_usertype<T>::value>> {
|
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
typedef unique_usertype_traits<T> u_traits;
|
if constexpr (std::is_base_of_v<Real, meta::unqualified_t<Arg>>) {
|
||||||
typedef typename u_traits::type P;
|
if (u_traits::is_null(arg)) {
|
||||||
typedef typename u_traits::actual_type Real;
|
|
||||||
typedef typename u_traits::template rebind_base<void> rebind_t;
|
|
||||||
|
|
||||||
template <typename Arg, meta::enable<std::is_base_of<Real, meta::unqualified_t<Arg>>> = meta::enabler>
|
|
||||||
static int push(lua_State* L, Arg&& arg) {
|
|
||||||
if (unique_usertype_traits<T>::is_null(arg)) {
|
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
return push_deep(L, std::forward<Arg>(arg));
|
return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Arg0, typename Arg1, typename... Args>
|
|
||||||
static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) {
|
|
||||||
return push_deep(L, std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
@ -232,33 +230,32 @@ namespace sol {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} // namespace stack_detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename>
|
||||||
struct unqualified_pusher<std::reference_wrapper<T>> {
|
struct unqualified_pusher {
|
||||||
static int push(lua_State* L, const std::reference_wrapper<T>& t) {
|
template <typename... Args>
|
||||||
return stack::push(L, std::addressof(detail::deref(t.get())));
|
static int push(lua_State* L, Args&&... args) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (is_lua_reference_v<Tu>) {
|
||||||
|
using int_arr = int[];
|
||||||
|
int_arr p{ (std::forward<Args>(args).push(L))... };
|
||||||
|
return p[0];
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_same_v<Tu, bool>) {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_pusher<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
|
||||||
static int push(lua_State* L, const T& value) {
|
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
luaL_checkstack(L, 1, detail::not_enough_stack_space_floating);
|
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
|
||||||
#endif // make sure stack doesn't overflow
|
#endif // make sure stack doesn't overflow
|
||||||
lua_pushnumber(L, value);
|
lua_pushboolean(L, std::forward<Args>(args)...);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
else if constexpr (std::is_integral_v<Tu>) {
|
||||||
|
const Tu& value(std::forward<Args>(args)...);
|
||||||
template <typename T>
|
|
||||||
struct unqualified_pusher<T, std::enable_if_t<std::is_integral<T>::value>> {
|
|
||||||
static int push(lua_State* L, const T& value) {
|
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
luaL_checkstack(L, 1, detail::not_enough_stack_space_integral);
|
luaL_checkstack(L, 1, detail::not_enough_stack_space_integral);
|
||||||
#endif // make sure stack doesn't overflow
|
#endif // make sure stack doesn't overflow
|
||||||
#if SOL_LUA_VERSION >= 503
|
#if SOL_LUA_VERSION >= 503
|
||||||
if (stack_detail::integer_value_fits<T>(value)) {
|
if (stack_detail::integer_value_fits<Tu>(value)) {
|
||||||
lua_pushinteger(L, static_cast<lua_Integer>(value));
|
lua_pushinteger(L, static_cast<lua_Integer>(value));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -268,7 +265,7 @@ namespace sol {
|
||||||
#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS
|
#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS
|
||||||
// Is this really worth it?
|
// Is this really worth it?
|
||||||
assert(false && "integer value will be misrepresented in lua");
|
assert(false && "integer value will be misrepresented in lua");
|
||||||
lua_pushnumber(L, static_cast<lua_Number>(value));
|
lua_pushnumber(L, static_cast<lua_Number>(std::forward<Args>(args)...));
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
throw error(detail::direct_error, "integer value will be misrepresented in lua");
|
throw error(detail::direct_error, "integer value will be misrepresented in lua");
|
||||||
|
@ -278,32 +275,50 @@ namespace sol {
|
||||||
lua_pushnumber(L, static_cast<lua_Number>(value));
|
lua_pushnumber(L, static_cast<lua_Number>(value));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_floating_point_v<Tu>) {
|
||||||
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
|
luaL_checkstack(L, 1, detail::not_enough_stack_space_floating);
|
||||||
|
#endif // make sure stack doesn't overflow
|
||||||
|
lua_pushnumber(L, std::forward<Args>(args)...);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_enum_v<Tu>) {
|
||||||
|
return stack_detail::msvc_is_ass_with_if_constexpr_push_enum(std::true_type(), L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_pointer_v<Tu>) {
|
||||||
|
return stack::push<detail::as_pointer_tag<std::remove_pointer_t<T>>>(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else if constexpr (is_unique_usertype_v<Tu>) {
|
||||||
|
stack_detail::uu_pusher<T> p;
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return stack::push<detail::as_value_tag<T>>(L, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<T, std::enable_if_t<std::is_enum<T>::value>> {
|
struct unqualified_pusher<std::reference_wrapper<T>> {
|
||||||
static int push(lua_State* L, const T& value) {
|
static int push(lua_State* L, const std::reference_wrapper<T>& t) {
|
||||||
if (std::is_same<char, std::underlying_type_t<T>>::value) {
|
return stack::push(L, std::addressof(detail::deref(t.get())));
|
||||||
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 unqualified_pusher<detail::as_table_tag<T>> {
|
struct unqualified_pusher<detail::as_table_tag<T>> {
|
||||||
|
using has_kvp = meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>;
|
||||||
|
|
||||||
static int push(lua_State* L, const T& tablecont) {
|
static int push(lua_State* L, const T& tablecont) {
|
||||||
typedef meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>> has_kvp;
|
|
||||||
return push(has_kvp(), std::false_type(), L, tablecont);
|
return push(has_kvp(), std::false_type(), L, tablecont);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(std::true_type, lua_State* L, const T& tablecont) {
|
static int push(std::true_type, lua_State* L, const T& tablecont) {
|
||||||
typedef meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>> has_kvp;
|
|
||||||
return push(has_kvp(), std::true_type(), L, tablecont);
|
return push(has_kvp(), std::true_type(), L, tablecont);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(std::false_type, lua_State* L, const T& tablecont) {
|
static int push(std::false_type, lua_State* L, const T& tablecont) {
|
||||||
typedef meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>> has_kvp;
|
|
||||||
return push(has_kvp(), std::false_type(), L, tablecont);
|
return push(has_kvp(), std::false_type(), L, tablecont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,36 +383,28 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<as_table_t<T>, std::enable_if_t<is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> {
|
struct unqualified_pusher<as_table_t<T>> {
|
||||||
static int push(lua_State* L, const T& tablecont) {
|
|
||||||
return stack::push<detail::as_table_tag<T>>(L, tablecont);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_pusher<as_table_t<T>, std::enable_if_t<!is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> {
|
|
||||||
static int push(lua_State* L, const T& v) {
|
static int push(lua_State* L, const T& v) {
|
||||||
|
using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>;
|
||||||
|
if constexpr (is_container_v<inner_t>) {
|
||||||
|
return stack::push<detail::as_table_tag<T>>(L, v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return stack::push(L, v);
|
return stack::push(L, v);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_pusher<nested<T>, std::enable_if_t<is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> {
|
|
||||||
static int push(lua_State* L, const T& tablecont) {
|
|
||||||
unqualified_pusher<detail::as_table_tag<T>> p{};
|
|
||||||
// silence annoying VC++ warning
|
|
||||||
(void)p;
|
|
||||||
return p.push(std::true_type(), L, tablecont);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<nested<T>, std::enable_if_t<!is_container<std::remove_pointer_t<meta::unwrap_unqualified_t<T>>>::value>> {
|
struct unqualified_pusher<nested<T>> {
|
||||||
static int push(lua_State* L, const T& tablecont) {
|
static int push(lua_State* L, const T& tablecont) {
|
||||||
unqualified_pusher<meta::unqualified_t<T>> p{};
|
using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>;
|
||||||
// silence annoying VC++ warning
|
if constexpr (is_container_v<inner_t>) {
|
||||||
(void)p;
|
return stack::push<detail::as_table_tag<T>>(L, tablecont);
|
||||||
return p.push(L, tablecont);
|
}
|
||||||
|
else {
|
||||||
|
return stack::push<inner_t>(L, tablecont);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -411,28 +418,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_pusher<T, std::enable_if_t<is_lua_reference<T>::value>> {
|
|
||||||
static int push(lua_State* L, const T& ref) {
|
|
||||||
return ref.push(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int push(lua_State* L, T&& ref) {
|
|
||||||
return ref.push(L);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct unqualified_pusher<bool> {
|
|
||||||
static int push(lua_State* L, bool b) {
|
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
|
||||||
luaL_checkstack(L, 1, detail::not_enough_stack_space_generic);
|
|
||||||
#endif // make sure stack doesn't overflow
|
|
||||||
lua_pushboolean(L, b);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct unqualified_pusher<lua_nil_t> {
|
struct unqualified_pusher<lua_nil_t> {
|
||||||
static int push(lua_State* L, lua_nil_t) {
|
static int push(lua_State* L, lua_nil_t) {
|
||||||
|
@ -604,22 +589,20 @@ namespace sol {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_key_t>> = meta::enabler>
|
template <typename Arg, typename... Args>
|
||||||
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
static int push(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
|
if constexpr (std::is_same_v<meta::unqualified_t<Arg>, metatable_key_t>) {
|
||||||
return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
const auto name = &arg[0];
|
||||||
|
return push_with<true>(L, name, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<meta::unqualified_t<Arg>, no_metatable_t>) {
|
||||||
template <typename... Args>
|
|
||||||
static int push(lua_State* L, no_metatable_t, Args&&... args) {
|
|
||||||
const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
|
const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
|
||||||
return push_with<false>(L, name, std::forward<Args>(args)...);
|
return push_with<false>(L, name, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
template <typename Key, typename... Args>
|
const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0];
|
||||||
static int push(lua_State* L, metatable_key_t, Key&& key, Args&&... args) {
|
return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
const auto name = &key[0];
|
}
|
||||||
return push_with<true>(L, name, std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const user<T>& u) {
|
static int push(lua_State* L, const user<T>& u) {
|
||||||
|
@ -734,23 +717,33 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Traits, typename Al>
|
template <typename Ch, typename Traits, typename Al>
|
||||||
struct unqualified_pusher<std::basic_string<char, Traits, Al>> {
|
struct unqualified_pusher<std::basic_string<Ch, Traits, Al>> {
|
||||||
static int push(lua_State* L, const std::basic_string<char, Traits, Al>& str) {
|
static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& str) {
|
||||||
|
if constexpr (!std::is_same_v<Ch, char>) {
|
||||||
|
return stack::push(str.data(), str.size());
|
||||||
|
}
|
||||||
|
else {
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
|
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
|
||||||
#endif // make sure stack doesn't overflow
|
#endif // make sure stack doesn't overflow
|
||||||
lua_pushlstring(L, str.c_str(), str.size());
|
lua_pushlstring(L, str.c_str(), str.size());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int push(lua_State* L, const std::basic_string<char, Traits, Al>& str, std::size_t sz) {
|
static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& str, std::size_t sz) {
|
||||||
|
if constexpr (!std::is_same_v<Ch, char>) {
|
||||||
|
return stack::push(str.data(), sz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
|
||||||
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
|
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
|
||||||
#endif // make sure stack doesn't overflow
|
#endif // make sure stack doesn't overflow
|
||||||
lua_pushlstring(L, str.c_str(), sz);
|
lua_pushlstring(L, str.c_str(), sz);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Ch, typename Traits>
|
template <typename Ch, typename Traits>
|
||||||
|
@ -1066,17 +1059,6 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Ch, typename Traits, typename Al>
|
|
||||||
struct unqualified_pusher<std::basic_string<Ch, Traits, Al>, std::enable_if_t<!std::is_same<Ch, char>::value>> {
|
|
||||||
static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& wstr) {
|
|
||||||
return push(L, wstr, wstr.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& wstr, std::size_t sz) {
|
|
||||||
return stack::push(L, wstr.data(), wstr.data() + sz);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
struct unqualified_pusher<std::tuple<Args...>> {
|
struct unqualified_pusher<std::tuple<Args...>> {
|
||||||
template <std::size_t... I, typename T>
|
template <std::size_t... I, typename T>
|
||||||
|
|
|
@ -72,13 +72,13 @@ namespace sol {
|
||||||
|
|
||||||
inline int default_traceback_error_handler(lua_State* L) {
|
inline int default_traceback_error_handler(lua_State* L) {
|
||||||
std::string msg = "An unknown error has triggered the default error handler";
|
std::string msg = "An unknown error has triggered the default error handler";
|
||||||
optional<string_view> maybetopmsg = stack::check_get<string_view>(L, 1);
|
optional<string_view> maybetopmsg = stack::unqualified_check_get<string_view>(L, 1, no_panic);
|
||||||
if (maybetopmsg) {
|
if (maybetopmsg) {
|
||||||
const string_view& topmsg = maybetopmsg.value();
|
const string_view& topmsg = maybetopmsg.value();
|
||||||
msg.assign(topmsg.data(), topmsg.size());
|
msg.assign(topmsg.data(), topmsg.size());
|
||||||
}
|
}
|
||||||
luaL_traceback(L, L, msg.c_str(), 1);
|
luaL_traceback(L, L, msg.c_str(), 1);
|
||||||
optional<string_view> maybetraceback = stack::check_get<string_view>(L, -1);
|
optional<string_view> maybetraceback = stack::unqualified_check_get<string_view>(L, -1, no_panic);
|
||||||
if (maybetraceback) {
|
if (maybetraceback) {
|
||||||
const string_view& traceback = maybetraceback.value();
|
const string_view& traceback = maybetraceback.value();
|
||||||
msg.assign(traceback.data(), traceback.size());
|
msg.assign(traceback.data(), traceback.size());
|
||||||
|
@ -141,7 +141,7 @@ namespace sol {
|
||||||
#endif // serialize exception information if possible
|
#endif // serialize exception information if possible
|
||||||
if (t == type::string) {
|
if (t == type::string) {
|
||||||
err += ": ";
|
err += ": ";
|
||||||
string_view serr = stack::get<string_view>(L, result.stack_index());
|
string_view serr = stack::unqualified_get<string_view>(L, result.stack_index());
|
||||||
err.append(serr.data(), serr.size());
|
err.append(serr.data(), serr.size());
|
||||||
}
|
}
|
||||||
#if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS
|
#if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS
|
||||||
|
|
|
@ -47,6 +47,23 @@ namespace sol {
|
||||||
using sfinae_yes_t = std::true_type;
|
using sfinae_yes_t = std::true_type;
|
||||||
using sfinae_no_t = std::false_type;
|
using sfinae_no_t = std::false_type;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using void_t = void;
|
||||||
|
|
||||||
|
namespace meta_detail {
|
||||||
|
template <template <class...> class Test, class, class... Args>
|
||||||
|
struct is_detected : std::false_type {};
|
||||||
|
|
||||||
|
template <template <class...> class Test, class... Args>
|
||||||
|
struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type {};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <template <class...> class Trait, class... Args>
|
||||||
|
using is_detected = typename meta_detail::is_detected<Trait, void, Args...>::type;
|
||||||
|
|
||||||
|
template <template <class...> class Trait, class... Args>
|
||||||
|
constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value;
|
||||||
|
|
||||||
template <std::size_t I>
|
template <std::size_t I>
|
||||||
using index_value = std::integral_constant<std::size_t, I>;
|
using index_value = std::integral_constant<std::size_t, I>;
|
||||||
|
|
||||||
|
@ -130,18 +147,21 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using remove_member_pointer_t = remove_member_pointer<T>;
|
using remove_member_pointer_t = remove_member_pointer<T>;
|
||||||
|
|
||||||
template <class T, class...>
|
template <typename T, typename...>
|
||||||
struct all_same : std::true_type {};
|
struct all_same : std::true_type {};
|
||||||
|
|
||||||
template <class T, class U, class... Args>
|
template <typename T, typename U, typename... Args>
|
||||||
struct all_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && all_same<T, Args...>::value> {};
|
struct all_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && all_same<T, Args...>::value> {};
|
||||||
|
|
||||||
template <class T, class...>
|
template <typename T, typename...>
|
||||||
struct any_same : std::false_type {};
|
struct any_same : std::false_type {};
|
||||||
|
|
||||||
template <class T, class U, class... Args>
|
template <typename T, typename U, typename... Args>
|
||||||
struct any_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value || any_same<T, Args...>::value> {};
|
struct any_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value || any_same<T, Args...>::value> {};
|
||||||
|
|
||||||
|
template <typename T, typename...Args>
|
||||||
|
constexpr inline bool any_same_v = any_same<T, Args...>::value;
|
||||||
|
|
||||||
template <bool B>
|
template <bool B>
|
||||||
using boolean = std::integral_constant<bool, B>;
|
using boolean = std::integral_constant<bool, B>;
|
||||||
|
|
||||||
|
@ -151,6 +171,9 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using neg = boolean<!T::value>;
|
using neg = boolean<!T::value>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool neg_v = neg<T>::value;
|
||||||
|
|
||||||
template <typename Condition, typename Then, typename Else>
|
template <typename Condition, typename Then, typename Else>
|
||||||
using condition = conditional_t<Condition::value, Then, Else>;
|
using condition = conditional_t<Condition::value, Then, Else>;
|
||||||
|
|
||||||
|
@ -166,6 +189,12 @@ namespace sol {
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {};
|
struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {};
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
constexpr inline bool all_v = all<T, Args...>::value;
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
constexpr inline bool any_v = any<T, Args...>::value;
|
||||||
|
|
||||||
enum class enable_t { _ };
|
enum class enable_t { _ };
|
||||||
|
|
||||||
constexpr const auto enabler = enable_t::_;
|
constexpr const auto enabler = enable_t::_;
|
||||||
|
@ -538,11 +567,17 @@ namespace sol {
|
||||||
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<meta_detail::non_void_t<T>>::value>;
|
using supports_to_string_member = meta::boolean<meta_detail::has_to_string_test<meta_detail::non_void_t<T>>::value>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_callable : boolean<meta_detail::is_callable<T>::value> {};
|
using is_callable = boolean<meta_detail::is_callable<T>::value>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool is_callable_v = is_callable<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {};
|
struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool has_begin_end_v = has_begin_end<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
@ -592,28 +627,76 @@ namespace sol {
|
||||||
using is_matched_lookup = meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value>;
|
using is_matched_lookup = meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_string_like = any<is_specialization_of<meta::unqualified_t<T>, std::basic_string>,
|
using is_initializer_list = meta::is_specialization_of<T, std::initializer_list>;
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
|
||||||
is_specialization_of<meta::unqualified_t<T>, std::basic_string_view>,
|
|
||||||
#else
|
|
||||||
is_specialization_of<meta::unqualified_t<T>, basic_string_view>,
|
|
||||||
#endif
|
|
||||||
meta::all<std::is_array<unqualified_t<T>>,
|
|
||||||
meta::any_same<meta::unqualified_t<std::remove_all_extents_t<meta::unqualified_t<T>>>, char, char16_t, char32_t, wchar_t>>>;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_string_constructible
|
constexpr inline bool is_initializer_list_v = is_initializer_list<T>::value;
|
||||||
= any<meta::all<std::is_array<unqualified_t<T>>, std::is_same<meta::unqualified_t<std::remove_all_extents_t<meta::unqualified_t<T>>>, char>>,
|
|
||||||
std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>,
|
template <typename T, typename CharT = char>
|
||||||
std::is_same<unqualified_t<T>, std::initializer_list<char>>
|
using is_string_literal_array_of = boolean<std::is_array_v<T> && std::is_same_v<std::remove_all_extents_t<T>, CharT>>;
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
constexpr inline bool is_string_literal_array_of_v = is_string_literal_array_of<T, CharT>::value;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_string_literal_array = boolean<std::is_array_v<T> && any_same_v<std::remove_all_extents_t<T>, char, char16_t, char32_t, wchar_t>>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool is_string_literal_array_v = is_string_literal_array<T>::value;
|
||||||
|
|
||||||
|
template <typename T, typename CharT>
|
||||||
|
struct is_string_of : std::false_type {};
|
||||||
|
|
||||||
|
template <typename CharT, typename CharTargetT, typename TraitsT, typename AllocT>
|
||||||
|
struct is_string_of<std::basic_string<CharT, TraitsT, AllocT>, CharTargetT> : std::is_same<CharT, CharTargetT> {};
|
||||||
|
|
||||||
|
template <typename T, typename CharT>
|
||||||
|
constexpr inline bool is_string_of_v = is_string_of<T, CharT>::value;
|
||||||
|
|
||||||
|
template <typename T, typename CharT>
|
||||||
|
struct is_string_view_of : std::false_type {};
|
||||||
|
|
||||||
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
,
|
template <typename CharT, typename CharTargetT, typename TraitsT>
|
||||||
std::is_same<unqualified_t<T>, std::string_view>
|
struct is_string_view_of<std::basic_string_view<CharT, TraitsT>, CharTargetT> : std::is_same<CharT, CharTargetT> {};
|
||||||
|
#else
|
||||||
|
template <typename CharT, typename CharTargetT, typename TraitsT>
|
||||||
|
struct is_string_view_of<basic_string_view<CharT, TraitsT>, CharTargetT> : std::is_same<CharT, CharTargetT> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T, typename CharT>
|
||||||
|
constexpr inline bool is_string_view_of_v = is_string_view_of<T, CharT>::value;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using is_string_like = meta::boolean<
|
||||||
|
is_specialization_of_v<T, std::basic_string>
|
||||||
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
|
|| is_specialization_of_v<T, std::basic_string_view>
|
||||||
|
#else
|
||||||
|
|| is_specialization_of_v<T, basic_string_view>
|
||||||
|
#endif
|
||||||
|
|| is_string_literal_array_v<T>>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool is_string_like_v = is_string_like<T>::value;
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
using is_string_constructible = meta::boolean<
|
||||||
|
is_string_literal_array_of_v<T, CharT>
|
||||||
|
|| std::is_same_v<T, const CharT*>
|
||||||
|
|| std::is_same_v<T, CharT>
|
||||||
|
|| is_string_of_v<T, CharT>
|
||||||
|
|| std::is_same_v<T, std::initializer_list<CharT>>
|
||||||
|
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
|
||||||
|
|| is_string_view_of_v<T, CharT>
|
||||||
#endif
|
#endif
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
constexpr inline bool is_string_constructible_v = is_string_constructible<T, CharT>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_string_like_or_constructible = any<is_string_like<T>, is_string_constructible<T>>;
|
using is_string_like_or_constructible = meta::boolean<is_string_like_v<T> || is_string_constructible_v<T>>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_pair : std::false_type {};
|
struct is_pair : std::false_type {};
|
||||||
|
|
|
@ -480,6 +480,8 @@ namespace sol {
|
||||||
T value_;
|
T value_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using type = T;
|
||||||
|
|
||||||
as_container_t() = default;
|
as_container_t() = default;
|
||||||
as_container_t(const as_container_t&) = default;
|
as_container_t(const as_container_t&) = default;
|
||||||
as_container_t(as_container_t&&) = default;
|
as_container_t(as_container_t&&) = default;
|
||||||
|
@ -909,21 +911,25 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_reference : std::integral_constant<bool,
|
struct is_lua_reference : std::integral_constant<bool,
|
||||||
std::is_base_of<reference, meta::unqualified_t<T>>::value || std::is_base_of<main_reference, meta::unqualified_t<T>>::value
|
std::is_base_of_v<reference, T> || std::is_base_of_v<main_reference, T>
|
||||||
|| std::is_base_of<stack_reference, meta::unqualified_t<T>>::value> {};
|
|| std::is_base_of_v<stack_reference, T>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_lua_reference_v = is_lua_reference<T>::value;
|
inline constexpr bool is_lua_reference_v = is_lua_reference<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_reference_or_proxy
|
struct is_lua_reference_or_proxy
|
||||||
: std::integral_constant<bool, is_lua_reference<meta::unqualified_t<T>>::value || meta::is_specialization_of<meta::unqualified_t<T>, proxy>::value> {};
|
: std::integral_constant<bool, is_lua_reference_v<T> || meta::is_specialization_of_v<T, proxy>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy<T>::value;
|
inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_transparent_argument : std::false_type {};
|
struct is_transparent_argument : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool is_transparent_argument_v = is_transparent_argument<T>::value;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct is_transparent_argument<this_state> : std::true_type {};
|
struct is_transparent_argument<this_state> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
|
@ -933,38 +939,13 @@ namespace sol {
|
||||||
template <>
|
template <>
|
||||||
struct is_transparent_argument<variadic_args> : std::true_type {};
|
struct is_transparent_argument<variadic_args> : std::true_type {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_variadic_arguments : std::is_same<meta::unqualified_t<T>, variadic_args> {};
|
struct is_variadic_arguments : std::is_same<T, variadic_args> {};
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template <typename T>
|
|
||||||
struct is_initializer_list : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_initializer_list<std::initializer_list<T>> : std::true_type {};
|
struct is_container : std::integral_constant<bool, !meta::is_initializer_list_v<T> && !meta::is_string_like_v<T> && !meta::is_string_literal_array_v<T> && !is_transparent_argument_v<T> && !is_lua_reference_v<T> && (meta::has_begin_end_v<T> || std::is_array_v<T>)> {};
|
||||||
|
|
||||||
template <typename T, typename C = void>
|
|
||||||
struct is_container : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_container<std::initializer_list<T>> : std::false_type {};
|
constexpr inline bool is_container_v = is_container<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_container<T, std::enable_if_t<meta::is_string_like<meta::unqualified_t<T>>::value>> : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_container<T,
|
|
||||||
std::enable_if_t<meta::all<std::is_array<meta::unqualified_t<T>>,
|
|
||||||
meta::neg<meta::any_same<std::remove_all_extents_t<meta::unqualified_t<T>>, char, wchar_t, char16_t, char32_t>>>::value>> : std::true_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_container<T,
|
|
||||||
std::enable_if_t<meta::all<meta::has_begin_end<meta::unqualified_t<T>>, meta::neg<is_initializer_list<meta::unqualified_t<T>>>,
|
|
||||||
meta::neg<meta::is_string_like<meta::unqualified_t<T>>>>::value>> : std::true_type {};
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_container : detail::is_container<T> {};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_to_stringable : meta::any<meta::supports_to_string_member<meta::unqualified_t<T>>, meta::supports_adl_to_string<meta::unqualified_t<T>>,
|
struct is_to_stringable : meta::any<meta::supports_to_string_member<meta::unqualified_t<T>>, meta::supports_adl_to_string<meta::unqualified_t<T>>,
|
||||||
|
@ -1224,17 +1205,23 @@ namespace sol {
|
||||||
struct has_internal_marker_impl<T, typename void_<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>::type> : std::true_type {};
|
struct has_internal_marker_impl<T, typename void_<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>::type> : std::true_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_internal_marker : has_internal_marker_impl<T> {};
|
using has_internal_marker = has_internal_marker_impl<T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool has_internal_marker_v = has_internal_marker<T>::value;
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_lua_primitive
|
struct is_lua_primitive
|
||||||
: std::integral_constant<bool,
|
: std::integral_constant<bool,
|
||||||
type::userdata != lua_type_of<meta::unqualified_t<T>>::value
|
type::userdata != lua_type_of_v<T>
|
||||||
|| ((type::userdata == lua_type_of<meta::unqualified_t<T>>::value) && detail::has_internal_marker<lua_type_of<meta::unqualified_t<T>>>::value
|
|| ((type::userdata == lua_type_of_v<T>) && detail::has_internal_marker_v<lua_type_of<T>>
|
||||||
&& !detail::has_internal_marker<lua_size<meta::unqualified_t<T>>>::value)
|
&& !detail::has_internal_marker_v<lua_size<T>>)
|
||||||
|| is_lua_reference<meta::unqualified_t<T>>::value || meta::is_specialization_of<meta::unqualified_t<T>, std::tuple>::value
|
|| is_lua_reference_v<T> || meta::is_specialization_of_v<T, std::tuple>
|
||||||
|| meta::is_specialization_of<meta::unqualified_t<T>, std::pair>::value> {};
|
|| meta::is_specialization_of_v<T, std::pair>> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline bool is_lua_primitive_v = is_lua_primitive<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_main_threaded : std::is_base_of<main_reference, T> {};
|
struct is_main_threaded : std::is_base_of<main_reference, T> {};
|
||||||
|
|
|
@ -1080,7 +1080,7 @@ namespace sol {
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
int p;
|
int p;
|
||||||
if (ip) {
|
if constexpr (ip) {
|
||||||
++i.i;
|
++i.i;
|
||||||
p = stack::push_reference(L, i.i);
|
p = stack::push_reference(L, i.i);
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1102,12 @@ namespace sol {
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
int p;
|
int p;
|
||||||
|
if constexpr (std::is_integral_v<next_K>) {
|
||||||
p = stack::push_reference(L, k + 1);
|
p = stack::push_reference(L, k + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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_non_pointer(*it));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
|
@ -1137,7 +1142,7 @@ namespace sol {
|
||||||
auto& self = get_src(L);
|
auto& self = get_src(L);
|
||||||
detail::error_result er;
|
detail::error_result er;
|
||||||
{
|
{
|
||||||
std::ptrdiff_t pos = stack::unqualified_get<std::ptrdiff_t>(L);
|
std::ptrdiff_t pos = stack::unqualified_get<std::ptrdiff_t>(L, 2);
|
||||||
er = at_start(L, self, pos);
|
er = at_start(L, self, pos);
|
||||||
}
|
}
|
||||||
return handle_errors(L, er);
|
return handle_errors(L, er);
|
||||||
|
@ -1315,7 +1320,7 @@ namespace sol {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int p;
|
int p;
|
||||||
p = stack::push_reference(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_non_pointer(*it));
|
||||||
std::advance(it, 1);
|
std::advance(it, 1);
|
||||||
return p;
|
return p;
|
||||||
|
|
|
@ -365,7 +365,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<as_container_t<T>> {
|
struct unqualified_pusher<as_container_t<T>> {
|
||||||
typedef meta::unqualified_t<T> C;
|
using C = meta::unqualified_t<T>;
|
||||||
|
|
||||||
static int push_lvalue(std::true_type, lua_State* L, const C& cont) {
|
static int push_lvalue(std::true_type, lua_State* L, const C& cont) {
|
||||||
stack_detail::metatable_setup<C*, true> fx(L);
|
stack_detail::metatable_setup<C*, true> fx(L);
|
||||||
|
@ -397,7 +397,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<as_container_t<T*>> {
|
struct unqualified_pusher<as_container_t<T*>> {
|
||||||
typedef std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>> C;
|
using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>;
|
||||||
|
|
||||||
static int push(lua_State* L, T* cont) {
|
static int push(lua_State* L, T* cont) {
|
||||||
stack_detail::metatable_setup<C> fx(L);
|
stack_detail::metatable_setup<C> fx(L);
|
||||||
|
@ -406,8 +406,8 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<T, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<is_lua_reference<meta::unqualified_t<T>>>>::value>> {
|
struct unqualified_pusher<T, std::enable_if_t<is_container_v<T>>> {
|
||||||
typedef meta::unqualified_t<T> C;
|
using C = T;
|
||||||
|
|
||||||
static int push(lua_State* L, const T& cont) {
|
static int push(lua_State* L, const T& cont) {
|
||||||
stack_detail::metatable_setup<C> fx(L);
|
stack_detail::metatable_setup<C> fx(L);
|
||||||
|
@ -421,36 +421,14 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unqualified_pusher<T*, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<is_lua_reference<meta::unqualified_t<T>>>>::value>> {
|
struct unqualified_pusher<T*, std::enable_if_t<is_container_v<T>>> {
|
||||||
typedef std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>> C;
|
using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>;
|
||||||
|
|
||||||
static int push(lua_State* L, T* cont) {
|
static int push(lua_State* L, T* cont) {
|
||||||
stack_detail::metatable_setup<C> fx(L);
|
stack_detail::metatable_setup<C> fx(L);
|
||||||
return stack::push<detail::as_pointer_tag<T>>(L, detail::with_function_tag(), fx, cont);
|
return stack::push<detail::as_pointer_tag<T>>(L, detail::with_function_tag(), fx, cont);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename C>
|
|
||||||
struct unqualified_checker<as_container_t<T>, type::userdata, C> {
|
|
||||||
template <typename Handler>
|
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
return stack::check<T>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_getter<as_container_t<T>> {
|
|
||||||
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
|
||||||
return stack::unqualified_get<T>(L, index, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct unqualified_getter<as_container_t<T>*> {
|
|
||||||
static decltype(auto) get(lua_State* L, int index, record& tracking) {
|
|
||||||
return stack::unqualified_get<T*>(L, index, tracking);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace stack
|
} // namespace stack
|
||||||
|
|
||||||
} // namespace sol
|
} // namespace sol
|
||||||
|
|
|
@ -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-02-16 22:26:16.417718 UTC
|
// Generated 2019-03-10 01:57:28.833449 UTC
|
||||||
// This header was generated with sol v3.0.0 (revision 95ffd10)
|
// This header was generated with sol v3.0.0 (revision b6f4093)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||||
|
@ -245,6 +245,14 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA
|
||||||
|
struct lua_State;
|
||||||
|
#else
|
||||||
|
extern "C" {
|
||||||
|
struct lua_State;
|
||||||
|
}
|
||||||
|
#endif // C++ Mangling for Lua vs. Not
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
template <bool b>
|
template <bool b>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user