mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
SUPER DUPER UPDATE WOO
This commit is contained in:
parent
ffe77ccb3f
commit
b938e42af6
|
@ -85,7 +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
|
||||||
-Wall -Wpendatic -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)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -29,36 +29,27 @@ private:
|
||||||
int v_ = 50;
|
int v_ = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace sol {
|
template <typename T, typename Handler>
|
||||||
namespace stack {
|
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
|
||||||
template <typename T>
|
// just marking unused parameters for no compiler warnings
|
||||||
struct userdata_checker<extensible<T>> {
|
(void)index_type;
|
||||||
template <typename Handler>
|
(void)handler;
|
||||||
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) {
|
tracking.use(1);
|
||||||
// just marking unused parameters for no compiler warnings
|
int index = lua_absindex(L, relindex);
|
||||||
(void)index_type;
|
T* corrected = luabridge::Userdata::get<T>(L, index, true);
|
||||||
(void)handler;
|
return corrected != nullptr;
|
||||||
tracking.use(1);
|
}
|
||||||
int index = lua_absindex(L, relindex);
|
|
||||||
T* corrected = luabridge::Userdata::get<T>(L, index, true);
|
template <typename T>
|
||||||
return corrected != nullptr;
|
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
|
||||||
}
|
(void)unadjusted_pointer;
|
||||||
};
|
int index = lua_absindex(L, relindex);
|
||||||
|
if (!sol_lua_interop_check(t, L, index, sol::type::userdata, sol::no_panic, tracking)) {
|
||||||
template <typename T>
|
return { false, nullptr };
|
||||||
struct userdata_getter<extensible<T>> {
|
}
|
||||||
static std::pair<bool, T*> get(lua_State* L, int relindex, void* unadjusted_pointer, record& tracking) {
|
T* corrected = luabridge::Userdata::get<T>(L, index, true);
|
||||||
(void)unadjusted_pointer;
|
return { true, corrected };
|
||||||
int index = lua_absindex(L, relindex);
|
|
||||||
if (!userdata_checker<extensible<T>>::check(L, index, type::userdata, no_panic, tracking)) {
|
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
T* corrected = luabridge::Userdata::get<T>(L, index, true);
|
|
||||||
return { true, corrected };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} // namespace sol::stack
|
|
||||||
|
|
||||||
void register_sol_stuff(lua_State* L) {
|
void register_sol_stuff(lua_State* L) {
|
||||||
// grab raw state and put into state_view
|
// grab raw state and put into state_view
|
||||||
|
|
|
@ -39,46 +39,37 @@ private:
|
||||||
int v_;
|
int v_;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace sol {
|
template <typename T, typename Handler>
|
||||||
namespace stack {
|
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
|
||||||
template <typename T>
|
// just marking unused parameters for no compiler warnings
|
||||||
struct userdata_checker<extensible<T>> {
|
(void)index_type;
|
||||||
template <typename Handler>
|
(void)handler;
|
||||||
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) {
|
// using 1 element
|
||||||
// just marking unused parameters for no compiler warnings
|
tracking.use(1);
|
||||||
(void)index_type;
|
int index = lua_absindex(L, relindex);
|
||||||
(void)handler;
|
// use kaguya's own detail wrapper check to see if it's correct
|
||||||
// using 1 element
|
bool is_correct_type = kaguya::detail::object_wrapper_type_check(L, index);
|
||||||
tracking.use(1);
|
return is_correct_type;
|
||||||
int index = lua_absindex(L, relindex);
|
}
|
||||||
// use kaguya's own detail wrapper check to see if it's correct
|
|
||||||
bool is_correct_type = kaguya::detail::object_wrapper_type_check(L, index);
|
template <typename T>
|
||||||
return is_correct_type;
|
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T>, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
|
||||||
}
|
// you may not need to specialize this method every time:
|
||||||
};
|
// some libraries are compatible with sol2's layout
|
||||||
|
|
||||||
template <typename T>
|
// kaguya's storage of data is incompatible with sol's
|
||||||
struct userdata_getter<extensible<T>> {
|
// it stores the data directly in the pointer, not a pointer inside of the `void*`
|
||||||
static std::pair<bool, T*> get(lua_State* L, int relindex, void* unadjusted_pointer, record& tracking) {
|
// therefore, leave the raw userdata pointer as-is,
|
||||||
// you may not need to specialize this method every time:
|
// if it's of the right type
|
||||||
// some libraries are compatible with sol2's layout
|
int index = lua_absindex(L, relindex);
|
||||||
|
if (!kaguya::detail::object_wrapper_type_check(L, index)) {
|
||||||
// kaguya's storage of data is incompatible with sol's
|
return { false, nullptr };
|
||||||
// it stores the data directly in the pointer, not a pointer inside of the `void*`
|
}
|
||||||
// therefore, leave the raw userdata pointer as-is,
|
// using 1 element
|
||||||
// if it's of the right type
|
tracking.use(1);
|
||||||
int index = lua_absindex(L, relindex);
|
kaguya::ObjectWrapperBase* base = kaguya::object_wrapper(L, index);
|
||||||
if (!kaguya::detail::object_wrapper_type_check(L, index)) {
|
return { true, static_cast<T*>(base->get()) };
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
// using 1 element
|
|
||||||
tracking.use(1);
|
|
||||||
kaguya::ObjectWrapperBase* base = kaguya::object_wrapper(L, index);
|
|
||||||
return { true, static_cast<T*>(base->get()) };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} // namespace sol::stack
|
|
||||||
|
|
||||||
void register_sol_stuff(lua_State* L) {
|
void register_sol_stuff(lua_State* L) {
|
||||||
// grab raw state and put into state_view
|
// grab raw state and put into state_view
|
||||||
|
|
|
@ -35,42 +35,33 @@ private:
|
||||||
int v_;
|
int v_;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace sol {
|
template <typename T, typename Handler>
|
||||||
namespace stack {
|
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
|
||||||
template <typename T>
|
// just marking unused parameters for no compiler warnings
|
||||||
struct userdata_checker<extensible<T>> {
|
(void)index_type;
|
||||||
template <typename Handler>
|
(void)handler;
|
||||||
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) {
|
// using 1 element
|
||||||
// just marking unused parameters for no compiler warnings
|
tracking.use(1);
|
||||||
(void)index_type;
|
int index = lua_absindex(L, relindex);
|
||||||
(void)handler;
|
if (lua_getmetatable(L, index) == 1) {
|
||||||
// using 1 element
|
luaL_getmetatable(L, luwra::internal::UserTypeReg<T>::name.c_str());
|
||||||
tracking.use(1);
|
bool is_correct_type = lua_rawequal(L, -2, -1) == 1;
|
||||||
int index = lua_absindex(L, relindex);
|
lua_pop(L, 2);
|
||||||
if (lua_getmetatable(L, index) == 1) {
|
return is_correct_type;
|
||||||
luaL_getmetatable(L, luwra::internal::UserTypeReg<T>::name.c_str());
|
}
|
||||||
bool is_correct_type = lua_rawequal(L, -2, -1) == 1;
|
return false;
|
||||||
lua_pop(L, 2);
|
}
|
||||||
return is_correct_type;
|
|
||||||
}
|
template <typename T>
|
||||||
return false;
|
inline std::pair<bool, T*> sol_lua_interop_get(sol::types<T> t, lua_State* L, int relindex, void* unadjusted_pointer, sol::stack::record& tracking) {
|
||||||
}
|
// you may not need to specialize this method every time:
|
||||||
};
|
// some libraries are compatible with sol2's layout
|
||||||
|
int index = lua_absindex(L, relindex);
|
||||||
template <typename T>
|
if (!sol_lua_interop_check(t, L, index, sol::type::userdata, sol::no_panic, tracking)) {
|
||||||
struct userdata_getter<extensible<T>> {
|
return { false, nullptr };
|
||||||
static std::pair<bool, T*> get(lua_State* L, int relindex, void* unadjusted_pointer, record& tracking) {
|
}
|
||||||
// you may not need to specialize this method every time:
|
return { true, static_cast<T*>(unadjusted_pointer) };
|
||||||
// some libraries are compatible with sol2's layout
|
|
||||||
int index = lua_absindex(L, relindex);
|
|
||||||
if (!userdata_checker<extensible<T>>::check(L, index, type::userdata, no_panic, tracking)) {
|
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
return { true, static_cast<T*>(unadjusted_pointer) };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} // namespace sol::stack
|
|
||||||
|
|
||||||
void register_sol_stuff(lua_State* L) {
|
void register_sol_stuff(lua_State* L) {
|
||||||
// grab raw state and put into state_view
|
// grab raw state and put into state_view
|
||||||
|
|
|
@ -15,24 +15,23 @@
|
||||||
// I don't know where else you're gonna find the reference,
|
// I don't know where else you're gonna find the reference,
|
||||||
// http://usefulgamedev.weebly.com/tolua-example.html
|
// http://usefulgamedev.weebly.com/tolua-example.html
|
||||||
|
|
||||||
namespace sol {
|
|
||||||
namespace stack {
|
/* NOTE: there is no sol_lua_interop_get here,
|
||||||
template <typename T>
|
because tolua types are -- thankfully -- memory-compatible
|
||||||
struct userdata_checker<extensible<T>> {
|
in most cases with sol.
|
||||||
template <typename Handler>
|
Please check other examples like kaguya or LuaBribe for an example
|
||||||
static bool check(lua_State* L, int relindex, type index_type, Handler&& handler, record& tracking) {
|
of how to also write the getter for your type*/
|
||||||
tracking.use(1);
|
template <typename T, typename Handler>
|
||||||
// just marking unused parameters for no compiler warnings
|
inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol::type index_type, Handler&& handler, sol::stack::record& tracking) {
|
||||||
(void)index_type;
|
tracking.use(1);
|
||||||
(void)handler;
|
// just marking unused parameters for no compiler warnings
|
||||||
int index = lua_absindex(L, relindex);
|
(void)index_type;
|
||||||
std::string name = sol::detail::short_demangle<T>();
|
(void)handler;
|
||||||
tolua_Error tolua_err;
|
int index = lua_absindex(L, relindex);
|
||||||
return tolua_isusertype(L, index, name.c_str(), 0, &tolua_err);
|
std::string name = sol::detail::short_demangle<T>();
|
||||||
}
|
tolua_Error tolua_err;
|
||||||
};
|
return tolua_isusertype(L, index, name.c_str(), 0, &tolua_err);
|
||||||
}
|
}
|
||||||
} // namespace sol::stack
|
|
||||||
|
|
||||||
void register_sol_stuff(lua_State* L) {
|
void register_sol_stuff(lua_State* L) {
|
||||||
// grab raw state and put into state_view
|
// grab raw state and put into state_view
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace sol { namespace detail {
|
||||||
template <typename Arg, typename... Args,
|
template <typename Arg, typename... Args,
|
||||||
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
||||||
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
||||||
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){};
|
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
|
||||||
|
|
||||||
T& value() {
|
T& value() {
|
||||||
return value_;
|
return value_;
|
||||||
|
@ -70,7 +70,7 @@ namespace sol { namespace detail {
|
||||||
template <typename Arg, typename... Args,
|
template <typename Arg, typename... Args,
|
||||||
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
||||||
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
||||||
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){};
|
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
|
||||||
|
|
||||||
ebco& operator=(const ebco&) = default;
|
ebco& operator=(const ebco&) = default;
|
||||||
ebco& operator=(ebco&&) = default;
|
ebco& operator=(ebco&&) = default;
|
||||||
|
|
|
@ -1149,20 +1149,26 @@ namespace sol {
|
||||||
/// \synopsis template <class U> optional(const optional<U> &rhs);
|
/// \synopsis template <class U> optional(const optional<U> &rhs);
|
||||||
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
|
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
|
||||||
optional(const optional<U>& rhs) {
|
optional(const optional<U>& rhs) {
|
||||||
this->construct(*rhs);
|
if (rhs.has_value()) {
|
||||||
|
this->construct(*rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
|
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
|
||||||
explicit optional(const optional<U>& rhs) {
|
explicit optional(const optional<U>& rhs) {
|
||||||
this->construct(*rhs);
|
if (rhs.has_value()) {
|
||||||
|
this->construct(*rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converting move constructor.
|
/// Converting move constructor.
|
||||||
/// \synopsis template <class U> optional(optional<U> &&rhs);
|
/// \synopsis template <class U> optional(optional<U> &&rhs);
|
||||||
template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
|
template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
|
||||||
optional(optional<U>&& rhs) {
|
optional(optional<U>&& rhs) {
|
||||||
this->construct(std::move(*rhs));
|
if (rhs.has_value()) {
|
||||||
|
this->construct(std::move(*rhs));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
|
|
|
@ -71,13 +71,21 @@ namespace sol { namespace stack {
|
||||||
} // namespace stack_detail
|
} // namespace stack_detail
|
||||||
|
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct userdata_checker {
|
struct unqualified_interop_checker {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State*, int, type, Handler&&, record&) {
|
static bool check(lua_State*, int, type, Handler&&, record&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, typename>
|
||||||
|
struct qualified_interop_checker {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
return stack_detail::unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, type expected, typename>
|
template <typename T, type expected, typename>
|
||||||
struct unqualified_checker {
|
struct unqualified_checker {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
|
@ -446,15 +454,13 @@ namespace sol { namespace stack {
|
||||||
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);
|
||||||
return check(types<T>(), L, index, indextype, handler, tracking);
|
return check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename Handler>
|
template <typename U, typename Handler>
|
||||||
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||||
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
||||||
userdata_checker<extensible<T>> uc;
|
if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
|
||||||
(void)uc;
|
|
||||||
if (uc.check(L, index, indextype, handler, tracking)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // interop extensibility
|
#endif // interop extensibility
|
||||||
|
@ -463,8 +469,7 @@ namespace sol { namespace stack {
|
||||||
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
|
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::
|
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||||
value)
|
|
||||||
return true;
|
return true;
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -98,14 +98,13 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* align_usertype_pointer(void* ptr) {
|
inline void* align_usertype_pointer(void* ptr) {
|
||||||
typedef std::integral_constant<bool,
|
using use_align = std::integral_constant<bool,
|
||||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||||
false
|
false
|
||||||
#else
|
#else
|
||||||
(std::alignment_of<void*>::value > 1)
|
(std::alignment_of<void*>::value > 1)
|
||||||
#endif
|
#endif
|
||||||
>
|
>;
|
||||||
use_align;
|
|
||||||
if (!use_align::value) {
|
if (!use_align::value) {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -115,14 +114,13 @@ namespace sol {
|
||||||
|
|
||||||
template <bool pre_aligned = false, bool pre_shifted = false>
|
template <bool pre_aligned = false, bool pre_shifted = false>
|
||||||
inline void* align_usertype_unique_destructor(void* ptr) {
|
inline void* align_usertype_unique_destructor(void* ptr) {
|
||||||
typedef std::integral_constant<bool,
|
using use_align = std::integral_constant<bool,
|
||||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||||
false
|
false
|
||||||
#else
|
#else
|
||||||
(std::alignment_of<unique_destructor>::value > 1)
|
(std::alignment_of<unique_destructor>::value > 1)
|
||||||
#endif
|
#endif
|
||||||
>
|
>;
|
||||||
use_align;
|
|
||||||
if (!pre_aligned) {
|
if (!pre_aligned) {
|
||||||
ptr = align_usertype_pointer(ptr);
|
ptr = align_usertype_pointer(ptr);
|
||||||
}
|
}
|
||||||
|
@ -138,14 +136,13 @@ namespace sol {
|
||||||
|
|
||||||
template <bool pre_aligned = false, bool pre_shifted = false>
|
template <bool pre_aligned = false, bool pre_shifted = false>
|
||||||
inline void* align_usertype_unique_tag(void* ptr) {
|
inline void* align_usertype_unique_tag(void* ptr) {
|
||||||
typedef std::integral_constant<bool,
|
using use_align = std::integral_constant<bool,
|
||||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||||
false
|
false
|
||||||
#else
|
#else
|
||||||
(std::alignment_of<unique_tag>::value > 1)
|
(std::alignment_of<unique_tag>::value > 1)
|
||||||
#endif
|
#endif
|
||||||
>
|
>;
|
||||||
use_align;
|
|
||||||
if (!pre_aligned) {
|
if (!pre_aligned) {
|
||||||
ptr = align_usertype_unique_destructor(ptr);
|
ptr = align_usertype_unique_destructor(ptr);
|
||||||
}
|
}
|
||||||
|
@ -590,7 +587,9 @@ namespace sol {
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct qualified_getter;
|
struct qualified_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct userdata_getter;
|
struct qualified_interop_getter;
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct unqualified_interop_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct popper;
|
struct popper;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
|
@ -600,7 +599,9 @@ namespace sol {
|
||||||
template <typename T, type = lua_type_of<T>::value, typename = void>
|
template <typename T, type = lua_type_of<T>::value, typename = void>
|
||||||
struct qualified_checker;
|
struct qualified_checker;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct userdata_checker;
|
struct qualified_interop_checker;
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct unqualified_interop_checker;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct unqualified_check_getter;
|
struct unqualified_check_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
|
@ -646,6 +647,19 @@ namespace sol {
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_adl_sol_lua_interop_get {
|
||||||
|
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 {
|
struct is_adl_sol_lua_check {
|
||||||
private:
|
private:
|
||||||
|
@ -659,6 +673,19 @@ namespace sol {
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_adl_sol_lua_interop_check {
|
||||||
|
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 {
|
struct is_adl_sol_lua_check_get {
|
||||||
private:
|
private:
|
||||||
|
@ -700,9 +727,15 @@ namespace sol {
|
||||||
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 = is_adl_sol_lua_get<T>::value;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_adl_sol_lua_interop_get_v = is_adl_sol_lua_interop_get<T>::value;
|
||||||
|
|
||||||
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 = is_adl_sol_lua_check<T>::value;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_adl_sol_lua_interop_check_v = is_adl_sol_lua_interop_check<T>::value;
|
||||||
|
|
||||||
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 = is_adl_sol_lua_check_get<T>::value;
|
||||||
|
|
||||||
|
@ -792,6 +825,58 @@ namespace sol {
|
||||||
return g.get(L, index, tracking);
|
return g.get(L, index, tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
|
||||||
|
return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unqualified_interop_getter<Tu> g{};
|
||||||
|
(void)g;
|
||||||
|
return g.get(L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
|
||||||
|
return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qualified_interop_getter<T> g{};
|
||||||
|
(void)g;
|
||||||
|
return g.get(L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
|
||||||
|
return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unqualified_interop_checker<Tu> c;
|
||||||
|
// VC++ has a bad warning here: shut it up
|
||||||
|
(void)c;
|
||||||
|
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
|
||||||
|
return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qualified_interop_checker<T> c;
|
||||||
|
// 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
|
||||||
|
|
||||||
inline bool maybe_indexable(lua_State* L, int index = -1) {
|
inline bool maybe_indexable(lua_State* L, int index = -1) {
|
||||||
|
@ -868,11 +953,10 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T, typename Arg, typename... Args>
|
template <typename T, typename Arg, typename... Args>
|
||||||
inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
|
inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
typedef meta::all<std::is_lvalue_reference<T>,
|
using use_reference_tag = meta::all<std::is_lvalue_reference<T>,
|
||||||
meta::neg<std::is_const<T>>,
|
meta::neg<std::is_const<T>>,
|
||||||
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
|
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
|
||||||
meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>
|
meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>;
|
||||||
use_reference_tag;
|
|
||||||
using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
|
using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
|
||||||
return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
@ -913,6 +997,32 @@ namespace sol {
|
||||||
return pushcount;
|
return pushcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
|
||||||
|
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unqualified_checker<Tu> c;
|
||||||
|
// VC++ has a bad warning here: shut it up
|
||||||
|
(void)c;
|
||||||
|
return c.check(L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
|
||||||
|
record tracking{};
|
||||||
|
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
||||||
|
auto handler = no_panic;
|
||||||
|
return unqualified_check<T>(L, index, handler);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
template <typename T, typename Handler>
|
||||||
bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
|
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
|
||||||
|
@ -938,32 +1048,6 @@ namespace sol {
|
||||||
return check<T>(L, index, handler);
|
return check<T>(L, index, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
|
||||||
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
typedef meta::unqualified_t<T> Tu;
|
|
||||||
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
|
|
||||||
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unqualified_checker<Tu> c;
|
|
||||||
// VC++ has a bad warning here: shut it up
|
|
||||||
(void)c;
|
|
||||||
return c.check(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
|
||||||
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
|
|
||||||
record tracking{};
|
|
||||||
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
|
||||||
auto handler = no_panic;
|
|
||||||
return unqualified_check<T>(L, index, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
template <typename T, typename Handler>
|
||||||
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
using Tu = meta::unqualified_t<T>;
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
@ -1067,6 +1151,8 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace stack_detail
|
} // namespace stack_detail
|
||||||
|
|
||||||
template <bool b, typename... Args, typename Handler>
|
template <bool b, typename... Args, typename Handler>
|
||||||
|
@ -1159,7 +1245,6 @@ namespace sol {
|
||||||
return get<T>(L, index, tracking);
|
return get<T>(L, index, tracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
|
inline decltype(auto) get_usertype(lua_State* L, int index, record& tracking) {
|
||||||
using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>;
|
using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>;
|
||||||
|
@ -1239,7 +1324,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
|
inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
|
||||||
typedef unique_usertype_traits<T> u_traits;
|
using u_traits = unique_usertype_traits<T>;
|
||||||
void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
|
void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
|
||||||
void* ptr_memory = detail::align_usertype_pointer(raw);
|
void* ptr_memory = detail::align_usertype_pointer(raw);
|
||||||
void* uu_memory = detail::align_usertype_unique<T>(raw);
|
void* uu_memory = detail::align_usertype_unique<T>(raw);
|
||||||
|
@ -1250,9 +1335,10 @@ namespace sol {
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
inline void modify_unique_usertype(const stack_reference& obj, F&& f) {
|
inline void modify_unique_usertype(const stack_reference& obj, F&& f) {
|
||||||
typedef meta::bind_traits<meta::unqualified_t<F>> bt;
|
using bt = meta::bind_traits<meta::unqualified_t<F>>;
|
||||||
typedef typename bt::template arg_at<0> T;
|
using T = typename bt::template arg_at<0>;
|
||||||
modify_unique_usertype_as<meta::unqualified_t<T>>(obj, std::forward<F>(f));
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace stack
|
} // namespace stack
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace sol { namespace stack {
|
||||||
|
|
||||||
template <typename BaseCh, typename S>
|
template <typename BaseCh, typename S>
|
||||||
inline S get_into(lua_State* L, int index, record& tracking) {
|
inline S get_into(lua_State* L, int index, record& tracking) {
|
||||||
typedef typename S::value_type Ch;
|
using Ch = typename S::value_type;
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
size_t len;
|
size_t len;
|
||||||
auto utf8p = lua_tolstring(L, index, &len);
|
auto utf8p = lua_tolstring(L, index, &len);
|
||||||
|
@ -114,16 +114,7 @@ namespace sol { namespace stack {
|
||||||
convert<BaseCh>(strb, stre, copy_units);
|
convert<BaseCh>(strb, stre, copy_units);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
} // namespace stack_detail
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
struct userdata_getter<U> {
|
|
||||||
typedef stack_detail::strip_extensible_t<U> T;
|
|
||||||
|
|
||||||
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
|
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct unqualified_getter {
|
struct unqualified_getter {
|
||||||
|
@ -139,6 +130,22 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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>
|
template <typename T>
|
||||||
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static T get(lua_State* L, int index, record& tracking) {
|
||||||
|
@ -796,9 +803,7 @@ namespace sol { namespace stack {
|
||||||
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
||||||
void* memory = lua_touserdata(L, index);
|
void* memory = lua_touserdata(L, index);
|
||||||
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
||||||
userdata_getter<extensible<T>> ug;
|
auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
|
||||||
(void)ug;
|
|
||||||
auto ugr = ug.get(L, index, memory, tracking);
|
|
||||||
if (ugr.first) {
|
if (ugr.first) {
|
||||||
return ugr.second;
|
return ugr.second;
|
||||||
}
|
}
|
||||||
|
@ -951,9 +956,9 @@ namespace sol { namespace stack {
|
||||||
return V();
|
return V();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using T = std::variant_alternative_t<0, V>;
|
//using T = std::variant_alternative_t<0, V>;
|
||||||
std::abort();
|
std::abort();
|
||||||
/*return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));*/
|
//return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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-11 10:50:20.059748 UTC
|
// Generated 2019-02-14 07:36:40.809154 UTC
|
||||||
// This header was generated with sol v2.20.6 (revision 4fd197d)
|
// This header was generated with sol v2.20.6 (revision ffe77cc)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2019-02-11 10:50:18.478770 UTC
|
// Generated 2019-02-14 07:36:40.566598 UTC
|
||||||
// This header was generated with sol v2.20.6 (revision 4fd197d)
|
// This header was generated with sol v2.20.6 (revision ffe77cc)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
|
@ -4485,20 +4485,26 @@ namespace sol {
|
||||||
/// \synopsis template <class U> optional(const optional<U> &rhs);
|
/// \synopsis template <class U> optional(const optional<U> &rhs);
|
||||||
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
|
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr>
|
||||||
optional(const optional<U>& rhs) {
|
optional(const optional<U>& rhs) {
|
||||||
this->construct(*rhs);
|
if (rhs.has_value()) {
|
||||||
|
this->construct(*rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
|
template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr>
|
||||||
explicit optional(const optional<U>& rhs) {
|
explicit optional(const optional<U>& rhs) {
|
||||||
this->construct(*rhs);
|
if (rhs.has_value()) {
|
||||||
|
this->construct(*rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converting move constructor.
|
/// Converting move constructor.
|
||||||
/// \synopsis template <class U> optional(optional<U> &&rhs);
|
/// \synopsis template <class U> optional(optional<U> &&rhs);
|
||||||
template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
|
template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
|
||||||
optional(optional<U>&& rhs) {
|
optional(optional<U>&& rhs) {
|
||||||
this->construct(std::move(*rhs));
|
if (rhs.has_value()) {
|
||||||
|
this->construct(std::move(*rhs));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
|
@ -5847,7 +5853,7 @@ namespace sol { namespace detail {
|
||||||
template <typename Arg, typename... Args,
|
template <typename Arg, typename... Args,
|
||||||
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
||||||
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
||||||
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){};
|
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
|
||||||
|
|
||||||
T& value() {
|
T& value() {
|
||||||
return value_;
|
return value_;
|
||||||
|
@ -5868,7 +5874,7 @@ namespace sol { namespace detail {
|
||||||
template <typename Arg, typename... Args,
|
template <typename Arg, typename... Args,
|
||||||
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
|
||||||
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
|
||||||
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){};
|
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
|
||||||
|
|
||||||
ebco& operator=(const ebco&) = default;
|
ebco& operator=(const ebco&) = default;
|
||||||
ebco& operator=(ebco&&) = default;
|
ebco& operator=(ebco&&) = default;
|
||||||
|
@ -8751,14 +8757,13 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* align_usertype_pointer(void* ptr) {
|
inline void* align_usertype_pointer(void* ptr) {
|
||||||
typedef std::integral_constant<bool,
|
using use_align = std::integral_constant<bool,
|
||||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||||
false
|
false
|
||||||
#else
|
#else
|
||||||
(std::alignment_of<void*>::value > 1)
|
(std::alignment_of<void*>::value > 1)
|
||||||
#endif
|
#endif
|
||||||
>
|
>;
|
||||||
use_align;
|
|
||||||
if (!use_align::value) {
|
if (!use_align::value) {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -8768,14 +8773,13 @@ namespace sol {
|
||||||
|
|
||||||
template <bool pre_aligned = false, bool pre_shifted = false>
|
template <bool pre_aligned = false, bool pre_shifted = false>
|
||||||
inline void* align_usertype_unique_destructor(void* ptr) {
|
inline void* align_usertype_unique_destructor(void* ptr) {
|
||||||
typedef std::integral_constant<bool,
|
using use_align = std::integral_constant<bool,
|
||||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||||
false
|
false
|
||||||
#else
|
#else
|
||||||
(std::alignment_of<unique_destructor>::value > 1)
|
(std::alignment_of<unique_destructor>::value > 1)
|
||||||
#endif
|
#endif
|
||||||
>
|
>;
|
||||||
use_align;
|
|
||||||
if (!pre_aligned) {
|
if (!pre_aligned) {
|
||||||
ptr = align_usertype_pointer(ptr);
|
ptr = align_usertype_pointer(ptr);
|
||||||
}
|
}
|
||||||
|
@ -8791,14 +8795,13 @@ namespace sol {
|
||||||
|
|
||||||
template <bool pre_aligned = false, bool pre_shifted = false>
|
template <bool pre_aligned = false, bool pre_shifted = false>
|
||||||
inline void* align_usertype_unique_tag(void* ptr) {
|
inline void* align_usertype_unique_tag(void* ptr) {
|
||||||
typedef std::integral_constant<bool,
|
using use_align = std::integral_constant<bool,
|
||||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||||
false
|
false
|
||||||
#else
|
#else
|
||||||
(std::alignment_of<unique_tag>::value > 1)
|
(std::alignment_of<unique_tag>::value > 1)
|
||||||
#endif
|
#endif
|
||||||
>
|
>;
|
||||||
use_align;
|
|
||||||
if (!pre_aligned) {
|
if (!pre_aligned) {
|
||||||
ptr = align_usertype_unique_destructor(ptr);
|
ptr = align_usertype_unique_destructor(ptr);
|
||||||
}
|
}
|
||||||
|
@ -9243,7 +9246,9 @@ namespace sol {
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct qualified_getter;
|
struct qualified_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct userdata_getter;
|
struct qualified_interop_getter;
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct unqualified_interop_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct popper;
|
struct popper;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
|
@ -9253,7 +9258,9 @@ namespace sol {
|
||||||
template <typename T, type = lua_type_of<T>::value, typename = void>
|
template <typename T, type = lua_type_of<T>::value, typename = void>
|
||||||
struct qualified_checker;
|
struct qualified_checker;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct userdata_checker;
|
struct qualified_interop_checker;
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct unqualified_interop_checker;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct unqualified_check_getter;
|
struct unqualified_check_getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
|
@ -9299,6 +9306,19 @@ namespace sol {
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_adl_sol_lua_interop_get {
|
||||||
|
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 {
|
struct is_adl_sol_lua_check {
|
||||||
private:
|
private:
|
||||||
|
@ -9312,6 +9332,19 @@ namespace sol {
|
||||||
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
static constexpr bool value = std::is_same_v<decltype(test<T>(nullptr)), meta::sfinae_yes_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_adl_sol_lua_interop_check {
|
||||||
|
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 {
|
struct is_adl_sol_lua_check_get {
|
||||||
private:
|
private:
|
||||||
|
@ -9353,9 +9386,15 @@ namespace sol {
|
||||||
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 = is_adl_sol_lua_get<T>::value;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_adl_sol_lua_interop_get_v = is_adl_sol_lua_interop_get<T>::value;
|
||||||
|
|
||||||
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 = is_adl_sol_lua_check<T>::value;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_adl_sol_lua_interop_check_v = is_adl_sol_lua_interop_check<T>::value;
|
||||||
|
|
||||||
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 = is_adl_sol_lua_check_get<T>::value;
|
||||||
|
|
||||||
|
@ -9444,6 +9483,58 @@ namespace sol {
|
||||||
return g.get(L, index, tracking);
|
return g.get(L, index, tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) {
|
||||||
|
return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unqualified_interop_getter<Tu> g{};
|
||||||
|
(void)g;
|
||||||
|
return g.get(L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) {
|
||||||
|
return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qualified_interop_getter<T> g{};
|
||||||
|
(void)g;
|
||||||
|
return g.get(L, index, unadjusted_pointer, tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) {
|
||||||
|
return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unqualified_interop_checker<Tu> c;
|
||||||
|
// VC++ has a bad warning here: shut it up
|
||||||
|
(void)c;
|
||||||
|
return c.check(L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) {
|
||||||
|
return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qualified_interop_checker<T> c;
|
||||||
|
// 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
|
||||||
|
|
||||||
inline bool maybe_indexable(lua_State* L, int index = -1) {
|
inline bool maybe_indexable(lua_State* L, int index = -1) {
|
||||||
|
@ -9520,11 +9611,10 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T, typename Arg, typename... Args>
|
template <typename T, typename Arg, typename... Args>
|
||||||
inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
|
inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) {
|
||||||
typedef meta::all<std::is_lvalue_reference<T>,
|
using use_reference_tag = meta::all<std::is_lvalue_reference<T>,
|
||||||
meta::neg<std::is_const<T>>,
|
meta::neg<std::is_const<T>>,
|
||||||
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
|
meta::neg<is_lua_primitive<meta::unqualified_t<T>>>,
|
||||||
meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>
|
meta::neg<is_unique_usertype<meta::unqualified_t<T>>>>;
|
||||||
use_reference_tag;
|
|
||||||
using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
|
using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>;
|
||||||
return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
@ -9565,6 +9655,32 @@ namespace sol {
|
||||||
return pushcount;
|
return pushcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
|
||||||
|
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unqualified_checker<Tu> c;
|
||||||
|
// VC++ has a bad warning here: shut it up
|
||||||
|
(void)c;
|
||||||
|
return c.check(L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Handler>
|
||||||
|
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
|
||||||
|
record tracking{};
|
||||||
|
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
||||||
|
auto handler = no_panic;
|
||||||
|
return unqualified_check<T>(L, index, handler);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
template <typename T, typename Handler>
|
||||||
bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
|
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) {
|
||||||
|
@ -9590,32 +9706,6 @@ namespace sol {
|
||||||
return check<T>(L, index, handler);
|
return check<T>(L, index, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
|
||||||
bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
|
||||||
typedef meta::unqualified_t<T> Tu;
|
|
||||||
if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) {
|
|
||||||
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unqualified_checker<Tu> c;
|
|
||||||
// VC++ has a bad warning here: shut it up
|
|
||||||
(void)c;
|
|
||||||
return c.check(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
|
||||||
bool unqualified_check(lua_State* L, int index, Handler&& handler) {
|
|
||||||
record tracking{};
|
|
||||||
return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) {
|
|
||||||
auto handler = no_panic;
|
|
||||||
return unqualified_check<T>(L, index, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Handler>
|
template <typename T, typename Handler>
|
||||||
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
using Tu = meta::unqualified_t<T>;
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
@ -9890,7 +9980,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
|
inline void modify_unique_usertype_as(const stack_reference& obj, F&& f) {
|
||||||
typedef unique_usertype_traits<T> u_traits;
|
using u_traits = unique_usertype_traits<T>;
|
||||||
void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
|
void* raw = lua_touserdata(obj.lua_state(), obj.stack_index());
|
||||||
void* ptr_memory = detail::align_usertype_pointer(raw);
|
void* ptr_memory = detail::align_usertype_pointer(raw);
|
||||||
void* uu_memory = detail::align_usertype_unique<T>(raw);
|
void* uu_memory = detail::align_usertype_unique<T>(raw);
|
||||||
|
@ -9901,9 +9991,10 @@ namespace sol {
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
inline void modify_unique_usertype(const stack_reference& obj, F&& f) {
|
inline void modify_unique_usertype(const stack_reference& obj, F&& f) {
|
||||||
typedef meta::bind_traits<meta::unqualified_t<F>> bt;
|
using bt = meta::bind_traits<meta::unqualified_t<F>>;
|
||||||
typedef typename bt::template arg_at<0> T;
|
using T = typename bt::template arg_at<0>;
|
||||||
modify_unique_usertype_as<meta::unqualified_t<T>>(obj, std::forward<F>(f));
|
using Tu = meta::unqualified_t<T>;
|
||||||
|
modify_unique_usertype_as<Tu>(obj, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace stack
|
} // namespace stack
|
||||||
|
@ -10098,13 +10189,21 @@ namespace sol { namespace stack {
|
||||||
} // namespace stack_detail
|
} // namespace stack_detail
|
||||||
|
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct userdata_checker {
|
struct unqualified_interop_checker {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State*, int, type, Handler&&, record&) {
|
static bool check(lua_State*, int, type, Handler&&, record&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, typename>
|
||||||
|
struct qualified_interop_checker {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
return stack_detail::unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, type expected, typename>
|
template <typename T, type expected, typename>
|
||||||
struct unqualified_checker {
|
struct unqualified_checker {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
|
@ -10473,15 +10572,13 @@ namespace sol { namespace stack {
|
||||||
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);
|
||||||
return check(types<T>(), L, index, indextype, handler, tracking);
|
return check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename Handler>
|
template <typename U, typename Handler>
|
||||||
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||||
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
||||||
userdata_checker<extensible<T>> uc;
|
if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
|
||||||
(void)uc;
|
|
||||||
if (uc.check(L, index, indextype, handler, tracking)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // interop extensibility
|
#endif // interop extensibility
|
||||||
|
@ -10490,8 +10587,7 @@ namespace sol { namespace stack {
|
||||||
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
|
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::
|
if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value)
|
||||||
value)
|
|
||||||
return true;
|
return true;
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -11175,7 +11271,7 @@ namespace sol { namespace stack {
|
||||||
|
|
||||||
template <typename BaseCh, typename S>
|
template <typename BaseCh, typename S>
|
||||||
inline S get_into(lua_State* L, int index, record& tracking) {
|
inline S get_into(lua_State* L, int index, record& tracking) {
|
||||||
typedef typename S::value_type Ch;
|
using Ch = typename S::value_type;
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
size_t len;
|
size_t len;
|
||||||
auto utf8p = lua_tolstring(L, index, &len);
|
auto utf8p = lua_tolstring(L, index, &len);
|
||||||
|
@ -11192,16 +11288,7 @@ namespace sol { namespace stack {
|
||||||
convert<BaseCh>(strb, stre, copy_units);
|
convert<BaseCh>(strb, stre, copy_units);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
} // namespace stack_detail
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
struct userdata_getter<U> {
|
|
||||||
typedef stack_detail::strip_extensible_t<U> T;
|
|
||||||
|
|
||||||
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
|
|
||||||
return { false, nullptr };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct unqualified_getter {
|
struct unqualified_getter {
|
||||||
|
@ -11217,6 +11304,22 @@ namespace sol { namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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>
|
template <typename T>
|
||||||
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
struct unqualified_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
|
||||||
static T get(lua_State* L, int index, record& tracking) {
|
static T get(lua_State* L, int index, record& tracking) {
|
||||||
|
@ -11874,9 +11977,7 @@ namespace sol { namespace stack {
|
||||||
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
||||||
void* memory = lua_touserdata(L, index);
|
void* memory = lua_touserdata(L, index);
|
||||||
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
|
||||||
userdata_getter<extensible<T>> ug;
|
auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking);
|
||||||
(void)ug;
|
|
||||||
auto ugr = ug.get(L, index, memory, tracking);
|
|
||||||
if (ugr.first) {
|
if (ugr.first) {
|
||||||
return ugr.second;
|
return ugr.second;
|
||||||
}
|
}
|
||||||
|
@ -12028,9 +12129,9 @@ namespace sol { namespace stack {
|
||||||
return V();
|
return V();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using T = std::variant_alternative_t<0, V>;
|
//using T = std::variant_alternative_t<0, V>;
|
||||||
std::abort();
|
std::abort();
|
||||||
/*return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));*/
|
//return V(std::in_place_index<0>, stack::get<T>(L, index, tracking));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ function(CREATE_TEST test_target_name test_name target_sol)
|
||||||
else()
|
else()
|
||||||
target_compile_options(${test_target_name}
|
target_compile_options(${test_target_name}
|
||||||
PRIVATE -std=c++1z
|
PRIVATE -std=c++1z
|
||||||
-Wall -Wpendatic -Werror -pedantic -pedantic-errors
|
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
|
||||||
-Wno-noexcept-type -pthread
|
-Wno-noexcept-type -pthread
|
||||||
-Wno-unknown-warning -Wno-unknown-warning-option)
|
-Wno-unknown-warning -Wno-unknown-warning-option)
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,31 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
struct woof {
|
||||||
|
int var;
|
||||||
|
|
||||||
|
int func(int x) {
|
||||||
|
return var + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
double func2(int x, int y) {
|
||||||
|
return var + x + y + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string func2s(int x, std::string y) {
|
||||||
|
return y + " " + std::to_string(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct thing {
|
||||||
|
int v = 100;
|
||||||
|
|
||||||
|
thing() {
|
||||||
|
}
|
||||||
|
thing(int x) : v(x) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct non_copyable {
|
struct non_copyable {
|
||||||
non_copyable() = default;
|
non_copyable() = default;
|
||||||
non_copyable(non_copyable&& other) noexcept = default;
|
non_copyable(non_copyable&& other) noexcept = default;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
297
tests/runtime_tests/source/container_semantics.custom.cpp
Normal file
297
tests/runtime_tests/source/container_semantics.custom.cpp
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <numeric> // std::iota
|
||||||
|
|
||||||
|
|
||||||
|
struct my_object {
|
||||||
|
private:
|
||||||
|
std::vector<int> mdata;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const void* last_printed;
|
||||||
|
|
||||||
|
my_object(int sz) : mdata() {
|
||||||
|
mdata.resize(sz);
|
||||||
|
std::iota(mdata.begin(), mdata.end(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(std::size_t count, int value) {
|
||||||
|
for (; count > 0; --count) {
|
||||||
|
mdata.push_back(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // Container requirements, as per the C++ standard
|
||||||
|
using value_type = int;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using iterator = decltype(mdata)::iterator;
|
||||||
|
using const_iterator = decltype(mdata)::const_iterator;
|
||||||
|
using difference_type = decltype(mdata)::difference_type;
|
||||||
|
using size_type = decltype(mdata)::size_type;
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return iterator(mdata.begin());
|
||||||
|
}
|
||||||
|
iterator end() {
|
||||||
|
return iterator(mdata.end());
|
||||||
|
}
|
||||||
|
const_iterator begin() const {
|
||||||
|
return const_iterator(mdata.begin());
|
||||||
|
}
|
||||||
|
const_iterator end() const {
|
||||||
|
return const_iterator(mdata.end());
|
||||||
|
}
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return begin();
|
||||||
|
}
|
||||||
|
const_iterator cend() const {
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
size_type size() const noexcept {
|
||||||
|
return mdata.size();
|
||||||
|
}
|
||||||
|
size_type max_size() const noexcept {
|
||||||
|
return mdata.max_size();
|
||||||
|
}
|
||||||
|
void push_back(const value_type& v) {
|
||||||
|
mdata.push_back(v);
|
||||||
|
}
|
||||||
|
void insert(const_iterator where, const value_type& v) {
|
||||||
|
mdata.insert(where, v);
|
||||||
|
}
|
||||||
|
bool empty() const noexcept {
|
||||||
|
return mdata.empty();
|
||||||
|
}
|
||||||
|
bool operator==(const my_object& right) const {
|
||||||
|
return mdata == right.mdata;
|
||||||
|
}
|
||||||
|
bool operator!=(const my_object& right) const noexcept {
|
||||||
|
return mdata != right.mdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int>& data() {
|
||||||
|
return mdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<int>& data() const {
|
||||||
|
return mdata;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const void* my_object::last_printed = nullptr;
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& ostr, const my_object& mo) {
|
||||||
|
my_object::last_printed = static_cast<const void*>(&mo);
|
||||||
|
ostr << "{ ";
|
||||||
|
const auto& v = mo.data();
|
||||||
|
if (v.empty()) {
|
||||||
|
ostr << "empty";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ostr << v[0];
|
||||||
|
for (std::size_t i = 1; i < v.size(); ++i) {
|
||||||
|
ostr << ", " << v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ostr << " }";
|
||||||
|
|
||||||
|
return ostr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
template <>
|
||||||
|
struct is_container<my_object> : std::false_type {};
|
||||||
|
} // namespace sol
|
||||||
|
|
||||||
|
TEST_CASE("containers/as_container reference", "test that we can force a container to be treated like one despite is_container being false_type") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<my_object>("my_object",
|
||||||
|
sol::constructors<my_object(int)>(),
|
||||||
|
sol::call_constructor,
|
||||||
|
sol::constructors<my_object(int)>(),
|
||||||
|
"size",
|
||||||
|
&my_object::size,
|
||||||
|
"iterable",
|
||||||
|
[](my_object& mo) { return sol::as_container(mo); });
|
||||||
|
|
||||||
|
#if SOL_LUA_VERSION > 501
|
||||||
|
auto result1 = lua.safe_script(R"(
|
||||||
|
mop = my_object.new(20)
|
||||||
|
for i, v in pairs(mop) do
|
||||||
|
assert(i == v)
|
||||||
|
end
|
||||||
|
print(mop)
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
REQUIRE_NOTHROW([&]() {
|
||||||
|
my_object& mo = lua["mop"];
|
||||||
|
REQUIRE((&mo == my_object::last_printed));
|
||||||
|
}());
|
||||||
|
#endif
|
||||||
|
auto result2 = lua.safe_script(R"(
|
||||||
|
mo = my_object(10)
|
||||||
|
c_mo = mo
|
||||||
|
c_iterable = mo:iterable()
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(result2.valid());
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW([&]() {
|
||||||
|
my_object& mo = lua["c_mo"];
|
||||||
|
my_object& mo_iterable = lua["c_iterable"];
|
||||||
|
REQUIRE(&mo == &mo_iterable);
|
||||||
|
REQUIRE(mo == mo_iterable);
|
||||||
|
}());
|
||||||
|
|
||||||
|
auto result3 = lua.safe_script(R"(
|
||||||
|
s1 = c_mo:size()
|
||||||
|
s1_len = #c_mo
|
||||||
|
s1_iterable = c_iterable:size()
|
||||||
|
s1_iterable_len = #c_iterable
|
||||||
|
)");
|
||||||
|
REQUIRE(result3.valid());
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW([&]() {
|
||||||
|
std::size_t s1 = lua["s1"];
|
||||||
|
std::size_t s1_len = lua["s1_len"];
|
||||||
|
std::size_t s1_iterable = lua["s1_iterable"];
|
||||||
|
std::size_t s1_iterable_len = lua["s1_iterable_len"];
|
||||||
|
REQUIRE(s1 == 10);
|
||||||
|
REQUIRE(s1 == s1_len);
|
||||||
|
REQUIRE(s1 == s1_iterable_len);
|
||||||
|
REQUIRE(s1_iterable == s1_iterable_len);
|
||||||
|
}());
|
||||||
|
|
||||||
|
auto result4 = lua.safe_script(R"(
|
||||||
|
for i=1,#c_mo do
|
||||||
|
v_iterable = c_iterable[i]
|
||||||
|
assert(v_iterable == i)
|
||||||
|
end
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(result4.valid());
|
||||||
|
|
||||||
|
auto result5 = lua.safe_script(R"(
|
||||||
|
mo(5, 20)
|
||||||
|
c_iterable:insert(1, 100)
|
||||||
|
v1 = c_iterable[1]
|
||||||
|
s2 = c_mo:size()
|
||||||
|
s2_len = #c_mo
|
||||||
|
s2_iterable = c_iterable:size()
|
||||||
|
s2_iterable_len = #c_iterable
|
||||||
|
print(mo)
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(result5.valid());
|
||||||
|
|
||||||
|
int v1 = lua["v1"];
|
||||||
|
std::size_t s2 = lua["s2"];
|
||||||
|
std::size_t s2_len = lua["s2_len"];
|
||||||
|
std::size_t s2_iterable = lua["s2_iterable"];
|
||||||
|
std::size_t s2_iterable_len = lua["s2_iterable_len"];
|
||||||
|
REQUIRE(v1 == 100);
|
||||||
|
REQUIRE(s2 == 16);
|
||||||
|
REQUIRE(s2 == s2_len);
|
||||||
|
REQUIRE(s2 == s2_iterable_len);
|
||||||
|
REQUIRE(s2_iterable == s2_iterable_len);
|
||||||
|
|
||||||
|
my_object& mo = lua["mo"];
|
||||||
|
REQUIRE(&mo == my_object::last_printed);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/as_container", "test that we can force a container to be treated like one despite the trait being false using the proper marker") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.set_function("f", [](int v) { return sol::as_container(my_object(v)); });
|
||||||
|
|
||||||
|
#if SOL_LUA_VERSION > 501
|
||||||
|
auto result1 = lua.safe_script(R"(
|
||||||
|
mop = f(20)
|
||||||
|
for i, v in pairs(mop) do
|
||||||
|
assert(i == v)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
#endif
|
||||||
|
auto result2 = lua.safe_script(R"(
|
||||||
|
mo = f(10)
|
||||||
|
c_iterable = mo
|
||||||
|
)");
|
||||||
|
REQUIRE(result2.valid());
|
||||||
|
|
||||||
|
{
|
||||||
|
my_object& mo = lua["mo"];
|
||||||
|
my_object& mo_iterable = lua["c_iterable"];
|
||||||
|
REQUIRE(&mo == &mo_iterable);
|
||||||
|
REQUIRE(mo == mo_iterable);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result3 = lua.safe_script(R"(
|
||||||
|
s1_iterable = c_iterable:size()
|
||||||
|
s1_iterable_len = #c_iterable
|
||||||
|
)");
|
||||||
|
REQUIRE(result3.valid());
|
||||||
|
|
||||||
|
{
|
||||||
|
std::size_t s1_iterable = lua["s1_iterable"];
|
||||||
|
std::size_t s1_iterable_len = lua["s1_iterable_len"];
|
||||||
|
REQUIRE(s1_iterable == 10);
|
||||||
|
REQUIRE(s1_iterable == s1_iterable_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result4 = lua.safe_script(R"(
|
||||||
|
for i=1,#c_iterable do
|
||||||
|
v_iterable = c_iterable[i]
|
||||||
|
assert(v_iterable == i)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
REQUIRE(result4.valid());
|
||||||
|
|
||||||
|
auto result5 = lua.safe_script(R"(
|
||||||
|
c_iterable:insert(1, 100)
|
||||||
|
v1 = c_iterable:get(1)
|
||||||
|
s2_iterable = c_iterable:size()
|
||||||
|
s2_iterable_len = #c_iterable
|
||||||
|
)");
|
||||||
|
REQUIRE(result5.valid());
|
||||||
|
|
||||||
|
{
|
||||||
|
int v1 = lua["v1"];
|
||||||
|
std::size_t s2_iterable = lua["s2_iterable"];
|
||||||
|
std::size_t s2_iterable_len = lua["s2_iterable_len"];
|
||||||
|
REQUIRE(v1 == 100);
|
||||||
|
REQUIRE(s2_iterable_len == 11);
|
||||||
|
REQUIRE(s2_iterable == s2_iterable_len);
|
||||||
|
}
|
||||||
|
}
|
377
tests/runtime_tests/source/container_semantics.ordered.cpp
Normal file
377
tests/runtime_tests/source/container_semantics.ordered.cpp
Normal file
|
@ -0,0 +1,377 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ordered_container_check(sol::state& lua, T& items) {
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script(R"(
|
||||||
|
for i=1,#c do
|
||||||
|
v = c[(i + 10)]
|
||||||
|
assert(v == (i + 10))
|
||||||
|
end
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("c:set(20)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("c:set(16)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r5.valid());
|
||||||
|
auto r1 = lua.safe_script("c:erase(i1)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r3.valid());
|
||||||
|
auto r2 = lua.safe_script("c:erase(i2)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r4.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c:add(17)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c[18] = true", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
auto backit = items.begin();
|
||||||
|
std::size_t len = 0;
|
||||||
|
{
|
||||||
|
auto e = items.end();
|
||||||
|
auto last = backit;
|
||||||
|
for (; backit != e; ++backit, ++len) {
|
||||||
|
if (backit == e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = backit;
|
||||||
|
}
|
||||||
|
backit = last;
|
||||||
|
}
|
||||||
|
const int& first = *items.begin();
|
||||||
|
const int& last = *backit;
|
||||||
|
int i1 = lua["i1"];
|
||||||
|
int i2 = lua["i2"];
|
||||||
|
int io1 = lua["io1"];
|
||||||
|
int io2 = lua["io2"];
|
||||||
|
std::size_t s1 = lua["s1"];
|
||||||
|
std::size_t s2 = lua["s2"];
|
||||||
|
std::size_t s3 = lua["s3"];
|
||||||
|
int v1 = lua["v1"];
|
||||||
|
int v2 = lua["v2"];
|
||||||
|
int v3 = lua["v3"];
|
||||||
|
int values[] = { 12, 13, 15, 16, 17, 18, 20 };
|
||||||
|
{
|
||||||
|
std::size_t idx = 0;
|
||||||
|
for (const auto& i : items) {
|
||||||
|
const auto& v = values[idx];
|
||||||
|
REQUIRE((i == v));
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REQUIRE((s1 == 7));
|
||||||
|
REQUIRE((s2 == 6));
|
||||||
|
REQUIRE((s3 == 5));
|
||||||
|
REQUIRE((len == 7));
|
||||||
|
REQUIRE((first == 12));
|
||||||
|
REQUIRE((last == 20));
|
||||||
|
REQUIRE((i1 == 11));
|
||||||
|
REQUIRE((i2 == 14));
|
||||||
|
REQUIRE((io1 == 2));
|
||||||
|
REQUIRE((io2 == 3));
|
||||||
|
REQUIRE((v1 == 11));
|
||||||
|
REQUIRE((v2 == 13));
|
||||||
|
REQUIRE((v3 == 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void associative_ordered_container_check(sol::state& lua, T& items) {
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script(R"(
|
||||||
|
for i=1,#c do
|
||||||
|
v = c[(i + 10)]
|
||||||
|
assert(v == (i + 20))
|
||||||
|
end
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("c:set(20, 30)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("c:set(16, 26)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
auto r3 = lua.safe_script("c:set(12, 31)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r3.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r5.valid());
|
||||||
|
auto r1 = lua.safe_script("c:erase(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r3.valid());
|
||||||
|
auto r2 = lua.safe_script("c:erase(14)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r4.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c:add(17, 27)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c[18] = 28", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
auto backit = items.begin();
|
||||||
|
std::size_t len = 0;
|
||||||
|
{
|
||||||
|
auto e = items.end();
|
||||||
|
auto last = backit;
|
||||||
|
for (; backit != e; ++backit, ++len) {
|
||||||
|
if (backit == e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = backit;
|
||||||
|
}
|
||||||
|
backit = last;
|
||||||
|
}
|
||||||
|
const std::pair<const short, int>& first = *items.begin();
|
||||||
|
const std::pair<const short, int>& last = *backit;
|
||||||
|
int i1 = lua["i1"];
|
||||||
|
int i2 = lua["i2"];
|
||||||
|
int io1 = lua["io1"];
|
||||||
|
int io2 = lua["io2"];
|
||||||
|
std::size_t s1 = lua["s1"];
|
||||||
|
std::size_t s2 = lua["s2"];
|
||||||
|
std::size_t s3 = lua["s3"];
|
||||||
|
int v1 = lua["v1"];
|
||||||
|
int v2 = lua["v2"];
|
||||||
|
int v3 = lua["v3"];
|
||||||
|
std::pair<const short, int> values[]
|
||||||
|
= { { (short)12, 31 }, { (short)13, 23 }, { (short)15, 25 }, { (short)16, 26 }, { (short)17, 27 }, { (short)18, 28 }, { (short)20, 30 } };
|
||||||
|
{
|
||||||
|
std::size_t idx = 0;
|
||||||
|
for (const auto& i : items) {
|
||||||
|
const auto& v = values[idx];
|
||||||
|
REQUIRE((i == v));
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REQUIRE((s1 == 7));
|
||||||
|
REQUIRE((s2 == 6));
|
||||||
|
REQUIRE((s3 == 5));
|
||||||
|
REQUIRE((len == 7));
|
||||||
|
REQUIRE((first.first == 12));
|
||||||
|
REQUIRE((last.first == 20));
|
||||||
|
REQUIRE((first.second == 31));
|
||||||
|
REQUIRE((last.second == 30));
|
||||||
|
REQUIRE((i1 == 21));
|
||||||
|
REQUIRE((i2 == 24));
|
||||||
|
REQUIRE((io1 == 2));
|
||||||
|
REQUIRE((io2 == 3));
|
||||||
|
REQUIRE((v1 == 21));
|
||||||
|
REQUIRE((v2 == 23));
|
||||||
|
REQUIRE((v3 == 30));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void associative_ordered_container_key_value_check(sol::state& lua, T& data, T& reflect) {
|
||||||
|
typedef typename T::key_type K;
|
||||||
|
typedef typename T::mapped_type V;
|
||||||
|
lua["collect"] = [&reflect](K k, V v) { reflect.insert({ k, v }); };
|
||||||
|
|
||||||
|
#if SOL_LUA_VERSION > 502
|
||||||
|
lua["val"] = data;
|
||||||
|
auto r = lua.safe_script(R"(
|
||||||
|
for k, v in pairs(val) do
|
||||||
|
collect(k, v)
|
||||||
|
end
|
||||||
|
print()
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
#else
|
||||||
|
reflect = data;
|
||||||
|
#endif
|
||||||
|
REQUIRE((data == reflect));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ordered_lookup_container_check(sol::state& lua, T&) {
|
||||||
|
auto result0 = lua.safe_script("assert(c['a'] == 'a')", sol::script_default_on_error);
|
||||||
|
REQUIRE(result0.valid());
|
||||||
|
auto result1 = lua.safe_script("assert(c['b'] == 'b')", sol::script_default_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
auto result2 = lua.safe_script("assert(c['c'] == 'c')", sol::script_default_on_error);
|
||||||
|
REQUIRE(result2.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/ordered lookup containers", "check ordered container types") {
|
||||||
|
SECTION("set") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::set<int> items{ 11, 12, 13, 14, 15 };
|
||||||
|
lua["c"] = &items;
|
||||||
|
ordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("set string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::set<std::string> items({ "a", "b", "c" });
|
||||||
|
lua["c"] = &items;
|
||||||
|
ordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("multiset") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::multiset<int> items{ 11, 12, 13, 14, 15 };
|
||||||
|
lua["c"] = &items;
|
||||||
|
ordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("multiset string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::multiset<std::string> items({ "a", "b", "c" });
|
||||||
|
lua["c"] = &items;
|
||||||
|
ordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/associative ordered containers", "check associative (map) containers that are ordered fulfill basic functionality requirements") {
|
||||||
|
SECTION("map") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::map<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
associative_ordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("map string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::map<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
ordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("multimap") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::multimap<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
associative_ordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("multimap string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::multimap<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
ordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/associative ordered pairs", "check to make sure pairs works properly for key-value types") {
|
||||||
|
struct bar {};
|
||||||
|
std::unique_ptr<bar> ua(new bar()), ub(new bar()), uc(new bar());
|
||||||
|
bar* a = ua.get();
|
||||||
|
bar* b = ub.get();
|
||||||
|
bar* c = uc.get();
|
||||||
|
|
||||||
|
SECTION("map") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
std::map<std::string, bar*> data({ { "a", a }, { "b", b }, { "c", c } });
|
||||||
|
std::map<std::string, bar*> reflect;
|
||||||
|
associative_ordered_container_key_value_check(lua, data, reflect);
|
||||||
|
}
|
||||||
|
SECTION("multimap") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
std::multimap<std::string, bar*> data({ { "a", a }, { "b", b }, { "c", c } });
|
||||||
|
std::multimap<std::string, bar*> reflect;
|
||||||
|
associative_ordered_container_key_value_check(lua, data, reflect);
|
||||||
|
}
|
||||||
|
}
|
269
tests/runtime_tests/source/container_semantics.unordered.cpp
Normal file
269
tests/runtime_tests/source/container_semantics.unordered.cpp
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void unordered_container_check(sol::state& lua, T& items) {
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("c:set(20)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("c:set(16)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r5.valid());
|
||||||
|
auto r1 = lua.safe_script("c:erase(i1)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r3.valid());
|
||||||
|
auto r2 = lua.safe_script("c:erase(i2)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r4.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c:add(17)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c[18] = true", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
std::size_t len = items.size();
|
||||||
|
int i1 = lua["i1"];
|
||||||
|
int i2 = lua["i2"];
|
||||||
|
std::size_t s1 = lua["s1"];
|
||||||
|
std::size_t s2 = lua["s2"];
|
||||||
|
std::size_t s3 = lua["s3"];
|
||||||
|
int v1 = lua["v1"];
|
||||||
|
int v2 = lua["v2"];
|
||||||
|
int v3 = lua["v3"];
|
||||||
|
int values[] = { 12, 13, 15, 16, 17, 18, 20 };
|
||||||
|
{
|
||||||
|
for (const auto& v : values) {
|
||||||
|
auto it = items.find(v);
|
||||||
|
REQUIRE((it != items.cend()));
|
||||||
|
REQUIRE((*it == v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REQUIRE((s1 == 7));
|
||||||
|
REQUIRE((s2 == 6));
|
||||||
|
REQUIRE((s3 == 5));
|
||||||
|
REQUIRE((len == 7));
|
||||||
|
REQUIRE((i1 == 11));
|
||||||
|
REQUIRE((i2 == 14));
|
||||||
|
REQUIRE((v1 == 11));
|
||||||
|
REQUIRE((v2 == 13));
|
||||||
|
REQUIRE((v3 == 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void associative_unordered_container_check(sol::state& lua, T& items) {
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("i1 = c:find(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("i2 = c:find(14)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("io1 = c:index_of(12)", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("io2 = c:index_of(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("v1 = c:get(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("v2 = c:get(13)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r1 = lua.safe_script("c:set(20, 30)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r2 = lua.safe_script("c:set(16, 26)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
auto r3 = lua.safe_script("c:set(12, 31)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r3.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r5 = lua.safe_script("s1 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r5.valid());
|
||||||
|
auto r1 = lua.safe_script("c:erase(11)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r1.valid());
|
||||||
|
auto r3 = lua.safe_script("s2 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r3.valid());
|
||||||
|
auto r2 = lua.safe_script("c:erase(14)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r2.valid());
|
||||||
|
auto r4 = lua.safe_script("s3 = #c", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r4.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c:add(17, 27)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("c[18] = 28", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r = lua.safe_script("v3 = c[20]", sol::script_pass_on_error);
|
||||||
|
REQUIRE(r.valid());
|
||||||
|
}
|
||||||
|
std::size_t len = items.size();
|
||||||
|
int i1 = lua["i1"];
|
||||||
|
int i2 = lua["i2"];
|
||||||
|
std::size_t s1 = lua["s1"];
|
||||||
|
std::size_t s2 = lua["s2"];
|
||||||
|
std::size_t s3 = lua["s3"];
|
||||||
|
int v1 = lua["v1"];
|
||||||
|
int v2 = lua["v2"];
|
||||||
|
int v3 = lua["v3"];
|
||||||
|
std::pair<const short, int> values[]
|
||||||
|
= { { (short)12, 31 }, { (short)13, 23 }, { (short)15, 25 }, { (short)16, 26 }, { (short)17, 27 }, { (short)18, 28 }, { (short)20, 30 } };
|
||||||
|
{
|
||||||
|
for (const auto& v : values) {
|
||||||
|
auto it = items.find(v.first);
|
||||||
|
REQUIRE((it != items.cend()));
|
||||||
|
REQUIRE((it->second == v.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REQUIRE((s1 == 7));
|
||||||
|
REQUIRE((s2 == 6));
|
||||||
|
REQUIRE((s3 == 5));
|
||||||
|
REQUIRE((len == 7));
|
||||||
|
REQUIRE((i1 == 21));
|
||||||
|
REQUIRE((i2 == 24));
|
||||||
|
REQUIRE((v1 == 21));
|
||||||
|
REQUIRE((v2 == 23));
|
||||||
|
REQUIRE((v3 == 30));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void unordered_lookup_container_check(sol::state& lua, T&) {
|
||||||
|
auto result0 = lua.safe_script("assert(c['a'] == 'a')", sol::script_default_on_error);
|
||||||
|
REQUIRE(result0.valid());
|
||||||
|
auto result1 = lua.safe_script("assert(c['b'] == 'b')", sol::script_default_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
auto result2 = lua.safe_script("assert(c['c'] == 'c')", sol::script_default_on_error);
|
||||||
|
REQUIRE(result2.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/unordered lookup containers", "check ordered container types") {
|
||||||
|
SECTION("unordered_set") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_set<int> items{ 11, 12, 13, 14, 15 };
|
||||||
|
lua["c"] = &items;
|
||||||
|
unordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("unordered_set string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_set<std::string> items({ "a", "b", "c" });
|
||||||
|
lua["c"] = &items;
|
||||||
|
unordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("unordered_multiset") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_multiset<int> items{ 11, 12, 13, 14, 15 };
|
||||||
|
lua["c"] = &items;
|
||||||
|
unordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("unordered_multiset string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_multiset<std::string> items({ "a", "b", "c" });
|
||||||
|
lua["c"] = &items;
|
||||||
|
unordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/associative unordered containers", "check associative (map) containers that are ordered that they fulfill basic requirements") {
|
||||||
|
SECTION("unordered_map") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_map<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
associative_unordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("unordered_map string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
unordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("unordered_multimap") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_multimap<short, int> items{ { (short)11, 21 }, { (short)12, 22 }, { (short)13, 23 }, { (short)14, 24 }, { (short)15, 25 } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
associative_unordered_container_check(lua, items);
|
||||||
|
}
|
||||||
|
SECTION("unordered_multimap string") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::unordered_multimap<std::string, std::string> items{ { "a", "a" }, { "b", "b" }, { "c", "c" } };
|
||||||
|
lua["c"] = &items;
|
||||||
|
unordered_lookup_container_check(lua, items);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,46 +37,6 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
auto test_table_return_one() {
|
|
||||||
return sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
|
|
||||||
}
|
|
||||||
|
|
||||||
auto test_table_return_two() {
|
|
||||||
return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 }, { "two", 2 }, { "three", 3 } });
|
|
||||||
}
|
|
||||||
|
|
||||||
auto test_table_return_three() {
|
|
||||||
return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" }, { "friend", "ThePhD" }, { "project", "sol" } });
|
|
||||||
}
|
|
||||||
|
|
||||||
auto test_table_return_four() {
|
|
||||||
return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } } });
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename T>
|
|
||||||
void check_ordered_values(S& src, T& target) {
|
|
||||||
std::size_t idx = 0;
|
|
||||||
auto b = std::begin(target);
|
|
||||||
auto e = std::end(target);
|
|
||||||
for (; b != e; ++b, ++idx) {
|
|
||||||
const auto& v = src[idx];
|
|
||||||
REQUIRE((*b == v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename S, typename T>
|
|
||||||
void check_unordered_values(S& src, T& target) {
|
|
||||||
std::size_t idx = 0;
|
|
||||||
auto b = std::begin(target);
|
|
||||||
auto e = std::end(target);
|
|
||||||
for (; b != e; ++b, ++idx) {
|
|
||||||
auto sb = std::begin(src);
|
|
||||||
auto se = std::end(src);
|
|
||||||
auto it = std::find(sb, se, *b);
|
|
||||||
REQUIRE((it != se));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
|
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
std::vector<int> v{ 1, 2, 3 };
|
std::vector<int> v{ 1, 2, 3 };
|
||||||
|
@ -98,123 +58,6 @@ TEST_CASE("containers/returns", "make sure that even references to vectors are b
|
||||||
REQUIRE(matching);
|
REQUIRE(matching);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/vector roundtrip", "make sure vectors can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::vector<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::vector<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::vector<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/deque roundtrip", "make sure deques can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::deque<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::deque<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::deque<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/array roundtrip", "make sure arrays can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::array<int, 3> v{ { 1, 2, 3 } };
|
|
||||||
lua.set_function("f", [&]() -> std::array<int, 3>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::array<int, 3> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/list roundtrip", "make sure lists can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::list<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::list<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::list<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/forward_list roundtrip", "make sure forward_lists can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::forward_list<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::forward_list<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::forward_list<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
|
|
||||||
lua.set_function("f", [&]() -> std::map<std::string, int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::map<std::string, int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::unordered_map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
|
|
||||||
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::unordered_map<std::string, int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/unordered_set roundtrip", "make sure unordered_sets can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::unordered_set<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::unordered_set<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::unordered_set<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/set roundtrip", "make sure sets can be round-tripped") {
|
|
||||||
sol::state lua;
|
|
||||||
std::set<int> v{ 1, 2, 3 };
|
|
||||||
lua.set_function("f", [&]() -> std::set<int>& {
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
std::set<int> x = lua["x"];
|
|
||||||
bool areequal = x == v;
|
|
||||||
REQUIRE(areequal);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") {
|
TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") {
|
||||||
typedef std::unordered_map<int, int> bark;
|
typedef std::unordered_map<int, int> bark;
|
||||||
|
|
||||||
|
@ -305,33 +148,6 @@ TEST_CASE("containers/const serialization", "make sure containers are turned int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_CASE("containers/table serialization", "ensure types can be serialized as tables still") {
|
|
||||||
typedef std::vector<int> woof;
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries();
|
|
||||||
lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }));
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
|
|
||||||
lua.set("b", sol::as_table(w));
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
lua.set("b", sol::as_table(&w));
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
lua.set("b", sol::as_table(std::ref(w)));
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/const correctness", "usertype metatable names should reasonably ignore const attributes") {
|
TEST_CASE("containers/const correctness", "usertype metatable names should reasonably ignore const attributes") {
|
||||||
struct Vec {
|
struct Vec {
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
|
@ -369,84 +185,6 @@ end
|
||||||
REQUIRE(pfr2.valid());
|
REQUIRE(pfr2.valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/arbitrary creation", "userdata and tables should be usable from standard containers") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
lua.set_function("test_one", test_table_return_one);
|
|
||||||
lua.set_function("test_two", test_table_return_two);
|
|
||||||
lua.set_function("test_three", test_table_return_three);
|
|
||||||
lua.set_function("test_four", test_table_return_four);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("a = test_one()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("b = test_two()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("c = test_three()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("d = test_four()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(#a == 10, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(a[3] == 3, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(b.one == 1, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(b.three == 3, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(c.name == 'Rapptz', 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(c.project == 'sol', 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(d.one == 1, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(d.three == 3, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(d.four == 4, 'error')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::table a = lua.get<sol::table>("a");
|
|
||||||
sol::table b = lua.get<sol::table>("b");
|
|
||||||
sol::table c = lua.get<sol::table>("c");
|
|
||||||
sol::table d = lua["d"];
|
|
||||||
|
|
||||||
REQUIRE(a.size() == 10ULL);
|
|
||||||
REQUIRE(a.get<int>(3) == 3);
|
|
||||||
REQUIRE(b.get<int>("one") == 1);
|
|
||||||
REQUIRE(b.get<int>("three") == 3);
|
|
||||||
REQUIRE(c.get<std::string>("name") == "Rapptz");
|
|
||||||
REQUIRE(c.get<std::string>("project") == "sol");
|
|
||||||
REQUIRE(d.get<int>("one") == 1);
|
|
||||||
REQUIRE(d.get<int>("three") == 3);
|
|
||||||
REQUIRE(d.get<int>("four") == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/usertype transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") {
|
TEST_CASE("containers/usertype transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") {
|
||||||
class A {
|
class A {
|
||||||
public:
|
public:
|
||||||
|
@ -616,41 +354,6 @@ TEST_CASE("containers/to_args", "Test that the to_args abstractions works") {
|
||||||
REQUIRE(d == 12);
|
REQUIRE(d == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly") {
|
|
||||||
struct thing {
|
|
||||||
int x = 20;
|
|
||||||
};
|
|
||||||
thing t{};
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries();
|
|
||||||
|
|
||||||
lua.set_function("f", [&t]() {
|
|
||||||
return std::vector<thing*>(5, &t);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto result1 = lua.safe_script(R"(
|
|
||||||
c = f()
|
|
||||||
)", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
|
|
||||||
auto result2 = lua.safe_script(R"(
|
|
||||||
check = {}
|
|
||||||
local i = 1
|
|
||||||
while c[i] do
|
|
||||||
check[i] = c[i]
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
)", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result2.valid());
|
|
||||||
|
|
||||||
sol::table c = lua["check"];
|
|
||||||
for (std::size_t i = 1; i < 6; ++i) {
|
|
||||||
thing& ct = c[i];
|
|
||||||
REQUIRE(&t == &ct);
|
|
||||||
REQUIRE(ct.x == 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("containers/append idiom", "ensure the append-idiom works as intended") {
|
TEST_CASE("containers/append idiom", "ensure the append-idiom works as intended") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::base);
|
lua.open_libraries(sol::lib::base);
|
||||||
|
@ -670,7 +373,7 @@ function f_append(vec)
|
||||||
vec[#vec + 1] = -54
|
vec[#vec + 1] = -54
|
||||||
print("#vec in lua: " .. #vec)
|
print("#vec in lua: " .. #vec)
|
||||||
end
|
end
|
||||||
)");
|
)", sol::script_pass_on_error);
|
||||||
REQUIRE(result1.valid());
|
REQUIRE(result1.valid());
|
||||||
|
|
||||||
std::vector<int> fill_cmp{ 1, 2, 3 };
|
std::vector<int> fill_cmp{ 1, 2, 3 };
|
||||||
|
@ -716,8 +419,8 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") {
|
TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") {
|
||||||
typedef std::pair<std::string, int> pair_arr_t[5];
|
using pair_arr_t = std::pair<std::string, int>[5];
|
||||||
typedef int arr_t[5];
|
using arr_t = int[5];
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
|
@ -825,52 +528,3 @@ TEST_CASE("containers/pointer types", "check that containers with unique usertyp
|
||||||
int val2 = b2->get();
|
int val2 = b2->get();
|
||||||
REQUIRE(val2 == 500);
|
REQUIRE(val2 == 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/initializer-list", "test initializer lists get pushed as tables directly rather than userdata") {
|
|
||||||
SECTION("array-like") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::table);
|
|
||||||
|
|
||||||
lua["c"] = { 1, 2, 3, 4, 5 };
|
|
||||||
auto result1 = lua.safe_script(R"lua(
|
|
||||||
for k, v in pairs(c) do
|
|
||||||
assert(k == v)
|
|
||||||
end
|
|
||||||
)lua", sol::script_pass_on_error);
|
|
||||||
sol::as_table_t<std::vector<int>> t1vector = lua["c"];
|
|
||||||
sol::as_table_t<std::deque<int>> t1deque = lua["c"];
|
|
||||||
sol::as_table_t<std::list<int>> t1list = lua["c"];
|
|
||||||
sol::as_table_t<std::forward_list<int>> t1flist = lua["c"];
|
|
||||||
sol::as_table_t<std::set<int>> t1set = lua["c"];
|
|
||||||
const int src[5] = { 1, 2, 3, 4, 5 };
|
|
||||||
check_ordered_values(src, t1vector.source);
|
|
||||||
check_ordered_values(src, t1deque.source);
|
|
||||||
check_ordered_values(src, t1list.source);
|
|
||||||
check_ordered_values(src, t1flist.source);
|
|
||||||
check_ordered_values(src, t1set.source);
|
|
||||||
}
|
|
||||||
SECTION("map-like") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::table);
|
|
||||||
std::pair<const std::string, int> src[5]{
|
|
||||||
{ "a", 21 },
|
|
||||||
{ "b", 22 },
|
|
||||||
{ "c", 23 },
|
|
||||||
{ "d", 24 },
|
|
||||||
{ "e", 25 }
|
|
||||||
};
|
|
||||||
|
|
||||||
lua["c"] = std::initializer_list<std::pair<std::string, int>>{
|
|
||||||
{ "a", 21 },
|
|
||||||
{ "b", 22 },
|
|
||||||
{ "c", 23 },
|
|
||||||
{ "d", 24 },
|
|
||||||
{ "e", 25 }
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::as_table_t<std::unordered_map<std::string, int>> t1umap = lua["c"];
|
|
||||||
sol::as_table_t<std::unordered_multimap<std::string, int>> t1ummap = lua["c"];
|
|
||||||
check_unordered_values(src, t1umap.source);
|
|
||||||
check_unordered_values(src, t1ummap.source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
172
tests/runtime_tests/source/containers.roundtrip.cpp
Normal file
172
tests/runtime_tests/source/containers.roundtrip.cpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <forward_list>
|
||||||
|
#include <map>
|
||||||
|
#include <deque>
|
||||||
|
#include <array>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
TEST_CASE("containers/vector roundtrip", "make sure vectors can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::vector<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::vector<int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::vector<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/deque roundtrip", "make sure deques can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::deque<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::deque<int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::deque<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/array roundtrip", "make sure arrays can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::array<int, 3> v{ { 1, 2, 3 } };
|
||||||
|
lua.set_function("f", [&]() -> std::array<int, 3>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::array<int, 3> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/list roundtrip", "make sure lists can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::list<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::list<int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::list<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/forward_list roundtrip", "make sure forward_lists can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::forward_list<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::forward_list<int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::forward_list<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
|
||||||
|
lua.set_function("f", [&]() -> std::map<std::string, int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::map<std::string, int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::unordered_map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
|
||||||
|
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::unordered_map<std::string, int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/unordered_set roundtrip", "make sure unordered_sets can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::unordered_set<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::unordered_set<int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::unordered_set<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/set roundtrip", "make sure sets can be round-tripped") {
|
||||||
|
sol::state lua;
|
||||||
|
std::set<int> v{ 1, 2, 3 };
|
||||||
|
lua.set_function("f", [&]() -> std::set<int>& { return v; });
|
||||||
|
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
std::set<int> x = lua["x"];
|
||||||
|
bool areequal = x == v;
|
||||||
|
REQUIRE(areequal);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly") {
|
||||||
|
struct thing {
|
||||||
|
int x = 20;
|
||||||
|
};
|
||||||
|
thing t{};
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
|
||||||
|
lua.set_function("f", [&t]() { return std::vector<thing*>(5, &t); });
|
||||||
|
|
||||||
|
auto result1 = lua.safe_script(R"(
|
||||||
|
c = f()
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
|
||||||
|
auto result2 = lua.safe_script(R"(
|
||||||
|
check = {}
|
||||||
|
local i = 1
|
||||||
|
while c[i] do
|
||||||
|
check[i] = c[i]
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
)",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
REQUIRE(result2.valid());
|
||||||
|
|
||||||
|
sol::table c = lua["check"];
|
||||||
|
for (std::size_t i = 1; i < 6; ++i) {
|
||||||
|
thing& ct = c[i];
|
||||||
|
REQUIRE(&t == &ct);
|
||||||
|
REQUIRE(ct.x == 20);
|
||||||
|
}
|
||||||
|
}
|
222
tests/runtime_tests/source/containers.table.cpp
Normal file
222
tests/runtime_tests/source/containers.table.cpp
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <forward_list>
|
||||||
|
#include <map>
|
||||||
|
#include <deque>
|
||||||
|
#include <array>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
||||||
|
auto test_table_return_one() {
|
||||||
|
return sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
|
||||||
|
}
|
||||||
|
|
||||||
|
auto test_table_return_two() {
|
||||||
|
return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 }, { "two", 2 }, { "three", 3 } });
|
||||||
|
}
|
||||||
|
|
||||||
|
auto test_table_return_three() {
|
||||||
|
return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" }, { "friend", "ThePhD" }, { "project", "sol" } });
|
||||||
|
}
|
||||||
|
|
||||||
|
auto test_table_return_four() {
|
||||||
|
return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } } });
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename T>
|
||||||
|
void check_ordered_values(S& src, T& target) {
|
||||||
|
std::size_t idx = 0;
|
||||||
|
auto b = std::begin(target);
|
||||||
|
auto e = std::end(target);
|
||||||
|
for (; b != e; ++b, ++idx) {
|
||||||
|
const auto& v = src[idx];
|
||||||
|
REQUIRE((*b == v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename T>
|
||||||
|
void table_check_unordered_values(S& src, T& target) {
|
||||||
|
std::size_t idx = 0;
|
||||||
|
auto b = std::begin(target);
|
||||||
|
auto e = std::end(target);
|
||||||
|
for (; b != e; ++b, ++idx) {
|
||||||
|
auto sb = std::begin(src);
|
||||||
|
auto se = std::end(src);
|
||||||
|
auto it = std::find(sb, se, *b);
|
||||||
|
REQUIRE((it != se));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/arbitrary creation", "userdata and tables should be usable from standard containers") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.set_function("test_one", test_table_return_one);
|
||||||
|
lua.set_function("test_two", test_table_return_two);
|
||||||
|
lua.set_function("test_three", test_table_return_three);
|
||||||
|
lua.set_function("test_four", test_table_return_four);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("a = test_one()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("b = test_two()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("c = test_three()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("d = test_four()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(#a == 10, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(a[3] == 3, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(b.one == 1, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(b.three == 3, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(c.name == 'Rapptz', 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(c.project == 'sol', 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(d.one == 1, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(d.three == 3, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(d.four == 4, 'error')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::table a = lua.get<sol::table>("a");
|
||||||
|
sol::table b = lua.get<sol::table>("b");
|
||||||
|
sol::table c = lua.get<sol::table>("c");
|
||||||
|
sol::table d = lua["d"];
|
||||||
|
|
||||||
|
REQUIRE(a.size() == 10ULL);
|
||||||
|
REQUIRE(a.get<int>(3) == 3);
|
||||||
|
REQUIRE(b.get<int>("one") == 1);
|
||||||
|
REQUIRE(b.get<int>("three") == 3);
|
||||||
|
REQUIRE(c.get<std::string>("name") == "Rapptz");
|
||||||
|
REQUIRE(c.get<std::string>("project") == "sol");
|
||||||
|
REQUIRE(d.get<int>("one") == 1);
|
||||||
|
REQUIRE(d.get<int>("three") == 3);
|
||||||
|
REQUIRE(d.get<int>("four") == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/table serialization", "ensure types can be serialized as tables still") {
|
||||||
|
typedef std::vector<int> woof;
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }));
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
|
||||||
|
lua.set("b", sol::as_table(w));
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
lua.set("b", sol::as_table(&w));
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
lua.set("b", sol::as_table(std::ref(w)));
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("for k, v in ipairs(b) do assert(k == v) end", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/initializer-list", "test initializer lists get pushed as tables directly rather than userdata") {
|
||||||
|
SECTION("array-like") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::table);
|
||||||
|
|
||||||
|
lua["c"] = { 1, 2, 3, 4, 5 };
|
||||||
|
auto result1 = lua.safe_script(R"lua(
|
||||||
|
for k, v in pairs(c) do
|
||||||
|
assert(k == v)
|
||||||
|
end
|
||||||
|
)lua",
|
||||||
|
sol::script_pass_on_error);
|
||||||
|
sol::as_table_t<std::vector<int>> t1vector = lua["c"];
|
||||||
|
sol::as_table_t<std::deque<int>> t1deque = lua["c"];
|
||||||
|
sol::as_table_t<std::list<int>> t1list = lua["c"];
|
||||||
|
sol::as_table_t<std::forward_list<int>> t1flist = lua["c"];
|
||||||
|
sol::as_table_t<std::set<int>> t1set = lua["c"];
|
||||||
|
const int src[5] = { 1, 2, 3, 4, 5 };
|
||||||
|
check_ordered_values(src, t1vector.source);
|
||||||
|
check_ordered_values(src, t1deque.source);
|
||||||
|
check_ordered_values(src, t1list.source);
|
||||||
|
check_ordered_values(src, t1flist.source);
|
||||||
|
check_ordered_values(src, t1set.source);
|
||||||
|
}
|
||||||
|
SECTION("map-like") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::table);
|
||||||
|
std::pair<const std::string, int> src[5]{ { "a", 21 }, { "b", 22 }, { "c", 23 }, { "d", 24 }, { "e", 25 } };
|
||||||
|
|
||||||
|
lua["c"] = std::initializer_list<std::pair<std::string, int>>{ { "a", 21 }, { "b", 22 }, { "c", 23 }, { "d", 24 }, { "e", 25 } };
|
||||||
|
|
||||||
|
sol::as_table_t<std::unordered_map<std::string, int>> t1umap = lua["c"];
|
||||||
|
sol::as_table_t<std::unordered_multimap<std::string, int>> t1ummap = lua["c"];
|
||||||
|
table_check_unordered_values(src, t1umap.source);
|
||||||
|
table_check_unordered_values(src, t1ummap.source);
|
||||||
|
}
|
||||||
|
}
|
289
tests/runtime_tests/source/usertypes.basic.cpp
Normal file
289
tests/runtime_tests/source/usertypes.basic.cpp
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::usertype<fuser> lc = lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
|
||||||
|
|
||||||
|
lua.safe_script(
|
||||||
|
"a = fuser:new()\n"
|
||||||
|
"b = a:add(1)\n"
|
||||||
|
"c = a:add2(1)\n");
|
||||||
|
|
||||||
|
sol::object a = lua.get<sol::object>("a");
|
||||||
|
sol::object b = lua.get<sol::object>("b");
|
||||||
|
sol::object c = lua.get<sol::object>("c");
|
||||||
|
REQUIRE((a.is<sol::userdata_value>()));
|
||||||
|
auto atype = a.get_type();
|
||||||
|
auto btype = b.get_type();
|
||||||
|
auto ctype = c.get_type();
|
||||||
|
REQUIRE((atype == sol::type::userdata));
|
||||||
|
REQUIRE((btype == sol::type::number));
|
||||||
|
REQUIRE((ctype == sol::type::number));
|
||||||
|
int bresult = b.as<int>();
|
||||||
|
int cresult = c.as<int>();
|
||||||
|
REQUIRE(bresult == 1);
|
||||||
|
REQUIRE(cresult == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/usertype fundamentals", "Verify new_usertype registers basic member functions and a constructor") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
|
||||||
|
|
||||||
|
lua.safe_script(
|
||||||
|
"a = fuser.new()\n"
|
||||||
|
"b = a:add(1)\n"
|
||||||
|
"c = a:add2(1)\n");
|
||||||
|
|
||||||
|
sol::object a = lua.get<sol::object>("a");
|
||||||
|
sol::object b = lua.get<sol::object>("b");
|
||||||
|
sol::object c = lua.get<sol::object>("c");
|
||||||
|
REQUIRE((a.is<sol::userdata_value>()));
|
||||||
|
auto atype = a.get_type();
|
||||||
|
auto btype = b.get_type();
|
||||||
|
auto ctype = c.get_type();
|
||||||
|
REQUIRE((atype == sol::type::userdata));
|
||||||
|
REQUIRE((btype == sol::type::number));
|
||||||
|
REQUIRE((ctype == sol::type::number));
|
||||||
|
int bresult = b.as<int>();
|
||||||
|
int cresult = c.as<int>();
|
||||||
|
REQUIRE(bresult == 1);
|
||||||
|
REQUIRE(cresult == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
void sayHello() {
|
||||||
|
std::cout << "Hey\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello);
|
||||||
|
static const std::string code = R"(
|
||||||
|
local t = Test.new()
|
||||||
|
t:sayHello() --Works fine
|
||||||
|
t.sayHello() --Uh oh.
|
||||||
|
)";
|
||||||
|
auto result = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("regressions/one", "issue number 48") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.new_usertype<vars>("vars", "boop", &vars::boop);
|
||||||
|
auto code
|
||||||
|
= "beep = vars.new()\n"
|
||||||
|
"beep.boop = 1";
|
||||||
|
auto result1 = lua.safe_script(code, sol::script_pass_on_error);
|
||||||
|
REQUIRE(result1.valid());
|
||||||
|
// test for segfault
|
||||||
|
auto my_var = lua.get<vars>("beep");
|
||||||
|
auto& my_var_ref = lua.get<vars>("beep");
|
||||||
|
auto* my_var_ptr = lua.get<vars*>("beep");
|
||||||
|
REQUIRE(my_var.boop == 1);
|
||||||
|
REQUIRE(my_var_ref.boop == 1);
|
||||||
|
REQUIRE(my_var_ptr->boop == 1);
|
||||||
|
REQUIRE(std::addressof(my_var_ref) == my_var_ptr);
|
||||||
|
std::cout << "----- end of 3" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
|
||||||
|
struct test {
|
||||||
|
int x = 0;
|
||||||
|
test& set() {
|
||||||
|
x = 10;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
test* pget() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
test create_get() {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fun(int xa) {
|
||||||
|
return xa * 10;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("x = test.new()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(x:set():get() == 10)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("y = x:pointer_get()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("y:set():get()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("y:fun(10)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("x:fun(10)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(y:fun(10) == x:fun(10), '...')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(y:fun(10) == 100, '...')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(y:set():get() == y:set():get(), '...')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("assert(y:set():get() == 10, '...')", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
sol::constructors<sol::types<float, float, float>> ctor;
|
||||||
|
lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script(
|
||||||
|
"v = Vec.new(1, 2, 3)\n"
|
||||||
|
"print(v:length())");
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script(
|
||||||
|
"v = Vec.new(1, 2, 3)\n"
|
||||||
|
"print(v:normalized():length())");
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
{
|
||||||
|
sol::constructors<sol::types<float, float, float>> ctor;
|
||||||
|
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
|
||||||
|
// usertype dies, but still usable in lua!
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script(
|
||||||
|
"collectgarbage()\n"
|
||||||
|
"v = Vec.new(1, 2, 3)\n"
|
||||||
|
"print(v:length())");
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script(
|
||||||
|
"v = Vec.new(1, 2, 3)\n"
|
||||||
|
"print(v:normalized():length())");
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
|
||||||
|
std::cout << "----- in 4" << std::endl;
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.new_usertype<vars>("vars", "boop", &vars::boop);
|
||||||
|
vars var{};
|
||||||
|
vars rvar{};
|
||||||
|
std::cout << "setting beep" << std::endl;
|
||||||
|
lua.set("beep", var);
|
||||||
|
std::cout << "setting rbeep" << std::endl;
|
||||||
|
lua.set("rbeep", std::ref(rvar));
|
||||||
|
std::cout << "getting my_var" << std::endl;
|
||||||
|
auto& my_var = lua.get<vars>("beep");
|
||||||
|
std::cout << "setting rbeep" << std::endl;
|
||||||
|
auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep");
|
||||||
|
vars& proxy_my_var = lua["beep"];
|
||||||
|
std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"];
|
||||||
|
var.boop = 2;
|
||||||
|
rvar.boop = 5;
|
||||||
|
|
||||||
|
// Was return as a value: var must be diferent from "beep"
|
||||||
|
REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var));
|
||||||
|
REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var));
|
||||||
|
REQUIRE((my_var.boop == 0));
|
||||||
|
REQUIRE(var.boop != my_var.boop);
|
||||||
|
|
||||||
|
REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
|
||||||
|
REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
|
||||||
|
REQUIRE(rvar.boop == 5);
|
||||||
|
REQUIRE(rvar.boop == ref_var.boop);
|
||||||
|
std::cout << "----- end of 4" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
|
||||||
|
struct A_x {
|
||||||
|
int x = 201;
|
||||||
|
};
|
||||||
|
struct B_foo {
|
||||||
|
int foo(const A_x* a) {
|
||||||
|
return a->x;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.new_usertype<B_foo>("B", "foo", &B_foo::foo);
|
||||||
|
lua.set("a", A_x());
|
||||||
|
lua.set("b", B_foo());
|
||||||
|
lua.safe_script("x = b:foo(a)");
|
||||||
|
int x = lua["x"];
|
||||||
|
REQUIRE(x == 201);
|
||||||
|
std::cout << "----- end of 6" << std::endl;
|
||||||
|
}
|
206
tests/runtime_tests/source/usertypes.constructors.cpp
Normal file
206
tests/runtime_tests/source/usertypes.constructors.cpp
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
struct matrix_xf {
|
||||||
|
float a, b;
|
||||||
|
|
||||||
|
static matrix_xf from_lua_table(sol::table t) {
|
||||||
|
matrix_xf m;
|
||||||
|
m.a = t[1][1];
|
||||||
|
m.b = t[1][2];
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct matrix_xi {
|
||||||
|
int a, b;
|
||||||
|
|
||||||
|
static matrix_xi from_lua_table(sol::table t) {
|
||||||
|
matrix_xi m;
|
||||||
|
m.a = t[1][1];
|
||||||
|
m.b = t[1][2];
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<thing>("thing", "v", &thing::v, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>());
|
||||||
|
|
||||||
|
lua.safe_script(R"(
|
||||||
|
t = thing(256)
|
||||||
|
)");
|
||||||
|
|
||||||
|
thing& y = lua["t"];
|
||||||
|
INFO(y.v);
|
||||||
|
REQUIRE(y.v == 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/call_constructor factories", "make sure tables can be passed to factory-based call constructors") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
|
||||||
|
lua.new_usertype<matrix_xf>("mat", sol::call_constructor, sol::factories(&matrix_xf::from_lua_table));
|
||||||
|
|
||||||
|
lua.safe_script("m = mat{ {1.1, 2.2} }");
|
||||||
|
|
||||||
|
lua.new_usertype<matrix_xi>("mati", sol::call_constructor, sol::factories(&matrix_xi::from_lua_table));
|
||||||
|
|
||||||
|
lua.safe_script("mi = mati{ {1, 2} }");
|
||||||
|
|
||||||
|
matrix_xf& m = lua["m"];
|
||||||
|
REQUIRE(m.a == 1.1f);
|
||||||
|
REQUIRE(m.b == 2.2f);
|
||||||
|
matrix_xi& mi = lua["mi"];
|
||||||
|
REQUIRE(mi.a == 1);
|
||||||
|
REQUIRE(mi.b == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/call_constructor metatable check", "prevent metatable regression") {
|
||||||
|
class class01 {
|
||||||
|
public:
|
||||||
|
int x = 57;
|
||||||
|
class01() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class class02 {
|
||||||
|
public:
|
||||||
|
int x = 50;
|
||||||
|
class02() {
|
||||||
|
}
|
||||||
|
class02(const class01& other) : x(other.x) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.new_usertype<class01>("class01", sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>());
|
||||||
|
|
||||||
|
lua.new_usertype<class02>("class02", sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>());
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(lua.safe_script(R"(
|
||||||
|
x = class01()
|
||||||
|
y = class02(x)
|
||||||
|
)"));
|
||||||
|
class02& y = lua["y"];
|
||||||
|
REQUIRE(y.x == 57);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed with arguments if a blank / empty constructor is provided") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<thing>("thing", "v", &thing::v, sol::call_constructor, sol::constructors<>());
|
||||||
|
|
||||||
|
auto result = lua.safe_script("t = thing(256)", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
|
||||||
|
SECTION("order1") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.new_usertype<thing>("thing", "v", &thing::v, sol::call_constructor, sol::no_constructor);
|
||||||
|
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("order2") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<thing>("thing", sol::call_constructor, sol::no_constructor, "v", &thing::v);
|
||||||
|
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("new no_constructor") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<thing>("thing", sol::meta_function::construct, sol::no_constructor);
|
||||||
|
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("call no_constructor") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<thing>("thing", sol::call_constructor, sol::no_constructor);
|
||||||
|
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/constructor list", "Show that we can create classes from usertype and use them with multiple constructors") {
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
|
||||||
|
sol::usertype<crapola::fuser> lc = lua.new_usertype<crapola::fuser>("fuser", con, "add", &crapola::fuser::add, "add2", &crapola::fuser::add2);
|
||||||
|
|
||||||
|
lua.safe_script(
|
||||||
|
"a = fuser.new(2)\n"
|
||||||
|
"u = a:add(1)\n"
|
||||||
|
"v = a:add2(1)\n"
|
||||||
|
"b = fuser:new()\n"
|
||||||
|
"w = b:add(1)\n"
|
||||||
|
"x = b:add2(1)\n"
|
||||||
|
"c = fuser.new(2, 3)\n"
|
||||||
|
"y = c:add(1)\n"
|
||||||
|
"z = c:add2(1)\n");
|
||||||
|
sol::object a = lua.get<sol::object>("a");
|
||||||
|
auto atype = a.get_type();
|
||||||
|
REQUIRE((atype == sol::type::userdata));
|
||||||
|
sol::object u = lua.get<sol::object>("u");
|
||||||
|
sol::object v = lua.get<sol::object>("v");
|
||||||
|
REQUIRE((u.as<int>() == 3));
|
||||||
|
REQUIRE((v.as<int>() == 5));
|
||||||
|
|
||||||
|
sol::object b = lua.get<sol::object>("b");
|
||||||
|
auto btype = b.get_type();
|
||||||
|
REQUIRE((btype == sol::type::userdata));
|
||||||
|
sol::object w = lua.get<sol::object>("w");
|
||||||
|
sol::object x = lua.get<sol::object>("x");
|
||||||
|
REQUIRE((w.as<int>() == 1));
|
||||||
|
REQUIRE((x.as<int>() == 3));
|
||||||
|
|
||||||
|
sol::object c = lua.get<sol::object>("c");
|
||||||
|
auto ctype = c.get_type();
|
||||||
|
REQUIRE((ctype == sol::type::userdata));
|
||||||
|
sol::object y = lua.get<sol::object>("y");
|
||||||
|
sol::object z = lua.get<sol::object>("z");
|
||||||
|
REQUIRE((y.as<int>() == 7));
|
||||||
|
REQUIRE((z.as<int>() == 9));
|
||||||
|
}
|
|
@ -31,16 +31,6 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
struct thing {
|
|
||||||
int v = 100;
|
|
||||||
|
|
||||||
thing() {
|
|
||||||
}
|
|
||||||
thing(int x)
|
|
||||||
: v(x) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct self_test {
|
struct self_test {
|
||||||
int bark;
|
int bark;
|
||||||
|
|
||||||
|
@ -62,154 +52,6 @@ struct self_test {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct matrix_xf {
|
|
||||||
float a, b;
|
|
||||||
|
|
||||||
static matrix_xf from_lua_table(sol::table t) {
|
|
||||||
matrix_xf m;
|
|
||||||
m.a = t[1][1];
|
|
||||||
m.b = t[1][2];
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct matrix_xi {
|
|
||||||
int a, b;
|
|
||||||
|
|
||||||
static matrix_xi from_lua_table(sol::table t) {
|
|
||||||
matrix_xi m;
|
|
||||||
m.a = t[1][1];
|
|
||||||
m.b = t[1][2];
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
|
|
||||||
sol::state lua;
|
|
||||||
|
|
||||||
sol::usertype<fuser> lc = lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
|
|
||||||
|
|
||||||
lua.safe_script(
|
|
||||||
"a = fuser:new()\n"
|
|
||||||
"b = a:add(1)\n"
|
|
||||||
"c = a:add2(1)\n");
|
|
||||||
|
|
||||||
sol::object a = lua.get<sol::object>("a");
|
|
||||||
sol::object b = lua.get<sol::object>("b");
|
|
||||||
sol::object c = lua.get<sol::object>("c");
|
|
||||||
REQUIRE((a.is<sol::userdata_value>()));
|
|
||||||
auto atype = a.get_type();
|
|
||||||
auto btype = b.get_type();
|
|
||||||
auto ctype = c.get_type();
|
|
||||||
REQUIRE((atype == sol::type::userdata));
|
|
||||||
REQUIRE((btype == sol::type::number));
|
|
||||||
REQUIRE((ctype == sol::type::number));
|
|
||||||
int bresult = b.as<int>();
|
|
||||||
int cresult = c.as<int>();
|
|
||||||
REQUIRE(bresult == 1);
|
|
||||||
REQUIRE(cresult == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") {
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
|
|
||||||
sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
|
|
||||||
sol::usertype<crapola::fuser> lc = lua.new_usertype<crapola::fuser>("fuser",
|
|
||||||
con,
|
|
||||||
"add", &crapola::fuser::add,
|
|
||||||
"add2", &crapola::fuser::add2);
|
|
||||||
|
|
||||||
lua.safe_script(
|
|
||||||
"a = fuser.new(2)\n"
|
|
||||||
"u = a:add(1)\n"
|
|
||||||
"v = a:add2(1)\n"
|
|
||||||
"b = fuser:new()\n"
|
|
||||||
"w = b:add(1)\n"
|
|
||||||
"x = b:add2(1)\n"
|
|
||||||
"c = fuser.new(2, 3)\n"
|
|
||||||
"y = c:add(1)\n"
|
|
||||||
"z = c:add2(1)\n");
|
|
||||||
sol::object a = lua.get<sol::object>("a");
|
|
||||||
auto atype = a.get_type();
|
|
||||||
REQUIRE((atype == sol::type::userdata));
|
|
||||||
sol::object u = lua.get<sol::object>("u");
|
|
||||||
sol::object v = lua.get<sol::object>("v");
|
|
||||||
REQUIRE((u.as<int>() == 3));
|
|
||||||
REQUIRE((v.as<int>() == 5));
|
|
||||||
|
|
||||||
sol::object b = lua.get<sol::object>("b");
|
|
||||||
auto btype = b.get_type();
|
|
||||||
REQUIRE((btype == sol::type::userdata));
|
|
||||||
sol::object w = lua.get<sol::object>("w");
|
|
||||||
sol::object x = lua.get<sol::object>("x");
|
|
||||||
REQUIRE((w.as<int>() == 1));
|
|
||||||
REQUIRE((x.as<int>() == 3));
|
|
||||||
|
|
||||||
sol::object c = lua.get<sol::object>("c");
|
|
||||||
auto ctype = c.get_type();
|
|
||||||
REQUIRE((ctype == sol::type::userdata));
|
|
||||||
sol::object y = lua.get<sol::object>("y");
|
|
||||||
sol::object z = lua.get<sol::object>("z");
|
|
||||||
REQUIRE((y.as<int>() == 7));
|
|
||||||
REQUIRE((z.as<int>() == 9));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") {
|
|
||||||
sol::state lua;
|
|
||||||
|
|
||||||
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
|
|
||||||
|
|
||||||
lua.safe_script(
|
|
||||||
"a = fuser.new()\n"
|
|
||||||
"b = a:add(1)\n"
|
|
||||||
"c = a:add2(1)\n");
|
|
||||||
|
|
||||||
sol::object a = lua.get<sol::object>("a");
|
|
||||||
sol::object b = lua.get<sol::object>("b");
|
|
||||||
sol::object c = lua.get<sol::object>("c");
|
|
||||||
REQUIRE((a.is<sol::userdata_value>()));
|
|
||||||
auto atype = a.get_type();
|
|
||||||
auto btype = b.get_type();
|
|
||||||
auto ctype = c.get_type();
|
|
||||||
REQUIRE((atype == sol::type::userdata));
|
|
||||||
REQUIRE((btype == sol::type::number));
|
|
||||||
REQUIRE((ctype == sol::type::number));
|
|
||||||
int bresult = b.as<int>();
|
|
||||||
int cresult = c.as<int>();
|
|
||||||
REQUIRE(bresult == 1);
|
|
||||||
REQUIRE(cresult == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
sol::constructors<sol::types<int>> basector;
|
|
||||||
sol::usertype<Base> baseusertype = lua.new_usertype<Base>("Base", basector, "get_num", &Base::get_num);
|
|
||||||
|
|
||||||
lua.safe_script("base = Base.new(5)");
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("print(base:get_num())", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::constructors<sol::types<int>> derivedctor;
|
|
||||||
sol::usertype<Derived> derivedusertype = lua.new_usertype<Derived>("Derived", derivedctor,
|
|
||||||
"get_num_10", &Derived::get_num_10,
|
|
||||||
"get_num", &Derived::get_num);
|
|
||||||
|
|
||||||
lua.safe_script("derived = Derived.new(7)");
|
|
||||||
lua.safe_script(
|
|
||||||
"dgn = derived:get_num()\n"
|
|
||||||
"print(dgn)");
|
|
||||||
lua.safe_script(
|
|
||||||
"dgn10 = derived:get_num_10()\n"
|
|
||||||
"print(dgn10)");
|
|
||||||
|
|
||||||
REQUIRE((lua.get<int>("dgn10") == 70));
|
|
||||||
REQUIRE((lua.get<int>("dgn") == 7));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") {
|
TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::base);
|
lua.open_libraries(sol::lib::base);
|
||||||
|
@ -224,178 +66,6 @@ TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice
|
||||||
REQUIRE(result.valid());
|
REQUIRE(result.valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
|
|
||||||
struct test {
|
|
||||||
int x = 0;
|
|
||||||
test& set() {
|
|
||||||
x = 10;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
test* pget() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
test create_get() {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fun(int xa) {
|
|
||||||
return xa * 10;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("x = test.new()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(x:set():get() == 10)", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("y = x:pointer_get()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("y:set():get()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("y:fun(10)", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("x:fun(10)", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(y:fun(10) == x:fun(10), '...')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(y:fun(10) == 100, '...')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(y:set():get() == y:set():get(), '...')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("assert(y:set():get() == 10, '...')", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
sol::constructors<sol::types<float, float, float>> ctor;
|
|
||||||
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec", ctor, "normalized", &Vec::normalized, "length", &Vec::length);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script(
|
|
||||||
"v = Vec.new(1, 2, 3)\n"
|
|
||||||
"print(v:length())");
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script(
|
|
||||||
"v = Vec.new(1, 2, 3)\n"
|
|
||||||
"print(v:normalized():length())");
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
{
|
|
||||||
sol::constructors<sol::types<float, float, float>> ctor;
|
|
||||||
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec",
|
|
||||||
ctor,
|
|
||||||
"normalized", &Vec::normalized,
|
|
||||||
"length", &Vec::length);
|
|
||||||
|
|
||||||
// usertype dies, but still usable in lua!
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script(
|
|
||||||
"collectgarbage()\n"
|
|
||||||
"v = Vec.new(1, 2, 3)\n"
|
|
||||||
"print(v:length())");
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script(
|
|
||||||
"v = Vec.new(1, 2, 3)\n"
|
|
||||||
"print(v:normalized():length())");
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
sol::constructors<sol::types<float, float, float>> ctor;
|
|
||||||
sol::usertype<Vec> udata = lua.new_usertype<Vec>("Vec",
|
|
||||||
ctor,
|
|
||||||
"x", &Vec::x,
|
|
||||||
"y", &Vec::y,
|
|
||||||
"z", &Vec::z,
|
|
||||||
"normalized", &Vec::normalized,
|
|
||||||
"length", &Vec::length);
|
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.safe_script(
|
|
||||||
"v = Vec.new(1, 2, 3)\n"
|
|
||||||
"v2 = Vec.new(0, 1, 0)\n"
|
|
||||||
"print(v:length())\n"));
|
|
||||||
REQUIRE_NOTHROW(lua.safe_script(
|
|
||||||
"v.x = 2\n"
|
|
||||||
"v2.y = 2\n"
|
|
||||||
"print(v.x, v.y, v.z)\n"
|
|
||||||
"print(v2.x, v2.y, v2.z)\n"));
|
|
||||||
REQUIRE_NOTHROW(lua.safe_script(
|
|
||||||
"assert(v.x == 2)\n"
|
|
||||||
"assert(v2.x == 0)\n"
|
|
||||||
"assert(v2.y == 2)\n"));
|
|
||||||
REQUIRE_NOTHROW(lua.safe_script(
|
|
||||||
"v.x = 3\n"
|
|
||||||
"local x = v.x\n"
|
|
||||||
"assert(x == 3)\n"));
|
|
||||||
|
|
||||||
struct breaks {
|
|
||||||
sol::function f;
|
|
||||||
};
|
|
||||||
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
lua.set("b", breaks());
|
|
||||||
lua.new_usertype<breaks>("breaks",
|
|
||||||
"f", &breaks::f);
|
|
||||||
|
|
||||||
breaks& b = lua["b"];
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("b.f = function () print('BARK!') end", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("b.f()", sol::script_pass_on_error);
|
|
||||||
REQUIRE(result.valid());
|
|
||||||
}
|
|
||||||
REQUIRE_NOTHROW(b.f());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
|
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::base);
|
lua.open_libraries(sol::lib::base);
|
||||||
|
@ -425,354 +95,6 @@ TEST_CASE("usertype/nonmember-functions", "let users set non-member functions th
|
||||||
std::cout << "----- end of 1" << std::endl;
|
std::cout << "----- end of 1" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("regressions/one", "issue number 48") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.new_usertype<vars>("vars",
|
|
||||||
"boop", &vars::boop);
|
|
||||||
auto code =
|
|
||||||
"beep = vars.new()\n"
|
|
||||||
"beep.boop = 1";
|
|
||||||
auto result1 = lua.safe_script(code, sol::script_pass_on_error);
|
|
||||||
REQUIRE(result1.valid());
|
|
||||||
// test for segfault
|
|
||||||
auto my_var = lua.get<vars>("beep");
|
|
||||||
auto& my_var_ref = lua.get<vars>("beep");
|
|
||||||
auto* my_var_ptr = lua.get<vars*>("beep");
|
|
||||||
REQUIRE(my_var.boop == 1);
|
|
||||||
REQUIRE(my_var_ref.boop == 1);
|
|
||||||
REQUIRE(my_var_ptr->boop == 1);
|
|
||||||
REQUIRE(std::addressof(my_var_ref) == my_var_ptr);
|
|
||||||
std::cout << "----- end of 3" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
|
|
||||||
std::cout << "----- in 4" << std::endl;
|
|
||||||
sol::state lua;
|
|
||||||
|
|
||||||
lua.new_usertype<vars>("vars",
|
|
||||||
"boop", &vars::boop);
|
|
||||||
vars var{};
|
|
||||||
vars rvar{};
|
|
||||||
std::cout << "setting beep" << std::endl;
|
|
||||||
lua.set("beep", var);
|
|
||||||
std::cout << "setting rbeep" << std::endl;
|
|
||||||
lua.set("rbeep", std::ref(rvar));
|
|
||||||
std::cout << "getting my_var" << std::endl;
|
|
||||||
auto& my_var = lua.get<vars>("beep");
|
|
||||||
std::cout << "setting rbeep" << std::endl;
|
|
||||||
auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep");
|
|
||||||
vars& proxy_my_var = lua["beep"];
|
|
||||||
std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"];
|
|
||||||
var.boop = 2;
|
|
||||||
rvar.boop = 5;
|
|
||||||
|
|
||||||
// Was return as a value: var must be diferent from "beep"
|
|
||||||
REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var));
|
|
||||||
REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var));
|
|
||||||
REQUIRE((my_var.boop == 0));
|
|
||||||
REQUIRE(var.boop != my_var.boop);
|
|
||||||
|
|
||||||
REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
|
|
||||||
REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
|
|
||||||
REQUIRE(rvar.boop == 5);
|
|
||||||
REQUIRE(rvar.boop == ref_var.boop);
|
|
||||||
std::cout << "----- end of 4" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
|
|
||||||
struct A_x {
|
|
||||||
int x = 201;
|
|
||||||
};
|
|
||||||
struct B_foo {
|
|
||||||
int foo(const A_x* a) {
|
|
||||||
return a->x;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.new_usertype<B_foo>("B",
|
|
||||||
"foo", &B_foo::foo);
|
|
||||||
lua.set("a", A_x());
|
|
||||||
lua.set("b", B_foo());
|
|
||||||
lua.safe_script("x = b:foo(a)");
|
|
||||||
int x = lua["x"];
|
|
||||||
REQUIRE(x == 201);
|
|
||||||
std::cout << "----- end of 6" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
|
|
||||||
struct woof {
|
|
||||||
int var;
|
|
||||||
|
|
||||||
int func(int x) {
|
|
||||||
return var + x;
|
|
||||||
}
|
|
||||||
|
|
||||||
double func2(int x, int y) {
|
|
||||||
return var + x + y + 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string func2s(int x, std::string y) {
|
|
||||||
return y + " " + std::to_string(x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
lua.new_usertype<woof>("woof",
|
|
||||||
"var", &woof::var,
|
|
||||||
"func", sol::overload(&woof::func, &woof::func2, &woof::func2s));
|
|
||||||
|
|
||||||
const std::string bark_58 = "bark 58";
|
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.safe_script(
|
|
||||||
"r = woof:new()\n"
|
|
||||||
"a = r:func(1)\n"
|
|
||||||
"b = r:func(1, 2)\n"
|
|
||||||
"c = r:func(58, 'bark')\n"));
|
|
||||||
REQUIRE((lua["a"] == 1));
|
|
||||||
REQUIRE((lua["b"] == 3.5));
|
|
||||||
REQUIRE((lua["c"] == bark_58));
|
|
||||||
auto result = lua.safe_script("r:func(1,2,'meow')", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
std::cout << "----- end of 7" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
|
|
||||||
struct overloading_test {
|
|
||||||
int print(int i) {
|
|
||||||
INFO("Integer print: " << i);
|
|
||||||
return 500 + i;
|
|
||||||
}
|
|
||||||
int print() {
|
|
||||||
INFO("No param print.");
|
|
||||||
return 500;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(),
|
|
||||||
"print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
|
|
||||||
"print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)));
|
|
||||||
lua.set("test", overloading_test());
|
|
||||||
|
|
||||||
sol::function f0_0 = lua.load("return test:print()");
|
|
||||||
sol::function f0_1 = lua.load("return test:print2()");
|
|
||||||
sol::function f1_0 = lua.load("return test:print(24)");
|
|
||||||
sol::function f1_1 = lua.load("return test:print2(24)");
|
|
||||||
int res = f0_0();
|
|
||||||
int res2 = f0_1();
|
|
||||||
int res3 = f1_0();
|
|
||||||
int res4 = f1_1();
|
|
||||||
|
|
||||||
REQUIRE(res == 500);
|
|
||||||
REQUIRE(res2 == 500);
|
|
||||||
|
|
||||||
REQUIRE(res3 == 524);
|
|
||||||
REQUIRE(res4 == 524);
|
|
||||||
std::cout << "----- end of 8" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
|
|
||||||
struct bark {
|
|
||||||
int var = 50;
|
|
||||||
};
|
|
||||||
struct woof {
|
|
||||||
bark b;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nested {
|
|
||||||
const int f = 25;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct outer {
|
|
||||||
nested n;
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.new_usertype<woof>("woof",
|
|
||||||
"b", &woof::b);
|
|
||||||
lua.new_usertype<bark>("bark",
|
|
||||||
"var", &bark::var);
|
|
||||||
lua.new_usertype<outer>("outer",
|
|
||||||
"n", &outer::n);
|
|
||||||
lua.set("w", woof());
|
|
||||||
lua.set("n", nested());
|
|
||||||
lua.set("o", outer());
|
|
||||||
lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
|
|
||||||
lua.safe_script(R"(
|
|
||||||
x = w.b
|
|
||||||
x.var = 20
|
|
||||||
val = w.b.var == x.var
|
|
||||||
v = f(n);
|
|
||||||
)");
|
|
||||||
|
|
||||||
woof& w = lua["w"];
|
|
||||||
bark& x = lua["x"];
|
|
||||||
nested& n = lua["n"];
|
|
||||||
int v = lua["v"];
|
|
||||||
bool val = lua["val"];
|
|
||||||
// enforce reference semantics
|
|
||||||
REQUIRE(std::addressof(w.b) == std::addressof(x));
|
|
||||||
REQUIRE(n.f == 25);
|
|
||||||
REQUIRE(v == 25);
|
|
||||||
REQUIRE(val);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("f(n, 50)", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto result = lua.safe_script("o.n = 25", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
|
|
||||||
class Test {
|
|
||||||
public:
|
|
||||||
void sayHello() {
|
|
||||||
std::cout << "Hey\n";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello);
|
|
||||||
static const std::string code = R"(
|
|
||||||
local t = Test.new()
|
|
||||||
t:sayHello() --Works fine
|
|
||||||
t.sayHello() --Uh oh.
|
|
||||||
)";
|
|
||||||
auto result = lua.safe_script(code, sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
lua.new_usertype<thing>("thing",
|
|
||||||
"v", &thing::v, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>());
|
|
||||||
|
|
||||||
lua.safe_script(R"(
|
|
||||||
t = thing(256)
|
|
||||||
)");
|
|
||||||
|
|
||||||
thing& y = lua["t"];
|
|
||||||
INFO(y.v);
|
|
||||||
REQUIRE(y.v == 256);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed to factory-based call constructors") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries();
|
|
||||||
|
|
||||||
lua.new_usertype<matrix_xf>("mat",
|
|
||||||
sol::call_constructor, sol::factories(&matrix_xf::from_lua_table));
|
|
||||||
|
|
||||||
lua.safe_script("m = mat{ {1.1, 2.2} }");
|
|
||||||
|
|
||||||
lua.new_usertype<matrix_xi>("mati",
|
|
||||||
sol::call_constructor, sol::factories(&matrix_xi::from_lua_table));
|
|
||||||
|
|
||||||
lua.safe_script("mi = mati{ {1, 2} }");
|
|
||||||
|
|
||||||
matrix_xf& m = lua["m"];
|
|
||||||
REQUIRE(m.a == 1.1f);
|
|
||||||
REQUIRE(m.b == 2.2f);
|
|
||||||
matrix_xi& mi = lua["mi"];
|
|
||||||
REQUIRE(mi.a == 1);
|
|
||||||
REQUIRE(mi.b == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") {
|
|
||||||
class class01 {
|
|
||||||
public:
|
|
||||||
int x = 57;
|
|
||||||
class01() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class class02 {
|
|
||||||
public:
|
|
||||||
int x = 50;
|
|
||||||
class02() {
|
|
||||||
}
|
|
||||||
class02(const class01& other)
|
|
||||||
: x(other.x) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
|
|
||||||
lua.new_usertype<class01>("class01",
|
|
||||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>());
|
|
||||||
|
|
||||||
lua.new_usertype<class02>("class02",
|
|
||||||
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>());
|
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.safe_script(R"(
|
|
||||||
x = class01()
|
|
||||||
y = class02(x)
|
|
||||||
)"));
|
|
||||||
class02& y = lua["y"];
|
|
||||||
REQUIRE(y.x == 57);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed with arguments if a blank / empty constructor is provided") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
lua.new_usertype<thing>("thing",
|
|
||||||
"v", &thing::v, sol::call_constructor, sol::constructors<>());
|
|
||||||
|
|
||||||
auto result = lua.safe_script("t = thing(256)", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
|
|
||||||
SECTION("order1") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
lua.new_usertype<thing>("thing",
|
|
||||||
"v", &thing::v,
|
|
||||||
sol::call_constructor, sol::no_constructor);
|
|
||||||
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("order2") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
lua.new_usertype<thing>("thing",
|
|
||||||
sol::call_constructor, sol::no_constructor,
|
|
||||||
"v", &thing::v);
|
|
||||||
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("new no_constructor") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
lua.new_usertype<thing>("thing",
|
|
||||||
sol::meta_function::construct, sol::no_constructor);
|
|
||||||
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("call no_constructor") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base);
|
|
||||||
|
|
||||||
lua.new_usertype<thing>("thing",
|
|
||||||
sol::call_constructor, sol::no_constructor);
|
|
||||||
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
|
|
||||||
REQUIRE_FALSE(result.valid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
|
TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);
|
lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "sol_test.hpp"
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -257,3 +259,31 @@ TEST_CASE("inheritance/runtime multi base", "test that multiple bases all work a
|
||||||
runtime_A& a_obj = lua["obj"];
|
runtime_A& a_obj = lua["obj"];
|
||||||
REQUIRE(a_obj.a == 5);
|
REQUIRE(a_obj.a == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("inheritance/usertype derived non-hiding", "usertype classes must play nice when a derived class does not overload a publically visible base function") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
sol::constructors<sol::types<int>> basector;
|
||||||
|
sol::usertype<Base> baseusertype = lua.new_usertype<Base>("Base", basector, "get_num", &Base::get_num);
|
||||||
|
|
||||||
|
lua.safe_script("base = Base.new(5)");
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("print(base:get_num())", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::constructors<sol::types<int>> derivedctor;
|
||||||
|
sol::usertype<Derived> derivedusertype
|
||||||
|
= lua.new_usertype<Derived>("Derived", derivedctor, "get_num_10", &Derived::get_num_10, "get_num", &Derived::get_num);
|
||||||
|
|
||||||
|
lua.safe_script("derived = Derived.new(7)");
|
||||||
|
lua.safe_script(
|
||||||
|
"dgn = derived:get_num()\n"
|
||||||
|
"print(dgn)");
|
||||||
|
lua.safe_script(
|
||||||
|
"dgn10 = derived:get_num_10()\n"
|
||||||
|
"print(dgn10)");
|
||||||
|
|
||||||
|
REQUIRE((lua.get<int>("dgn10") == 70));
|
||||||
|
REQUIRE((lua.get<int>("dgn") == 7));
|
||||||
|
}
|
126
tests/runtime_tests/source/usertypes.member_variables.cpp
Normal file
126
tests/runtime_tests/source/usertypes.member_variables.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
sol::constructors<sol::types<float, float, float>> ctor;
|
||||||
|
sol::usertype<Vec> udata
|
||||||
|
= lua.new_usertype<Vec>("Vec", ctor, "x", &Vec::x, "y", &Vec::y, "z", &Vec::z, "normalized", &Vec::normalized, "length", &Vec::length);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.safe_script("v = Vec.new(1, 2, 3)\n"
|
||||||
|
"v2 = Vec.new(0, 1, 0)\n"
|
||||||
|
"print(v:length())\n"));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.safe_script("v.x = 2\n"
|
||||||
|
"v2.y = 2\n"
|
||||||
|
"print(v.x, v.y, v.z)\n"
|
||||||
|
"print(v2.x, v2.y, v2.z)\n"));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.safe_script("assert(v.x == 2)\n"
|
||||||
|
"assert(v2.x == 0)\n"
|
||||||
|
"assert(v2.y == 2)\n"));
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.safe_script("v.x = 3\n"
|
||||||
|
"local x = v.x\n"
|
||||||
|
"assert(x == 3)\n"));
|
||||||
|
|
||||||
|
struct breaks {
|
||||||
|
sol::function f;
|
||||||
|
};
|
||||||
|
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.set("b", breaks());
|
||||||
|
lua.new_usertype<breaks>("breaks", "f", &breaks::f);
|
||||||
|
|
||||||
|
breaks& b = lua["b"];
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("b.f = function () print('BARK!') end", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("b.f()", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
REQUIRE_NOTHROW(b.f());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
|
||||||
|
struct bark {
|
||||||
|
int var = 50;
|
||||||
|
};
|
||||||
|
struct woof {
|
||||||
|
bark b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nested {
|
||||||
|
const int f = 25;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct outer {
|
||||||
|
nested n;
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.new_usertype<woof>("woof", "b", &woof::b);
|
||||||
|
lua.new_usertype<bark>("bark", "var", &bark::var);
|
||||||
|
lua.new_usertype<outer>("outer", "n", &outer::n);
|
||||||
|
lua.set("w", woof());
|
||||||
|
lua.set("n", nested());
|
||||||
|
lua.set("o", outer());
|
||||||
|
lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
|
||||||
|
lua.safe_script(R"(
|
||||||
|
x = w.b
|
||||||
|
x.var = 20
|
||||||
|
val = w.b.var == x.var
|
||||||
|
v = f(n);
|
||||||
|
)");
|
||||||
|
|
||||||
|
woof& w = lua["w"];
|
||||||
|
bark& x = lua["x"];
|
||||||
|
nested& n = lua["n"];
|
||||||
|
int v = lua["v"];
|
||||||
|
bool val = lua["val"];
|
||||||
|
// enforce reference semantics
|
||||||
|
REQUIRE(std::addressof(w.b) == std::addressof(x));
|
||||||
|
REQUIRE(n.f == 25);
|
||||||
|
REQUIRE(v == 25);
|
||||||
|
REQUIRE(val);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("f(n, 50)", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = lua.safe_script("o.n = 25", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
}
|
||||||
|
}
|
89
tests/runtime_tests/source/usertypes.overload.cpp
Normal file
89
tests/runtime_tests/source/usertypes.overload.cpp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// sol3
|
||||||
|
|
||||||
|
// The MIT License (MIT)
|
||||||
|
|
||||||
|
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "sol_test.hpp"
|
||||||
|
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
struct overloading_test {
|
||||||
|
int print(int i) {
|
||||||
|
INFO("Integer print: " << i);
|
||||||
|
return 500 + i;
|
||||||
|
}
|
||||||
|
int print() {
|
||||||
|
INFO("No param print.");
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<woof>("woof", "var", &woof::var, "func", sol::overload(&woof::func, &woof::func2, &woof::func2s));
|
||||||
|
|
||||||
|
const std::string bark_58 = "bark 58";
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(
|
||||||
|
lua.safe_script("r = woof:new()\n"
|
||||||
|
"a = r:func(1)\n"
|
||||||
|
"b = r:func(1, 2)\n"
|
||||||
|
"c = r:func(58, 'bark')\n"));
|
||||||
|
REQUIRE((lua["a"] == 1));
|
||||||
|
REQUIRE((lua["b"] == 3.5));
|
||||||
|
REQUIRE((lua["c"] == bark_58));
|
||||||
|
auto result = lua.safe_script("r:func(1,2,'meow')", sol::script_pass_on_error);
|
||||||
|
REQUIRE_FALSE(result.valid());
|
||||||
|
std::cout << "----- end of 7" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.new_usertype<overloading_test>("overloading_test",
|
||||||
|
sol::constructors<>(),
|
||||||
|
"print",
|
||||||
|
sol::overload(
|
||||||
|
static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
|
||||||
|
"print2",
|
||||||
|
sol::overload(
|
||||||
|
static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)));
|
||||||
|
lua.set("test", overloading_test());
|
||||||
|
|
||||||
|
sol::function f0_0 = lua.load("return test:print()");
|
||||||
|
sol::function f0_1 = lua.load("return test:print2()");
|
||||||
|
sol::function f1_0 = lua.load("return test:print(24)");
|
||||||
|
sol::function f1_1 = lua.load("return test:print2(24)");
|
||||||
|
int res = f0_0();
|
||||||
|
int res2 = f0_1();
|
||||||
|
int res3 = f1_0();
|
||||||
|
int res4 = f1_1();
|
||||||
|
|
||||||
|
REQUIRE(res == 500);
|
||||||
|
REQUIRE(res2 == 500);
|
||||||
|
|
||||||
|
REQUIRE(res3 == 524);
|
||||||
|
REQUIRE(res4 == 524);
|
||||||
|
std::cout << "----- end of 8" << std::endl;
|
||||||
|
}
|
|
@ -22,6 +22,7 @@
|
||||||
// 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.
|
||||||
|
|
||||||
#include "sol_test.hpp"
|
#include "sol_test.hpp"
|
||||||
|
#include "common_classes.hpp"
|
||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
@ -106,7 +107,25 @@ TEST_CASE("utility/variant", "test that variant can be round-tripped") {
|
||||||
#endif // C++17
|
#endif // C++17
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("utility/optional", "test that shit optional can be round-tripped") {
|
TEST_CASE("utility/optional-conversion", "test that regular optional will properly catch certain types") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<vars>("vars");
|
||||||
|
|
||||||
|
lua["test"] = [](sol::optional<vars> x) {
|
||||||
|
return static_cast<bool>(x);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto result = lua.safe_script(R"(
|
||||||
|
assert(test(vars:new()))
|
||||||
|
assert(not test(3))
|
||||||
|
assert(not test(nil))
|
||||||
|
)", sol::script_pass_on_error);
|
||||||
|
REQUIRE(result.valid());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("utility/std optional", "test that shit optional can be round-tripped") {
|
||||||
#ifdef SOL_CXX17_FEATURES
|
#ifdef SOL_CXX17_FEATURES
|
||||||
SECTION("okay") {
|
SECTION("okay") {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user