Add lua_table and lua_value abstractions

Improve dump handler, bytecode, and base traits
Fix tolua on bad calls, fix interop handler changes
We are now truly done with all feature requests...
This commit is contained in:
ThePhD 2019-03-18 07:41:51 -04:00
parent 70bc1113cb
commit b63d7af060
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
47 changed files with 2064 additions and 787 deletions

View File

@ -29,8 +29,16 @@ inline bool sol_lua_interop_check(sol::types<T>, lua_State* L, int relindex, sol
(void)handler;
int index = lua_absindex(L, relindex);
std::string name = sol::detail::short_demangle<T>();
tolua_Error tolua_err;
return tolua_isusertype(L, index, name.c_str(), 0, &tolua_err);
tolua_Error tolua_err{};
int r = tolua_isusertype(L, index, name.c_str(), 0, &tolua_err);
if (r == 0) {
// tolua seems to leave garbage on the stack
// when the check fails
// thanks, tolua
lua_pop(L, 2);
return false;
}
return true;
}
void register_sol_stuff(lua_State* L) {

View File

@ -39,7 +39,16 @@ namespace sol {
template <typename T>
using void_t = void;
template <typename T>
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
template <typename T>
using unqualified_t = typename unqualified<T>::type;
namespace meta_detail {
template <typename T>
struct unqualified_non_alias : unqualified<T> {};
template <template <class...> class Test, class, class... Args>
struct is_detected : std::false_type {};
@ -92,12 +101,6 @@ namespace sol {
template <typename T>
using identity_t = typename identity<T>::type;
template <typename T>
using is_tuple = is_specialization_of<T, std::tuple>;
template <typename T>
constexpr inline bool is_tuple_v = is_tuple<T>::value;
template <typename T>
using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>;

View File

@ -38,6 +38,17 @@ namespace sol {
using base_t = std::vector<std::byte, Allocator>;
public:
using base_t::allocator_type;
using base_t::const_iterator;
using base_t::const_pointer;
using base_t::const_reference;
using base_t::const_reverse_iterator;
using base_t::difference_type;
using base_t::iterator;
using base_t::pointer;
using base_t::reference;
using base_t::reverse_iterator;
using base_t::size_type;
using base_t::value_type;
using base_t::base_t;
@ -81,11 +92,11 @@ namespace sol {
}
};
using bytecode = basic_bytecode<>;
inline int bytecode_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata) {
template <typename Container>
inline int basic_insert_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata) {
using storage_t = Container;
const std::byte* p_code = static_cast<const std::byte*>(memory);
bytecode& bc = *static_cast<bytecode*>(userdata);
storage_t& bc = *static_cast<storage_t*>(userdata);
try {
bc.insert(bc.cend(), p_code, p_code + memory_size);
}
@ -95,6 +106,10 @@ namespace sol {
return 0;
}
using bytecode = basic_bytecode<>;
constexpr inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>;
} // namespace sol
#endif // SOL_BYTECODE_HPP

View File

@ -24,6 +24,8 @@
#ifndef SOL_DUMP_HANDLER_HPP
#define SOL_DUMP_HANDLER_HPP
#include "compatibility.hpp"
#include <cstdint>
#include <exception>
@ -42,19 +44,29 @@ namespace sol {
}
};
inline int dump_pass_on_error(int result_code, lua_Writer writer_function, void* userdata, bool strip) {
inline int dump_pass_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
(void)L;
(void)writer_function;
(void)userdata;
(void)strip;
return result_code;
}
inline int dump_throw_on_error(int result_code, lua_Writer writer_function, void* userdata, bool strip) {
inline int dump_throw_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
(void)L;
(void)writer_function;
(void)userdata;
(void)strip;
throw dump_error(result_code);
}
}
inline int dump_panic_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
(void)L;
(void)writer_function;
(void)userdata;
(void)strip;
return luaL_error(L, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code);
}
} // namespace sol

View File

@ -48,13 +48,15 @@ namespace sol {
template <typename A>
class basic_bytecode;
struct lua_value;
struct proxy_base_tag;
template <typename Super>
template <typename>
struct proxy_base;
template <typename Table, typename Key>
template <typename, typename>
struct proxy;
template <bool, typename base_type>
template <bool, typename>
class basic_table_core;
template <bool b>
using table_core = basic_table_core<b, reference>;
@ -71,6 +73,11 @@ namespace sol {
using stack_table = stack_table_core<false>;
using stack_global_table = stack_table_core<true>;
template <typename>
struct basic_lua_table;
using lua_table = basic_lua_table<reference>;
using stack_lua_table = basic_lua_table<stack_reference>;
template <typename T, typename base_type>
class basic_usertype;
template <typename T>

View File

@ -27,6 +27,7 @@
#include "stack.hpp"
#include "unsafe_function.hpp"
#include "protected_function.hpp"
#include "bytecode.hpp"
#include <functional>
namespace sol {
@ -117,8 +118,7 @@ namespace sol {
}
static std::function<Signature> get(lua_State* L, int index, record& tracking) {
tracking.last = 1;
tracking.used += 1;
tracking.use(1);
type t = type_of(L, index);
if (t == type::none || t == type::lua_nil) {
return nullptr;
@ -126,6 +126,15 @@ namespace sol {
return get_std_func(return_types(), L, index);
}
};
template <typename Allocator>
struct unqualified_getter<basic_bytecode<Allocator>> {
static basic_bytecode<Allocator> get(lua_State* L, int index, record& tracking) {
tracking.use(1);
stack_function sf(L, index);
return sf.dump(&dump_panic_on_error);
}
};
} // namespace stack
} // namespace sol

View File

@ -114,7 +114,7 @@ namespace sol {
stack::push(L, c_closure(freefunc, upvalues));
}
else if constexpr (sizeof...(Args) < 2) {
using Tu = typename meta::unqualified<Args...>::type;
using Tu = typename meta::meta_detail::unqualified_non_alias<Args...>::type;
constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx, is_yielding>::call;

95
include/sol/lua_table.hpp Normal file
View File

@ -0,0 +1,95 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_LUA_TABLE_HPP
#define SOL_LUA_TABLE_HPP
#include "table_core.hpp"
namespace sol {
template <typename ref_t>
struct basic_lua_table : basic_table_core<false, ref_t> {
private:
using base_t = basic_table_core<false, ref_t>;
friend class state;
friend class state_view;
public:
using base_t::lua_state;
basic_lua_table() noexcept = default;
basic_lua_table(const basic_lua_table&) = default;
basic_lua_table(basic_lua_table&&) = default;
basic_lua_table& operator=(const basic_lua_table&) = default;
basic_lua_table& operator=(basic_lua_table&&) = default;
basic_lua_table(const stack_reference& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
basic_lua_table(stack_reference&& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, const new_table& nt) : base_t(L, nt) {
if (!is_stack_based<meta::unqualified_t<ref_t>>::value) {
lua_pop(L, 1);
}
}
basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
constructor_handler handler{};
stack::check<basic_lua_table>(L, index, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
template <typename T,
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
if (!is_table<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_lua_table>(lua_state(), -1, handler);
}
#endif // Safety
}
basic_lua_table(lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) {
}
};
}
#endif // SOL_LUA_TABLE_HPP

130
include/sol/lua_value.hpp Normal file
View File

@ -0,0 +1,130 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_LUA_VALUE_HPP
#define SOL_LUA_VALUE_HPP
#include "stack.hpp"
#include "reference.hpp"
#include "make_reference.hpp"
namespace sol {
namespace detail {
template <typename T>
using is_reference_or_lua_value_init_list = meta::any<meta::is_specialization_of<T, std::initializer_list>, std::is_same<T, reference>>;
template <typename T>
using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>;
}
struct lua_value {
private:
static lua_State*& thread_local_lua_state() {
static thread_local lua_State* L = nullptr;
return L;
}
reference ref_value;
public:
static void set_lua_state(lua_State* L) {
thread_local_lua_state() = L;
}
template <typename T, meta::disable<detail::is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
lua_value(lua_State* L_, T&& value) : lua_value(((set_lua_state(L_)), std::forward<T>(value))) {
}
template <typename T, meta::disable<detail::is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) {
}
lua_value(lua_State* L_, std::initializer_list<lua_value> il) : lua_value(((set_lua_state(L_)), std::move(il))) {
}
lua_value(std::initializer_list<lua_value> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) {
}
lua_value(lua_State* L_, reference r) : lua_value(((thread_local_lua_state() = L_), std::move(r))) {
}
lua_value(reference r) : ref_value(std::move(r)) {
}
lua_value(const lua_value&) noexcept = default;
lua_value(lua_value&&) = default;
lua_value& operator=(const lua_value&) = default;
lua_value& operator=(lua_value&&) = default;
const reference& value() const& {
return ref_value;
}
reference& value() & {
return ref_value;
}
reference&& value() && {
return std::move(ref_value);
}
template <typename T>
decltype(auto) as() const {
ref_value.push();
return stack::pop<T>(ref_value.lua_state());
}
template <typename T>
bool is() const {
int r = ref_value.registry_index();
if (r == LUA_REFNIL)
return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false;
if (r == LUA_NOREF)
return false;
auto pp = stack::push_pop(ref_value);
return stack::check<T>(ref_value.lua_state(), -1, no_panic);
}
};
namespace stack {
template <>
struct unqualified_pusher<lua_value> {
static int push(lua_State* L, const lua_value& lv) {
return stack::push(L, lv.value());
}
static int push(lua_State* L, lua_value&& lv) {
return stack::push(L, std::move(lv).value());
}
};
template <>
struct unqualified_getter<lua_value> {
static lua_value get(lua_State* L, int index, record& tracking) {
return lua_value(L, stack::get<reference>(L, index, tracking));
}
};
}
} // namespace sol
#endif // SOL_LUA_VALUE_HPP

View File

@ -265,10 +265,11 @@ namespace sol {
template <typename Fx>
int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const {
auto pp = stack::push_pop(*this);
this->push();
auto ppn = stack::push_popper_n<false>(this->lua_state(), 1);
int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
if (r != 0) {
return on_error(r, writer, userdata, strip);
return on_error(this->lua_state(), r, writer, userdata, strip);
}
return r;
}
@ -277,9 +278,17 @@ namespace sol {
return dump(writer, userdata, strip, &dump_pass_on_error);
}
bytecode dump() const {
bytecode bc;
(void)dump(&bytecode_dump_writer, static_cast<void*>(&bc), false, &dump_throw_on_error);
template <typename Container = bytecode>
Container dump() const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_throw_on_error);
return bc;
}
template <typename Container = bytecode, typename Fx>
Container dump(Fx&& on_error) const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error));
return bc;
}

View File

@ -50,6 +50,7 @@
#include "forward.hpp"
#include "forward_detail.hpp"
#include "bytecode.hpp"
#include "stack.hpp"
#include "object.hpp"
#include "function.hpp"
@ -64,6 +65,7 @@
#include "as_args.hpp"
#include "variadic_args.hpp"
#include "variadic_results.hpp"
#include "lua_value.hpp"
#if defined(__GNUC__)
#pragma GCC diagnostic pop

View File

@ -29,7 +29,7 @@
namespace sol {
namespace stack {
template <typename X, type expected = lua_type_of_v<meta::unqualified_t<X>>, typename = void>
template <typename X, type expected, typename>
struct qualified_checker {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {

View File

@ -86,7 +86,7 @@ namespace sol { namespace stack {
}
};
template <typename T, type expected = lua_type_of_v<T>, typename = void>
template <typename T, type expected, typename>
struct unqualified_checker {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
@ -251,6 +251,24 @@ namespace sol { namespace stack {
else if constexpr (std::is_same_v<T, detail::non_lua_nil_t>) {
return !stack::unqualified_check<lua_nil_t>(L, index, std::forward<Handler>(handler), tracking);
}
else if constexpr (meta::is_specialization_of_v<T, basic_lua_table>) {
tracking.use(1);
type t = type_of(L, index);
if (t != type::table) {
handler(L, index, type::table, t, "value is not a table");
return false;
}
return true;
}
else if constexpr (meta::is_specialization_of_v<T, basic_bytecode>) {
tracking.use(1);
type t = type_of(L, index);
if (t != type::function) {
handler(L, index, type::function, t, "value is not a function that can be dumped");
return false;
}
return true;
}
else if constexpr(meta::is_specialization_of_v<T, basic_environment>) {
tracking.use(1);
if (lua_getmetatable(L, index) == 0) {
@ -297,7 +315,7 @@ namespace sol { namespace stack {
return success;
}
else if constexpr (meta::is_specialization_of_v<T, user>) {
unqualified_checker<lightuserdata_value> c;
unqualified_checker<lightuserdata_value, type::userdata> c;
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
}
@ -415,51 +433,59 @@ namespace sol { namespace stack {
template <typename U, typename Handler>
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 (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
return true;
}
#endif // interop extensibility
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
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>>::value)
return true;
if (lua_getmetatable(L, index) == 0) {
return true;
}
int metatableindex = lua_gettop(L);
if (stack_detail::check_metatable<U>(L, metatableindex))
return true;
if (stack_detail::check_metatable<U*>(L, metatableindex))
return true;
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex))
return true;
if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex))
return true;
bool success = false;
bool has_derived = derive<T>::value || weak_derive<T>::value;
if (has_derived) {
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
#endif // make sure stack doesn't overflow
auto pn = stack::pop_n(L, 1);
lua_pushstring(L, &detail::base_class_check_key()[0]);
lua_rawget(L, metatableindex);
if (type_of(L, -1) != type::lua_nil) {
void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata);
success = ic(usertype_traits<T>::qualified_name());
if constexpr (std::is_same_v<T, lightuserdata_value> || std::is_same_v<T, userdata_value> || std::is_same_v<T, userdata> || std::is_same_v<T, lightuserdata>) {
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
return false;
}
return true;
}
lua_pop(L, 1);
if (!success) {
handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type");
return false;
else {
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
return true;
}
#endif // interop extensibility
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
return false;
}
if (lua_getmetatable(L, index) == 0) {
return true;
}
int metatableindex = lua_gettop(L);
if (stack_detail::check_metatable<U>(L, metatableindex))
return true;
if (stack_detail::check_metatable<U*>(L, metatableindex))
return true;
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex))
return true;
if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex))
return true;
bool success = false;
bool has_derived = derive<T>::value || weak_derive<T>::value;
if (has_derived) {
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
#endif // make sure stack doesn't overflow
auto pn = stack::pop_n(L, 1);
lua_pushstring(L, &detail::base_class_check_key()[0]);
lua_rawget(L, metatableindex);
if (type_of(L, -1) != type::lua_nil) {
void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata);
success = ic(usertype_traits<T>::qualified_name());
}
}
lua_pop(L, 1);
if (!success) {
handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type");
return false;
}
return true;
}
return true;
}
};

View File

@ -597,9 +597,9 @@ namespace sol {
template <typename T, typename = void>
struct unqualified_pusher;
template <typename T, type t, typename>
template <typename T, type t, typename = void>
struct unqualified_checker;
template <typename T, type t, typename>
template <typename T, type t, typename = void>
struct qualified_checker;
template <typename T, typename = void>
@ -925,7 +925,7 @@ namespace sol {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
unqualified_checker<Tu> c;
unqualified_checker<Tu, lua_type_of_v<Tu>> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
@ -950,7 +950,8 @@ namespace sol {
return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
qualified_checker<T> c;
using Tu = meta::unqualified_t<T>;
qualified_checker<T, lua_type_of_v<Tu>> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
@ -1049,6 +1050,11 @@ namespace sol {
namespace stack_detail {
template <typename Handler>
inline bool check_types(lua_State*, int, Handler&&, record&) {
return true;
}
template <typename T, typename... Args, typename Handler>
inline bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) {
if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking))
@ -1056,13 +1062,8 @@ namespace sol {
return check_types<Args...>(L, firstargument, std::forward<Handler>(handler), tracking);
}
template <typename Handler>
static bool check_types(lua_State*, int, Handler&&, record&) {
return true;
}
template <typename... Args, typename Handler>
bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) {
inline bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) {
return check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
}

View File

@ -1146,6 +1146,24 @@ namespace sol {
}
};
template <typename Allocator>
struct unqualified_pusher<basic_bytecode<Allocator>> {
template <typename T>
static int push(lua_State* L, T&& bc, const char* bytecode_name) {
const auto first = bc.data();
const auto bcsize = bc.size();
// pushes either the function, or an error
// if it errors, shit goes south, and people can test that upstream
(void)luaL_loadbuffer(L, reinterpret_cast<const char*>(first), static_cast<std::size_t>(bcsize * (sizeof(*first) / sizeof(const char))), bytecode_name);
return 1;
}
template <typename T>
static int push(lua_State* L, T&& bc) {
return push(L, std::forward<bc>(bc), "bytecode");
}
};
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
template <typename O>
struct unqualified_pusher<std::optional<O>> {

View File

@ -28,6 +28,7 @@
#include "stack.hpp"
#include "function.hpp"
#include "object.hpp"
#include "lua_value.hpp"
#if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS
#include <iostream>
@ -97,6 +98,7 @@ namespace sol {
set_default_exception_handler(L, exf);
register_main_thread(L);
stack::luajit_exception_handler(L);
lua_value::set_lua_state(L);
}
inline std::size_t total_memory_used(lua_State* L) {

View File

@ -25,6 +25,7 @@
#define SOL_TABLE_HPP
#include "table_core.hpp"
#include "lua_table.hpp"
#include "usertype.hpp"
namespace sol {

View File

@ -25,6 +25,7 @@
#define SOL_TUPLE_HPP
#include "forward.hpp"
#include "base_traits.hpp"
#include <tuple>
#include <cstddef>
@ -35,6 +36,12 @@ namespace sol {
} // namespace detail
namespace meta {
template <typename T>
using is_tuple = is_specialization_of<T, std::tuple>;
template <typename T>
constexpr inline bool is_tuple_v = is_tuple<T>::value;
namespace detail {
template <typename... Args>
struct tuple_types_ { typedef types<Args...> type; };
@ -43,12 +50,6 @@ namespace sol {
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
} // namespace detail
template <typename T>
struct unqualified : std::remove_cv<std::remove_reference_t<T>> {};
template <typename T>
using unqualified_t = typename unqualified<T>::type;
template <typename... Args>
using tuple_types = typename detail::tuple_types_<Args...>::type;

View File

@ -1006,6 +1006,9 @@ namespace sol {
template <>
struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> {};
template <>
struct lua_type_of<lua_value> : std::integral_constant<type, type::poly> {};
template <>
struct lua_type_of<detail::non_lua_nil_t> : std::integral_constant<type, type::poly> {};
@ -1018,6 +1021,9 @@ namespace sol {
template <bool b, typename Base>
struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> {};
template <typename Base>
struct lua_type_of<basic_lua_table<Base>> : std::integral_constant<type, type::table> {};
template <typename Base>
struct lua_type_of<basic_metatable<Base>> : std::integral_constant<type, type::table> {};

View File

@ -124,10 +124,11 @@ namespace sol {
template <typename Fx>
int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const {
auto pp = stack::push_pop(*this);
this->push();
auto ppn = stack::push_popper_n<false>(this->lua_state(), 1);
int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
if (r != 0) {
return on_error(r, writer, userdata, strip);
return on_error(this->lua_state(), r, writer, userdata, strip);
}
return r;
}
@ -136,9 +137,17 @@ namespace sol {
return dump(writer, userdata, strip, &dump_throw_on_error);
}
bytecode dump() const {
bytecode bc;
(void)dump(&bytecode_dump_writer, static_cast<void*>(&bc), strip, &dump_throw_on_error);
template <typename Container = bytecode>
Container dump() const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_panic_on_error);
return bc;
}
template <typename Container = bytecode, typename Fx>
Container dump(Fx&& on_error) const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error));
return bc;
}

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2019-03-14 20:15:14.754895 UTC
// This header was generated with sol v3.0.0 (revision c1a8cb1)
// Generated 2019-03-18 11:40:51.752769 UTC
// This header was generated with sol v3.0.0 (revision 70bc111)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP
@ -264,13 +264,15 @@ namespace sol {
template <typename A>
class basic_bytecode;
struct lua_value;
struct proxy_base_tag;
template <typename Super>
template <typename>
struct proxy_base;
template <typename Table, typename Key>
template <typename, typename>
struct proxy;
template <bool, typename base_type>
template <bool, typename>
class basic_table_core;
template <bool b>
using table_core = basic_table_core<b, reference>;
@ -287,6 +289,11 @@ namespace sol {
using stack_table = stack_table_core<false>;
using stack_global_table = stack_table_core<true>;
template <typename>
struct basic_lua_table;
using lua_table = basic_lua_table<reference>;
using stack_lua_table = basic_lua_table<stack_reference>;
template <typename T, typename base_type>
class basic_usertype;
template <typename T>

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2019-03-14 20:15:14.455770 UTC
// This header was generated with sol v3.0.0 (revision c1a8cb1)
// Generated 2019-03-18 11:40:51.457664 UTC
// This header was generated with sol v3.0.0 (revision 70bc111)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -289,13 +289,15 @@ namespace sol {
template <typename A>
class basic_bytecode;
struct lua_value;
struct proxy_base_tag;
template <typename Super>
template <typename>
struct proxy_base;
template <typename Table, typename Key>
template <typename, typename>
struct proxy;
template <bool, typename base_type>
template <bool, typename>
class basic_table_core;
template <bool b>
using table_core = basic_table_core<b, reference>;
@ -312,6 +314,11 @@ namespace sol {
using stack_table = stack_table_core<false>;
using stack_global_table = stack_table_core<true>;
template <typename>
struct basic_lua_table;
using lua_table = basic_lua_table<reference>;
using stack_lua_table = basic_lua_table<stack_reference>;
template <typename T, typename base_type>
class basic_usertype;
template <typename T>
@ -498,69 +505,6 @@ namespace sol {
// beginning of sol/tuple.hpp
#include <tuple>
#include <cstddef>
namespace sol {
namespace detail {
using swallow = std::initializer_list<int>;
} // namespace detail
namespace meta {
namespace detail {
template <typename... Args>
struct tuple_types_ { typedef types<Args...> type; };
template <typename... Args>
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
} // namespace detail
template <typename T>
struct unqualified : std::remove_cv<std::remove_reference_t<T>> {};
template <typename T>
using unqualified_t = typename unqualified<T>::type;
template <typename... Args>
using tuple_types = typename detail::tuple_types_<Args...>::type;
template <typename Arg>
struct pop_front_type;
template <typename Arg>
using pop_front_type_t = typename pop_front_type<Arg>::type;
template <typename... Args>
struct pop_front_type<types<Args...>> {
typedef void front_type;
typedef types<Args...> type;
};
template <typename Arg, typename... Args>
struct pop_front_type<types<Arg, Args...>> {
typedef Arg front_type;
typedef types<Args...> type;
};
template <std::size_t N, typename Tuple>
using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>;
} // namespace meta
} // namespace sol
// end of sol/tuple.hpp
// beginning of sol/bind_traits.hpp
// beginning of sol/base_traits.hpp
namespace sol {
@ -576,7 +520,16 @@ namespace sol {
template <typename T>
using void_t = void;
template <typename T>
using unqualified = std::remove_cv<std::remove_reference_t<T>>;
template <typename T>
using unqualified_t = typename unqualified<T>::type;
namespace meta_detail {
template <typename T>
struct unqualified_non_alias : unqualified<T> {};
template <template <class...> class Test, class, class... Args>
struct is_detected : std::false_type {};
@ -629,12 +582,6 @@ namespace sol {
template <typename T>
using identity_t = typename identity<T>::type;
template <typename T>
using is_tuple = is_specialization_of<T, std::tuple>;
template <typename T>
constexpr inline bool is_tuple_v = is_tuple<T>::value;
template <typename T>
using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>;
@ -643,6 +590,69 @@ namespace sol {
// end of sol/base_traits.hpp
#include <tuple>
#include <cstddef>
namespace sol {
namespace detail {
using swallow = std::initializer_list<int>;
} // namespace detail
namespace meta {
template <typename T>
using is_tuple = is_specialization_of<T, std::tuple>;
template <typename T>
constexpr inline bool is_tuple_v = is_tuple<T>::value;
namespace detail {
template <typename... Args>
struct tuple_types_ { typedef types<Args...> type; };
template <typename... Args>
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
} // namespace detail
template <typename... Args>
using tuple_types = typename detail::tuple_types_<Args...>::type;
template <typename Arg>
struct pop_front_type;
template <typename Arg>
using pop_front_type_t = typename pop_front_type<Arg>::type;
template <typename... Args>
struct pop_front_type<types<Args...>> {
typedef void front_type;
typedef types<Args...> type;
};
template <typename Arg, typename... Args>
struct pop_front_type<types<Arg, Args...>> {
typedef Arg front_type;
typedef types<Args...> type;
};
template <std::size_t N, typename Tuple>
using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>;
template <std::size_t N, typename Tuple>
using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>;
} // namespace meta
} // namespace sol
// end of sol/tuple.hpp
// beginning of sol/bind_traits.hpp
namespace sol {
namespace meta {
namespace meta_detail {
@ -2041,13 +2051,7 @@ namespace sol {
#endif // SOL_FORWARD_DETAIL_HPP
// end of sol/forward_detail.hpp
// beginning of sol/stack.hpp
// beginning of sol/trampoline.hpp
// beginning of sol/types.hpp
// beginning of sol/error.hpp
// beginning of sol/bytecode.hpp
// beginning of sol/compatibility.hpp
@ -3369,6 +3373,99 @@ COMPAT53_API void luaL_requiref(lua_State *L, const char *modname,
// end of sol/compatibility.hpp
#include <vector>
namespace sol {
template <typename Allocator = std::allocator<std::byte>>
class basic_bytecode : private std::vector<std::byte, Allocator> {
private:
using base_t = std::vector<std::byte, Allocator>;
public:
using base_t::allocator_type;
using base_t::const_iterator;
using base_t::const_pointer;
using base_t::const_reference;
using base_t::const_reverse_iterator;
using base_t::difference_type;
using base_t::iterator;
using base_t::pointer;
using base_t::reference;
using base_t::reverse_iterator;
using base_t::size_type;
using base_t::value_type;
using base_t::base_t;
using base_t::operator=;
using base_t::data;
using base_t::empty;
using base_t::max_size;
using base_t::size;
using base_t::at;
using base_t::operator[];
using base_t::back;
using base_t::front;
using base_t::begin;
using base_t::cbegin;
using base_t::cend;
using base_t::end;
using base_t::crbegin;
using base_t::crend;
using base_t::rbegin;
using base_t::rend;
using base_t::swap;
using base_t::get_allocator;
using base_t::emplace;
using base_t::emplace_back;
using base_t::insert;
using base_t::pop_back;
using base_t::push_back;
using base_t::reserve;
using base_t::resize;
using base_t::shrink_to_fit;
string_view as_string_view () const {
return string_view(reinterpret_cast<const char*>(this->data()), this->size());
}
};
template <typename Container>
inline int basic_insert_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata) {
using storage_t = Container;
const std::byte* p_code = static_cast<const std::byte*>(memory);
storage_t& bc = *static_cast<storage_t*>(userdata);
try {
bc.insert(bc.cend(), p_code, p_code + memory_size);
}
catch ( ... ) {
return -1;
}
return 0;
}
using bytecode = basic_bytecode<>;
constexpr inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>;
} // namespace sol
// end of sol/bytecode.hpp
// beginning of sol/stack.hpp
// beginning of sol/trampoline.hpp
// beginning of sol/types.hpp
// beginning of sol/error.hpp
#include <stdexcept>
namespace sol {
@ -7017,6 +7114,9 @@ namespace sol {
template <>
struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> {};
template <>
struct lua_type_of<lua_value> : std::integral_constant<type, type::poly> {};
template <>
struct lua_type_of<detail::non_lua_nil_t> : std::integral_constant<type, type::poly> {};
@ -7029,6 +7129,9 @@ namespace sol {
template <bool b, typename Base>
struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> {};
template <typename Base>
struct lua_type_of<basic_lua_table<Base>> : std::integral_constant<type, type::table> {};
template <typename Base>
struct lua_type_of<basic_metatable<Base>> : std::integral_constant<type, type::table> {};
@ -8917,7 +9020,6 @@ namespace sol {
// end of sol/stack_guard.hpp
#include <vector>
#include <bitset>
#include <forward_list>
#include <algorithm>
@ -9476,9 +9578,9 @@ namespace sol {
template <typename T, typename = void>
struct unqualified_pusher;
template <typename T, type t, typename>
template <typename T, type t, typename = void>
struct unqualified_checker;
template <typename T, type t, typename>
template <typename T, type t, typename = void>
struct qualified_checker;
template <typename T, typename = void>
@ -9803,7 +9905,7 @@ namespace sol {
return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
unqualified_checker<Tu> c;
unqualified_checker<Tu, lua_type_of_v<Tu>> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
@ -9828,7 +9930,8 @@ namespace sol {
return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking);
}
else {
qualified_checker<T> c;
using Tu = meta::unqualified_t<T>;
qualified_checker<T, lua_type_of_v<Tu>> c;
// VC++ has a bad warning here: shut it up
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
@ -9927,6 +10030,11 @@ namespace sol {
namespace stack_detail {
template <typename Handler>
inline bool check_types(lua_State*, int, Handler&&, record&) {
return true;
}
template <typename T, typename... Args, typename Handler>
inline bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) {
if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking))
@ -9934,13 +10042,8 @@ namespace sol {
return check_types<Args...>(L, firstargument, std::forward<Handler>(handler), tracking);
}
template <typename Handler>
static bool check_types(lua_State*, int, Handler&&, record&) {
return true;
}
template <typename... Args, typename Handler>
bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) {
inline bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) {
return check_types<Args...>(L, index, std::forward<Handler>(handler), tracking);
}
@ -10323,7 +10426,7 @@ namespace sol { namespace stack {
}
};
template <typename T, type expected = lua_type_of_v<T>, typename = void>
template <typename T, type expected, typename>
struct unqualified_checker {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
@ -10488,6 +10591,24 @@ namespace sol { namespace stack {
else if constexpr (std::is_same_v<T, detail::non_lua_nil_t>) {
return !stack::unqualified_check<lua_nil_t>(L, index, std::forward<Handler>(handler), tracking);
}
else if constexpr (meta::is_specialization_of_v<T, basic_lua_table>) {
tracking.use(1);
type t = type_of(L, index);
if (t != type::table) {
handler(L, index, type::table, t, "value is not a table");
return false;
}
return true;
}
else if constexpr (meta::is_specialization_of_v<T, basic_bytecode>) {
tracking.use(1);
type t = type_of(L, index);
if (t != type::function) {
handler(L, index, type::function, t, "value is not a function that can be dumped");
return false;
}
return true;
}
else if constexpr(meta::is_specialization_of_v<T, basic_environment>) {
tracking.use(1);
if (lua_getmetatable(L, index) == 0) {
@ -10534,7 +10655,7 @@ namespace sol { namespace stack {
return success;
}
else if constexpr (meta::is_specialization_of_v<T, user>) {
unqualified_checker<lightuserdata_value> c;
unqualified_checker<lightuserdata_value, type::userdata> c;
(void)c;
return c.check(L, index, std::forward<Handler>(handler), tracking);
}
@ -10652,51 +10773,59 @@ namespace sol { namespace stack {
template <typename U, typename Handler>
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 (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
return true;
}
#endif // interop extensibility
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
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>>::value)
return true;
if (lua_getmetatable(L, index) == 0) {
return true;
}
int metatableindex = lua_gettop(L);
if (stack_detail::check_metatable<U>(L, metatableindex))
return true;
if (stack_detail::check_metatable<U*>(L, metatableindex))
return true;
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex))
return true;
if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex))
return true;
bool success = false;
bool has_derived = derive<T>::value || weak_derive<T>::value;
if (has_derived) {
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
#endif // make sure stack doesn't overflow
auto pn = stack::pop_n(L, 1);
lua_pushstring(L, &detail::base_class_check_key()[0]);
lua_rawget(L, metatableindex);
if (type_of(L, -1) != type::lua_nil) {
void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata);
success = ic(usertype_traits<T>::qualified_name());
if constexpr (std::is_same_v<T, lightuserdata_value> || std::is_same_v<T, userdata_value> || std::is_same_v<T, userdata> || std::is_same_v<T, lightuserdata>) {
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
return false;
}
return true;
}
lua_pop(L, 1);
if (!success) {
handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type");
return false;
else {
#if defined(SOL_ENABLE_INTEROP) && SOL_ENABLE_INTEROP
if (stack_detail::interop_check<U>(L, index, indextype, handler, tracking)) {
return true;
}
#endif // interop extensibility
tracking.use(1);
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
return false;
}
if (lua_getmetatable(L, index) == 0) {
return true;
}
int metatableindex = lua_gettop(L);
if (stack_detail::check_metatable<U>(L, metatableindex))
return true;
if (stack_detail::check_metatable<U*>(L, metatableindex))
return true;
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex))
return true;
if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex))
return true;
bool success = false;
bool has_derived = derive<T>::value || weak_derive<T>::value;
if (has_derived) {
#if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK
luaL_checkstack(L, 1, detail::not_enough_stack_space_string);
#endif // make sure stack doesn't overflow
auto pn = stack::pop_n(L, 1);
lua_pushstring(L, &detail::base_class_check_key()[0]);
lua_rawget(L, metatableindex);
if (type_of(L, -1) != type::lua_nil) {
void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata);
success = ic(usertype_traits<T>::qualified_name());
}
}
lua_pop(L, 1);
if (!success) {
handler(L, index, type::userdata, indextype, "value at this index does not properly reflect the desired type");
return false;
}
return true;
}
return true;
}
};
@ -10819,7 +10948,7 @@ namespace sol { namespace stack {
namespace sol {
namespace stack {
template <typename X, type expected = lua_type_of_v<meta::unqualified_t<X>>, typename = void>
template <typename X, type expected, typename>
struct qualified_checker {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
@ -13537,6 +13666,24 @@ namespace sol {
}
};
template <typename Allocator>
struct unqualified_pusher<basic_bytecode<Allocator>> {
template <typename T>
static int push(lua_State* L, T&& bc, const char* bytecode_name) {
const auto first = bc.data();
const auto bcsize = bc.size();
// pushes either the function, or an error
// if it errors, shit goes south, and people can test that upstream
(void)luaL_loadbuffer(L, reinterpret_cast<const char*>(first), static_cast<std::size_t>(bcsize * (sizeof(*first) / sizeof(const char))), bytecode_name);
return 1;
}
template <typename T>
static int push(lua_State* L, T&& bc) {
return push(L, std::forward<bc>(bc), "bytecode");
}
};
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
template <typename O>
struct unqualified_pusher<std::optional<O>> {
@ -17110,7 +17257,7 @@ namespace sol {
stack::push(L, c_closure(freefunc, upvalues));
}
else if constexpr (sizeof...(Args) < 2) {
using Tu = typename meta::unqualified<Args...>::type;
using Tu = typename meta::meta_detail::unqualified_non_alias<Args...>::type;
constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx, is_yielding>::call;
@ -17574,76 +17721,6 @@ namespace sol {
// end of sol/function_types.hpp
// beginning of sol/bytecode.hpp
namespace sol {
template <typename Allocator = std::allocator<std::byte>>
class basic_bytecode : private std::vector<std::byte, Allocator> {
private:
using base_t = std::vector<std::byte, Allocator>;
public:
using base_t::value_type;
using base_t::base_t;
using base_t::operator=;
using base_t::data;
using base_t::empty;
using base_t::max_size;
using base_t::size;
using base_t::at;
using base_t::operator[];
using base_t::back;
using base_t::front;
using base_t::begin;
using base_t::cbegin;
using base_t::cend;
using base_t::end;
using base_t::crbegin;
using base_t::crend;
using base_t::rbegin;
using base_t::rend;
using base_t::swap;
using base_t::get_allocator;
using base_t::emplace;
using base_t::emplace_back;
using base_t::insert;
using base_t::pop_back;
using base_t::push_back;
using base_t::reserve;
using base_t::resize;
using base_t::shrink_to_fit;
string_view as_string_view () const {
return string_view(reinterpret_cast<const char*>(this->data()), this->size());
}
};
using bytecode = basic_bytecode<>;
inline int bytecode_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata) {
const std::byte* p_code = static_cast<const std::byte*>(memory);
bytecode& bc = *static_cast<bytecode*>(userdata);
try {
bc.insert(bc.cend(), p_code, p_code + memory_size);
}
catch ( ... ) {
return -1;
}
return 0;
}
} // namespace sol
// end of sol/bytecode.hpp
// beginning of sol/dump_handler.hpp
namespace sol {
@ -17661,19 +17738,29 @@ namespace sol {
}
};
inline int dump_pass_on_error(int result_code, lua_Writer writer_function, void* userdata, bool strip) {
inline int dump_pass_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
(void)L;
(void)writer_function;
(void)userdata;
(void)strip;
return result_code;
}
inline int dump_throw_on_error(int result_code, lua_Writer writer_function, void* userdata, bool strip) {
inline int dump_throw_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
(void)L;
(void)writer_function;
(void)userdata;
(void)strip;
throw dump_error(result_code);
}
}
inline int dump_panic_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) {
(void)L;
(void)writer_function;
(void)userdata;
(void)strip;
return luaL_error(L, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code);
}
} // namespace sol
@ -17770,10 +17857,11 @@ namespace sol {
template <typename Fx>
int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const {
auto pp = stack::push_pop(*this);
this->push();
auto ppn = stack::push_popper_n<false>(this->lua_state(), 1);
int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
if (r != 0) {
return on_error(r, writer, userdata, strip);
return on_error(this->lua_state(), r, writer, userdata, strip);
}
return r;
}
@ -17782,9 +17870,17 @@ namespace sol {
return dump(writer, userdata, strip, &dump_throw_on_error);
}
bytecode dump() const {
bytecode bc;
(void)dump(&bytecode_dump_writer, static_cast<void*>(&bc), strip, &dump_throw_on_error);
template <typename Container = bytecode>
Container dump() const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_panic_on_error);
return bc;
}
template <typename Container = bytecode, typename Fx>
Container dump(Fx&& on_error) const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error));
return bc;
}
@ -18125,10 +18221,11 @@ namespace sol {
template <typename Fx>
int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const {
auto pp = stack::push_pop(*this);
this->push();
auto ppn = stack::push_popper_n<false>(this->lua_state(), 1);
int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0);
if (r != 0) {
return on_error(r, writer, userdata, strip);
return on_error(this->lua_state(), r, writer, userdata, strip);
}
return r;
}
@ -18137,9 +18234,17 @@ namespace sol {
return dump(writer, userdata, strip, &dump_pass_on_error);
}
bytecode dump() const {
bytecode bc;
(void)dump(&bytecode_dump_writer, static_cast<void*>(&bc), false, &dump_throw_on_error);
template <typename Container = bytecode>
Container dump() const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_throw_on_error);
return bc;
}
template <typename Container = bytecode, typename Fx>
Container dump(Fx&& on_error) const {
Container bc;
(void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error));
return bc;
}
@ -18288,8 +18393,7 @@ namespace sol {
}
static std::function<Signature> get(lua_State* L, int index, record& tracking) {
tracking.last = 1;
tracking.used += 1;
tracking.use(1);
type t = type_of(L, index);
if (t == type::none || t == type::lua_nil) {
return nullptr;
@ -18297,6 +18401,15 @@ namespace sol {
return get_std_func(return_types(), L, index);
}
};
template <typename Allocator>
struct unqualified_getter<basic_bytecode<Allocator>> {
static basic_bytecode<Allocator> get(lua_State* L, int index, record& tracking) {
tracking.use(1);
stack_function sf(L, index);
return sf.dump(&dump_panic_on_error);
}
};
} // namespace stack
} // namespace sol
@ -22479,6 +22592,76 @@ namespace sol {
// beginning of sol/table.hpp
// beginning of sol/lua_table.hpp
namespace sol {
template <typename ref_t>
struct basic_lua_table : basic_table_core<false, ref_t> {
private:
using base_t = basic_table_core<false, ref_t>;
friend class state;
friend class state_view;
public:
using base_t::lua_state;
basic_lua_table() noexcept = default;
basic_lua_table(const basic_lua_table&) = default;
basic_lua_table(basic_lua_table&&) = default;
basic_lua_table& operator=(const basic_lua_table&) = default;
basic_lua_table& operator=(basic_lua_table&&) = default;
basic_lua_table(const stack_reference& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
basic_lua_table(stack_reference&& r) : basic_lua_table(r.lua_state(), r.stack_index()) {
}
template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, const new_table& nt) : base_t(L, nt) {
if (!is_stack_based<meta::unqualified_t<ref_t>>::value) {
lua_pop(L, 1);
}
}
basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
constructor_handler handler{};
stack::check<basic_lua_table>(L, index, handler);
#endif // Safety
}
basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_lua_table>(lua_state(), -1, handler);
#endif // Safety
}
template <typename T,
meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>,
meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) {
#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES
if (!is_table<meta::unqualified_t<T>>::value) {
auto pp = stack::push_pop(*this);
constructor_handler handler{};
stack::check<basic_lua_table>(lua_state(), -1, handler);
}
#endif // Safety
}
basic_lua_table(lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) {
}
};
}
// end of sol/lua_table.hpp
namespace sol {
typedef table_core<false> table;
@ -22878,6 +23061,109 @@ namespace sol {
// beginning of sol/state_handling.hpp
// beginning of sol/lua_value.hpp
namespace sol {
namespace detail {
template <typename T>
using is_reference_or_lua_value_init_list = meta::any<meta::is_specialization_of<T, std::initializer_list>, std::is_same<T, reference>>;
template <typename T>
using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>;
}
struct lua_value {
private:
static lua_State*& thread_local_lua_state() {
static thread_local lua_State* L = nullptr;
return L;
}
reference ref_value;
public:
static void set_lua_state(lua_State* L) {
thread_local_lua_state() = L;
}
template <typename T, meta::disable<detail::is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
lua_value(lua_State* L_, T&& value) : lua_value(((set_lua_state(L_)), std::forward<T>(value))) {
}
template <typename T, meta::disable<detail::is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) {
}
lua_value(lua_State* L_, std::initializer_list<lua_value> il) : lua_value(((set_lua_state(L_)), std::move(il))) {
}
lua_value(std::initializer_list<lua_value> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) {
}
lua_value(lua_State* L_, reference r) : lua_value(((thread_local_lua_state() = L_), std::move(r))) {
}
lua_value(reference r) : ref_value(std::move(r)) {
}
lua_value(const lua_value&) noexcept = default;
lua_value(lua_value&&) = default;
lua_value& operator=(const lua_value&) = default;
lua_value& operator=(lua_value&&) = default;
const reference& value() const& {
return ref_value;
}
reference& value() & {
return ref_value;
}
reference&& value() && {
return std::move(ref_value);
}
template <typename T>
decltype(auto) as() const {
ref_value.push();
return stack::pop<T>(ref_value.lua_state());
}
template <typename T>
bool is() const {
int r = ref_value.registry_index();
if (r == LUA_REFNIL)
return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false;
if (r == LUA_NOREF)
return false;
auto pp = stack::push_pop(ref_value);
return stack::check<T>(ref_value.lua_state(), -1, no_panic);
}
};
namespace stack {
template <>
struct unqualified_pusher<lua_value> {
static int push(lua_State* L, const lua_value& lv) {
return stack::push(L, lv.value());
}
static int push(lua_State* L, lua_value&& lv) {
return stack::push(L, std::move(lv).value());
}
};
template <>
struct unqualified_getter<lua_value> {
static lua_value get(lua_State* L, int index, record& tracking) {
return lua_value(L, stack::get<reference>(L, index, tracking));
}
};
}
} // namespace sol
// end of sol/lua_value.hpp
#if defined(SOL_PRINT_ERRORS) && SOL_PRINT_ERRORS
#endif
@ -22945,6 +23231,7 @@ namespace sol {
set_default_exception_handler(L, exf);
register_main_thread(L);
stack::luajit_exception_handler(L);
lua_value::set_lua_state(L);
}
inline std::size_t total_memory_used(lua_State* L) {

View File

@ -0,0 +1,26 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_defines.hpp"
#include <sol/lua_table.hpp>

View File

@ -0,0 +1,26 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_defines.hpp"
#include <sol/lua_value.hpp>

View File

@ -255,6 +255,7 @@ end
TEST_CASE("containers/sequence containers", "check all of the functinos for every single container") {
SECTION("vector") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
std::vector<int> items{ 11, 12, 13, 14, 15 };
@ -263,6 +264,7 @@ TEST_CASE("containers/sequence containers", "check all of the functinos for ever
}
SECTION("list") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
std::list<int> items{ 11, 12, 13, 14, 15 };
@ -271,6 +273,7 @@ TEST_CASE("containers/sequence containers", "check all of the functinos for ever
}
SECTION("forward_list") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
std::forward_list<int> items{ 11, 12, 13, 14, 15 };
@ -279,6 +282,7 @@ TEST_CASE("containers/sequence containers", "check all of the functinos for ever
}
SECTION("deque") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
std::deque<int> items{ 11, 12, 13, 14, 15 };
@ -290,6 +294,7 @@ TEST_CASE("containers/sequence containers", "check all of the functinos for ever
TEST_CASE("containers/fixed containers", "check immutable container types") {
SECTION("array") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
std::array<int, 5> items{ { 11, 12, 13, 14, 15 } };
@ -298,6 +303,7 @@ TEST_CASE("containers/fixed containers", "check immutable container types") {
}
SECTION("array ref") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
std::array<int, 5> items{ { 11, 12, 13, 14, 15 } };
@ -306,6 +312,7 @@ TEST_CASE("containers/fixed containers", "check immutable container types") {
}
SECTION("c array") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
int items[5] = { 11, 12, 13, 14, 15 };
@ -314,6 +321,7 @@ TEST_CASE("containers/fixed containers", "check immutable container types") {
}
SECTION("c array ref") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
int items[5] = { 11, 12, 13, 14, 15 };
@ -324,6 +332,7 @@ TEST_CASE("containers/fixed containers", "check immutable container types") {
TEST_CASE("containers/auxiliary functions test", "make sure the manipulation functions are present and usable and working across various container types") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries();
auto result1 = lua.safe_script(R"(
@ -407,6 +416,8 @@ TEST_CASE("containers/indices test", "test indices on fixed array types") {
#if 0
SECTION("zero index test") {
sol::state lua;
sol::stack_guard luasg(lua);
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
auto result = lua.safe_script(R"(
c_arr[0] = 7
@ -416,6 +427,8 @@ c_arr[0] = 7
SECTION("negative index test") {
sol::state lua;
sol::stack_guard luasg(lua);
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
auto result = lua.safe_script(R"(
c_arr[-1] = 7

View File

@ -100,6 +100,8 @@ end
)";
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
auto result1 = lua.safe_script(script);
REQUIRE(result1.valid());
@ -127,6 +129,8 @@ end
)";
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
auto result = lua.safe_script(code, sol::script_pass_on_error);
REQUIRE(result.valid());
@ -146,6 +150,8 @@ end
TEST_CASE("coroutines/transfer", "test that things created inside of a coroutine can have their state transferred using lua_xmove constructors") {
for (std::size_t tries = 0; tries < 200; ++tries) {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries();
{
sol::function f2;

View File

@ -60,7 +60,7 @@ namespace sol {
namespace stack {
template <>
struct unqualified_checker<two_things> {
struct unqualified_checker<two_things, type::poly> {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
bool success = stack::check<int>(L, index, handler) && stack::check<bool>(L, index + 1, handler);
@ -89,7 +89,7 @@ namespace sol {
};
template <>
struct unqualified_checker<number_shim> {
struct unqualified_checker<number_shim, type::poly> {
template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
if (!check_usertype<number_shim>(L, index) && !stack::check<double>(L, index)) {

View File

@ -25,19 +25,97 @@
#include <catch.hpp>
TEST_CASE("dump/dump transfer", "test that a function can be transferred from one place to another") {
sol::state lua;
sol::state lua2;
lua2.open_libraries(sol::lib::base);
#include <list>
#include <vector>
#include <deque>
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::protected_function target = lr;
sol::bytecode target_bc = target.dump();
int dump_always_fail_number = -32;
auto result2 = lua2.safe_script(target_bc.as_string_view(), sol::script_pass_on_error);
REQUIRE(result2.valid());
sol::protected_function pf = lua2["a"];
int v = pf(25557);
REQUIRE(v == 25557);
int dump_always_fail(lua_State*, const void*, size_t, void*) {
return dump_always_fail_number;
}
TEST_CASE("dump/dump transfer", "test that a function can be transferred from one place to another") {
SECTION("safe") {
sol::state lua;
sol::state lua2;
lua2.open_libraries(sol::lib::base);
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::protected_function target = lr;
sol::bytecode target_bc = target.dump();
auto result2 = lua2.safe_script(target_bc.as_string_view(), sol::script_pass_on_error);
REQUIRE(result2.valid());
sol::protected_function pf = lua2["a"];
int v = pf(25557);
REQUIRE(v == 25557);
}
SECTION("unsafe") {
sol::state lua;
sol::state lua2;
lua2.open_libraries(sol::lib::base);
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::unsafe_function target = lr;
sol::bytecode target_bc = target.dump();
auto result2 = lua2.safe_script(target_bc.as_string_view(), sol::script_pass_on_error);
REQUIRE(result2.valid());
sol::unsafe_function pf = lua2["a"];
int v = pf(25557);
REQUIRE(v == 25557);
}
}
TEST_CASE("dump/failure", "test that failure is properly propagated") {
SECTION("safe") {
sol::state lua;
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::protected_function target = lr;
int err = target.dump(&dump_always_fail, nullptr, false, sol::dump_pass_on_error);
REQUIRE(err == dump_always_fail_number);
}
SECTION("unsafe") {
sol::state lua;
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::unsafe_function target = lr;
int err = target.dump(&dump_always_fail, nullptr, false, sol::dump_pass_on_error);
REQUIRE(err == dump_always_fail_number);
}
}
TEST_CASE("dump/different containers", "test that dump inserter works for various kinds of containers") {
SECTION("safe") {
sol::state lua;
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::protected_function target = lr;
sol::bytecode bytecode_dump = target.dump();
std::list<std::byte> list_dump = target.dump<std::list<std::byte>>();
std::vector<std::byte> vector_dump = target.dump<std::vector<std::byte>>();
std::deque<std::byte> deque_dump = target.dump<std::deque<std::byte>>();
REQUIRE(std::equal(bytecode_dump.cbegin(), bytecode_dump.cend(), vector_dump.cbegin(), vector_dump.cend()));
REQUIRE(std::equal(bytecode_dump.cbegin(), bytecode_dump.cend(), list_dump.cbegin(), list_dump.cend()));
REQUIRE(std::equal(bytecode_dump.cbegin(), bytecode_dump.cend(), deque_dump.cbegin(), deque_dump.cend()));
}
SECTION("unsafe") {
sol::state lua;
sol::load_result lr = lua.load("a = function (v) print(v) return v end");
REQUIRE(lr.valid());
sol::unsafe_function target = lr;
sol::bytecode bytecode_dump = target.dump();
std::list<std::byte> list_dump = target.dump<std::list<std::byte>>();
std::vector<std::byte> vector_dump = target.dump<std::vector<std::byte>>();
std::deque<std::byte> deque_dump = target.dump<std::deque<std::byte>>();
REQUIRE(std::equal(bytecode_dump.cbegin(), bytecode_dump.cend(), vector_dump.cbegin(), vector_dump.cend()));
REQUIRE(std::equal(bytecode_dump.cbegin(), bytecode_dump.cend(), list_dump.cbegin(), list_dump.cend()));
REQUIRE(std::equal(bytecode_dump.cbegin(), bytecode_dump.cend(), deque_dump.cbegin(), deque_dump.cend()));
}
}

View File

@ -30,6 +30,7 @@
TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
auto result1 = lua.safe_script("f = function() return test end", sol::script_pass_on_error);
@ -62,7 +63,7 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f
lua.set_function("check_f_env",
[&lua, &env_f](sol::object target) {
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::environment target_env(sol::env_key, target);
int test_env_f = env_f["test"];
int test_target_env = target_env["test"];
@ -72,7 +73,7 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f
});
lua.set_function("check_g_env",
[&lua, &env_g](sol::function target) {
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::environment target_env = sol::get_environment(target);
int test_env_g = env_g["test"];
int test_target_env = target_env["test"];
@ -82,7 +83,7 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f
});
lua.set_function("check_h_env",
[&lua](sol::function target) {
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::environment target_env = sol::get_environment(target);
});
@ -97,6 +98,8 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f
TEST_CASE("environments/shadowing", "Environments can properly shadow and fallback on variables") {
sol::state lua;
sol::stack_guard luasg(lua);
lua["b"] = 2142;
SECTION("no fallback") {
@ -179,6 +182,7 @@ TEST_CASE("environments/functions", "see if environments on functions are workin
SECTION("basic") {
sol::state lua;
sol::stack_guard luasg(lua);
auto result1 = lua.safe_script("a = function() return 5 end", sol::script_pass_on_error);
REQUIRE(result1.valid());
@ -196,6 +200,7 @@ TEST_CASE("environments/functions", "see if environments on functions are workin
}
SECTION("return environment value") {
sol::state lua;
sol::stack_guard luasg(lua);
auto result1 = lua.safe_script("a = function() return test end", sol::script_pass_on_error);
REQUIRE(result1.valid());
@ -212,6 +217,8 @@ TEST_CASE("environments/functions", "see if environments on functions are workin
SECTION("set environment value") {
sol::state lua;
sol::stack_guard luasg(lua);
auto result1 = lua.safe_script("a = function() test = 5 end", sol::script_pass_on_error);
REQUIRE(result1.valid());
@ -235,6 +242,7 @@ TEST_CASE("environments/this_environment", "test various situations of pulling o
static std::string code = "return (f(10))";
sol::state lua;
sol::stack_guard luasg(lua);
lua["f"] = [](sol::this_environment te, int x, sol::this_state ts) {
if (te) {

View File

@ -145,6 +145,8 @@ TEST_CASE("functions/tuple returns", "Make sure tuple returns are ordered proper
TEST_CASE("functions/overload resolution", "Check if overloaded function resolution templates compile/work") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.set_function("non_overloaded", non_overloaded);
@ -188,9 +190,9 @@ TEST_CASE("functions/return order and multi get", "Check if return order is in t
const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12);
const static std::tuple<int, float> paired = std::make_tuple(10, 10.f);
sol::state lua;
lua.set_function("f", [] {
return std::make_tuple(10, 11, 12);
});
sol::stack_guard luasg(lua);
lua.set_function("f", [] { return std::make_tuple(10, 11, 12); });
lua.set_function("h", []() {
return std::make_tuple(10, 10.0f);
});
@ -260,8 +262,9 @@ end )", sol::script_pass_on_error);
TEST_CASE("functions/pair and tuple and proxy tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") {
sol::state lua;
lua.new_usertype<A>("A",
"bark", &A::bark);
sol::stack_guard luasg(lua);
lua.new_usertype<A>("A", "bark", &A::bark);
auto result1 = lua.safe_script(R"( function f (num_value, a)
return num_value * 2, a:bark()
end
@ -302,6 +305,8 @@ nested = { variables = { no = { problem = 10 } } } )", sol::script_pass_on_error
TEST_CASE("functions/sol::function to std::function", "check if conversion to std::function works properly and calls with correct arguments") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.set_function("testFunc", test_free_func);
@ -336,12 +341,14 @@ TEST_CASE("functions/returning functions from C++", "check to see if returning a
}
TEST_CASE("functions/function_result and protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::debug);
static const char unhandlederrormessage[] = "true error message";
static const char handlederrormessage[] = "doodle";
static const std::string handlederrormessage_s = handlederrormessage;
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base, sol::lib::debug);
// Some function; just using a lambda to be cheap
auto doomfx = []() {
throw std::runtime_error(unhandlederrormessage);
@ -512,6 +519,7 @@ TEST_CASE("functions/unsafe protected_function_result handlers",
TEST_CASE("functions/all kinds", "Register all kinds of functions, make sure they all compile and work") {
sol::state lua;
sol::stack_guard luasg(lua);
struct test_1 {
int a = 0xA;
@ -972,14 +980,14 @@ TEST_CASE("functions/stack atomic", "make sure functions don't impede on the sta
//test protected_function
sol::protected_function Stringtest(lua["stringtest"]);
Stringtest.error_handler = lua["ErrorHandler"];
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
{
sol::protected_function_result stringresult = Stringtest("protected test");
REQUIRE(stringresult.valid());
std::string s = stringresult;
INFO("Back in C++, protected result is : " << s);
}
REQUIRE(sg.check_stack());
REQUIRE(luasg.check_stack());
//test optional
{
@ -994,7 +1002,7 @@ TEST_CASE("functions/stack atomic", "make sure functions don't impede on the sta
INFO("opt_result failed");
}
}
REQUIRE(sg.check_stack());
REQUIRE(luasg.check_stack());
{
sol::protected_function_result errresult = Stringtest(sol::lua_nil);
@ -1003,7 +1011,7 @@ TEST_CASE("functions/stack atomic", "make sure functions don't impede on the sta
std::string msg = err.what();
INFO("error :" << msg);
}
REQUIRE(sg.check_stack());
REQUIRE(luasg.check_stack());
}
TEST_CASE("functions/stack multi-return", "Make sure the stack is protected after multi-returns") {
@ -1011,7 +1019,7 @@ TEST_CASE("functions/stack multi-return", "Make sure the stack is protected afte
lua.safe_script("function f () return 1, 2, 3, 4, 5 end");
{
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::stack::push(lua, double(256.78));
{
int a, b, c, d, e;
@ -1034,7 +1042,7 @@ TEST_CASE("functions/protected stack multi-return", "Make sure the stack is prot
lua.safe_script("function f () return 1, 2, 3, 4, 5 end");
{
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::stack::push(lua, double(256.78));
{
int a, b, c, d, e;
@ -1060,7 +1068,7 @@ TEST_CASE("functions/function_result as arguments", "ensure that function_result
lua.safe_script("function g (a, b, c, d, e) assert(a == 1) assert(b == 2) assert(c == 3) assert(d == 4) assert(e == 5) end");
{
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::stack::push(lua, double(256.78));
{
int a, b, c, d, e;
@ -1089,7 +1097,7 @@ TEST_CASE("functions/protected_function_result as arguments", "ensure that prote
lua.safe_script("function g (a, b, c, d, e) assert(a == 1) assert(b == 2) assert(c == 3) assert(d == 4) assert(e == 5) end");
{
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::stack::push(lua, double(256.78));
{
int a, b, c, d, e;

View File

@ -0,0 +1,310 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
#include <vector>
#include <thread>
#include <mutex>
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
#include <string_view>
#include <variant>
#endif // C++17
struct int_entry {
int value;
int_entry() : value(0) {
}
int_entry(int v) : value(v) {
}
bool operator==(const int_entry& e) const {
return value == e.value;
}
};
std::mutex lua_value_construct_require_mutex;
void lua_value_construct_race() {
sol::state lua;
try {
lua.open_libraries();
lua["a"] = sol::lua_value(lua, 24);
int a = lua["a"];
{
std::lock_guard<std::mutex> lg(lua_value_construct_require_mutex);
REQUIRE(a == 24);
}
}
catch (const sol::error& e) {
std::lock_guard<std::mutex> lg(lua_value_construct_require_mutex);
INFO(e.what());
REQUIRE(false);
}
catch (...) {
std::lock_guard<std::mutex> lg(lua_value_construct_require_mutex);
REQUIRE(false);
}
}
TEST_CASE("lua_value/nested", "make nested values can be put in lua_value properly") {
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
using mixed_table_entry = std::variant<int, int_entry, std::string>;
using nested_entry = std::variant<int, int_entry, std::string, std::vector<mixed_table_entry>>;
const std::vector<std::variant<int, int_entry>> mixed_table_truth = { 1, int_entry(2), 3, int_entry(4), 5 };
const std::vector<nested_entry> mixed_nested_table_truth = { 1, int_entry(2), 3, int_entry(4), std::vector<mixed_table_entry>{ 5, 6, int_entry(7), "8" } };
sol::state lua;
sol::lua_value lv_mixed_table(lua, { 1, int_entry(2), 3, int_entry(4), 5 });
sol::lua_value lv_mixed_nested_table(lua, { 1, int_entry(2), 3, int_entry(4), { 5, 6, int_entry(7), "8" } });
REQUIRE(lv_mixed_table.is<sol::table>());
REQUIRE(lv_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value_lv = lv_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value_lv = lv_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value_lv);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value_lv);
SECTION("type check (object)") {
sol::object obj_mixed_table(lv_mixed_table.value());
sol::object obj_mixed_nested_table(lv_mixed_nested_table.value());
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
SECTION("pushing/popping") {
lua["obj_mixed_table"] = lv_mixed_table;
lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
sol::lua_value obj_mixed_table = lua["obj_mixed_table"];
sol::lua_value obj_mixed_nested_table = lua["obj_mixed_nested_table"];
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
SECTION("pushing/popping (object)") {
lua["obj_mixed_table"] = lv_mixed_table;
lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
sol::object obj_mixed_table = lua["obj_mixed_table"];
sol::object obj_mixed_nested_table = lua["obj_mixed_nested_table"];
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
#else
REQUIRE(true);
#endif // C++17
}
TEST_CASE("lua_value/basic types", "make sure we can stick values and nested values in a lua_value and retrieve them") {
sol::state lua;
const int_entry userdata_truth = int_entry(3);
const std::vector<int> int_table_truth = { 1, 2, 3, 4, 5 };
sol::lua_value lv_int(lua, 1);
sol::lua_value lv_double(lua, 2.0);
sol::lua_value lv_string(lua, "heyo");
sol::lua_value lv_lstring(lua, L"hiyo");
sol::lua_value lv_bool(lua, true);
sol::lua_value lv_nil(lua, sol::lua_nil);
sol::lua_value lv_userdata(lua, int_entry(3));
sol::lua_value lv_int_table(lua, { 1, 2, 3, 4, 5 });
REQUIRE(lv_int.is<int>());
REQUIRE(lv_double.is<double>());
REQUIRE(lv_string.is<std::string>());
REQUIRE(lv_lstring.is<std::string>());
REQUIRE(lv_bool.is<bool>());
REQUIRE(lv_nil.is<sol::lua_nil_t>());
REQUIRE(lv_userdata.is<sol::userdata>());
REQUIRE(lv_userdata.is<int_entry>());
REQUIRE(lv_int_table.is<sol::table>());
REQUIRE(lv_int.as<int>() == 1);
REQUIRE(lv_double.as<double>() == 2.0);
REQUIRE(lv_string.as<std::string>() == "heyo");
REQUIRE(lv_lstring.as<std::string>() == "hiyo");
REQUIRE(lv_lstring.as<std::wstring>() == L"hiyo");
REQUIRE(lv_bool.as<bool>());
REQUIRE(lv_nil.as<sol::lua_nil_t>() == sol::lua_nil);
REQUIRE(lv_userdata.as<int_entry>() == userdata_truth);
std::vector<int> int_table_value_lv = lv_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value_lv);
SECTION("type check (object)") {
sol::object obj_int(lv_int.value());
sol::object obj_double(lv_double.value());
sol::object obj_string(lv_string.value());
sol::object obj_lstring(lv_lstring.value());
sol::object obj_bool(lv_bool.value());
sol::object obj_nil(lv_nil.value());
sol::object obj_userdata(lv_userdata.value());
sol::object obj_int_table(lv_int_table.value());
REQUIRE(obj_int.is<int>());
REQUIRE(obj_double.is<double>());
REQUIRE(obj_string.is<std::string>());
REQUIRE(obj_lstring.is<std::string>());
REQUIRE(obj_bool.is<bool>());
REQUIRE(obj_nil.is<sol::lua_nil_t>());
REQUIRE(obj_userdata.is<sol::userdata>());
REQUIRE(obj_userdata.is<int_entry>());
REQUIRE(obj_int_table.is<sol::table>());
REQUIRE(obj_int.as<int>() == 1);
REQUIRE(obj_double.as<double>() == 2.0);
REQUIRE(obj_string.as<std::string>() == "heyo");
REQUIRE(obj_lstring.as<std::string>() == "hiyo");
REQUIRE(obj_lstring.as<std::wstring>() == L"hiyo");
REQUIRE(obj_bool.as<bool>());
REQUIRE(obj_userdata.as<int_entry>() == userdata_truth);
REQUIRE(obj_nil.as<sol::lua_nil_t>() == sol::lua_nil);
std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value);
}
SECTION("push/popping") {
lua["obj_int"] = lv_int;
lua["obj_double"] = lv_double;
lua["obj_string"] = lv_string;
lua["obj_lstring"] = lv_lstring;
lua["obj_bool"] = lv_bool;
lua["obj_nil"] = lv_nil;
lua["obj_userdata"] = lv_userdata;
lua["obj_int_table"] = lv_int_table;
// these all actually invoke the constructor
// so do one .get<> explicitly to ensure it's
// working correctl for a few cases...
// but it's nice to make sure it's all there now
sol::lua_value obj_int = lua["obj_int"].get<sol::lua_value>();
sol::lua_value obj_double = lua["obj_double"].get<sol::lua_value>();
sol::lua_value obj_string = lua["obj_string"].get<sol::lua_value>();
sol::lua_value obj_lstring = lua["obj_lstring"].get<sol::lua_value>();
sol::lua_value obj_bool = lua["obj_bool"].get<sol::lua_value>();
sol::lua_value obj_nil = lua["obj_nil"];
sol::lua_value obj_userdata = lua["obj_userdata"];
sol::lua_value obj_int_table = lua["obj_int_table"];
REQUIRE(obj_int.is<int>());
REQUIRE(obj_double.is<double>());
REQUIRE(obj_string.is<std::string>());
REQUIRE(obj_lstring.is<std::string>());
REQUIRE(obj_bool.is<bool>());
REQUIRE(obj_nil.is<sol::lua_nil_t>());
REQUIRE(obj_int_table.is<sol::table>());
REQUIRE(obj_int.as<int>() == 1);
REQUIRE(obj_double.as<double>() == 2.0);
REQUIRE(obj_string.as<std::string>() == "heyo");
REQUIRE(obj_lstring.as<std::string>() == "hiyo");
REQUIRE(obj_lstring.as<std::wstring>() == L"hiyo");
REQUIRE(obj_bool.as<bool>());
REQUIRE(obj_nil.as<sol::lua_nil_t>() == sol::lua_nil);
std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value);
}
SECTION("push/popping (object)") {
lua["obj_int"] = lv_int;
lua["obj_double"] = lv_double;
lua["obj_string"] = lv_string;
lua["obj_lstring"] = lv_lstring;
lua["obj_bool"] = lv_bool;
lua["obj_nil"] = lv_nil;
lua["obj_userdata"] = lv_userdata;
lua["obj_int_table"] = lv_int_table;
sol::object obj_int = lua["obj_int"];
sol::object obj_double = lua["obj_double"];
sol::object obj_string = lua["obj_string"];
sol::object obj_lstring = lua["obj_lstring"];
sol::object obj_bool = lua["obj_bool"];
sol::object obj_nil = lua["obj_nil"];
sol::object obj_userdata = lua["obj_userdata"];
sol::object obj_int_table = lua["obj_int_table"];
REQUIRE(obj_int.is<int>());
REQUIRE(obj_double.is<double>());
REQUIRE(obj_string.is<std::string>());
REQUIRE(obj_lstring.is<std::string>());
REQUIRE(obj_bool.is<bool>());
REQUIRE(obj_nil.is<sol::lua_nil_t>());
REQUIRE(obj_userdata.is<sol::userdata>());
REQUIRE(obj_userdata.is<int_entry>());
REQUIRE(obj_int_table.is<sol::table>());
REQUIRE(obj_int.as<int>() == 1);
REQUIRE(obj_double.as<double>() == 2.0);
REQUIRE(obj_string.as<std::string>() == "heyo");
REQUIRE(obj_lstring.as<std::string>() == "hiyo");
REQUIRE(obj_lstring.as<std::wstring>() == L"hiyo");
REQUIRE(obj_bool.as<bool>());
REQUIRE(obj_nil.as<sol::lua_nil_t>() == sol::lua_nil);
REQUIRE(obj_userdata.as<int_entry>() == userdata_truth);
std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value);
}
}
TEST_CASE("lua_value/threading", "test that thread_local in lua_value constructors do not race or clobber") {
REQUIRE_NOTHROW([]() {
std::thread thrds[24];
for (int i = 0; i < 24; i++) {
thrds[i] = std::thread(&lua_value_construct_race);
}
for (int i = 0; i < 24; i++) {
thrds[i].join();
}
}());
}

View File

@ -152,7 +152,7 @@ TEST_CASE("state/require_script", "opening strings as 'requires' clauses") {
std::string code = "return { modfunc = function () return 221 end }";
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::table thingy1 = lua.require_script("thingy", code);
sol::table thingy2 = lua.require_script("thingy", code);
@ -173,7 +173,7 @@ TEST_CASE("state/require", "require using a function") {
};
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
sol::table thingy1 = lua.require("thingy", open::open_func);
sol::table thingy2 = lua.require("thingy", open::open_func);
@ -344,7 +344,7 @@ return example;
};
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
lua.open_libraries();
lua.set_function("foo", foo);
@ -369,7 +369,7 @@ TEST_CASE("state/copy and move", "ensure state can be properly copied and moved"
TEST_CASE("state/requires-reload", "ensure that reloading semantics do not cause a crash") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
lua.open_libraries();
lua.safe_script("require 'io'\nreturn 'test1'");
lua.require_script("test2", "require 'io'\nreturn 'test2'");
@ -400,7 +400,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
SECTION("script") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
int ar = lua.safe_script(good);
int a = lua["a"];
REQUIRE(a == 21);
@ -409,7 +409,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("unsafe_script") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
int ar = lua.unsafe_script(good);
int a = lua["a"];
REQUIRE(a == 21);
@ -418,7 +418,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("script-handler") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbs = lua.safe_script(bad_syntax, sol::script_pass_on_error);
REQUIRE(!errbs.valid());
@ -435,7 +435,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("do_string") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbs = lua.do_string(bad_syntax);
REQUIRE(!errbs.valid());
@ -452,7 +452,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("load_string") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbsload = lua.load(bad_syntax);
REQUIRE(!errbsload.valid());
@ -475,7 +475,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("load") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
string_reader_load bssrl(bad_syntax);
void* vpbssrl = static_cast<void*>(&bssrl);
auto errbsload = lua.load(&string_reader, vpbssrl, bad_syntax);
@ -504,7 +504,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("load_string (text)") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbsload = lua.load(bad_syntax, bad_syntax, sol::load_mode::text);
REQUIRE(!errbsload.valid());
@ -527,7 +527,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("load (text)") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
string_reader_load bssrl(bad_syntax);
void* vpbssrl = static_cast<void*>(&bssrl);
auto errbsload = lua.load(&string_reader, vpbssrl, bad_syntax, sol::load_mode::text);
@ -556,7 +556,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("script_file") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
int ar = lua.safe_script_file(file_good);
int a = lua["a"];
REQUIRE(a == 21);
@ -565,7 +565,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("unsafe_script_file") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
int ar = lua.unsafe_script_file(file_good);
int a = lua["a"];
REQUIRE(a == 21);
@ -574,7 +574,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("script_file-handler") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbs = lua.safe_script_file(file_bad_syntax, sol::script_pass_on_error);
REQUIRE(!errbs.valid());
@ -591,7 +591,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("safe_script_file-handler") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbs = lua.safe_script_file(file_bad_syntax, sol::script_pass_on_error);
REQUIRE(!errbs.valid());
@ -608,7 +608,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("do_file") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbs = lua.do_file(file_bad_syntax);
REQUIRE(!errbs.valid());
@ -625,7 +625,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("load_file") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbsload = lua.load_file(file_bad_syntax);
REQUIRE(!errbsload.valid());
@ -648,7 +648,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
}
SECTION("load_file (text)") {
sol::state lua;
sol::stack_guard sg(lua);
sol::stack_guard luasg(lua);
auto errbsload = lua.load_file(file_bad_syntax, sol::load_mode::text);
REQUIRE(!errbsload.valid());

View File

@ -36,6 +36,8 @@ end
)";
sol::state lua;
sol::stack_guard luasg(lua);
{
auto r = lua.safe_script(code, sol::script_pass_on_error);
REQUIRE(r.valid());

View File

@ -41,6 +41,7 @@ namespace muh_namespace {
TEST_CASE("stack/strings", "test that strings can be roundtripped") {
sol::state lua;
sol::stack_guard luasg(lua);
static const char utf8str[] = "\xF0\x9F\x8D\x8C\x20\xE6\x99\xA5\x20\x46\x6F\x6F\x20\xC2\xA9\x20\x62\x61\x72\x20\xF0\x9D\x8C\x86\x20\x62\x61\x7A\x20\xE2\x98\x83\x20\x71\x75\x78";
static const char16_t utf16str[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 };

View File

@ -0,0 +1,51 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
struct not_a_table_at_all {};
TEST_CASE("tables/lua_table", "check that lua_table accepts only lua-style tables, and not other types") {
sol::state lua;
lua["f"] = [](sol::lua_table lt) {
int x = lt["a"];
REQUIRE(x == 3);
};
lua["ud"] = not_a_table_at_all{};
auto result0 = lua.safe_script("t = { a = 3 }", sol::script_pass_on_error);
REQUIRE(result0.valid());
auto result1 = lua.safe_script("f(t)", sol::script_pass_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script("f(ud)", sol::script_pass_on_error);
REQUIRE_FALSE(result2.valid());
auto result3 = lua.safe_script("f(24)", sol::script_pass_on_error);
REQUIRE_FALSE(result3.valid());
auto result4 = lua.safe_script("f(nil)", sol::script_pass_on_error);
REQUIRE_FALSE(result4.valid());
auto result5 = lua.safe_script("f('bark')", sol::script_pass_on_error);
REQUIRE_FALSE(result5.valid());
}

View File

@ -42,61 +42,9 @@ struct object {
}
};
int plop_xyz(int x, int y, std::string z) {
INFO(x << " " << y << " " << z);
return 11;
}
TEST_CASE("tables/as enums", "Making sure enums can be put in and gotten out as values") {
enum direction {
up,
down,
left,
right
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua["direction"] = lua.create_table_with(
"up", direction::up,
"down", direction::down,
"left", direction::left,
"right", direction::right);
sol::object obj = lua["direction"]["up"];
bool isdir = obj.is<direction>();
REQUIRE(isdir);
auto dir = obj.as<direction>();
REQUIRE(dir == direction::up);
}
TEST_CASE("tables/as enum classes", "Making sure enums can be put in and gotten out as values") {
enum class direction {
up,
down,
left,
right
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua["direction"] = lua.create_table_with(
"up", direction::up,
"down", direction::down,
"left", direction::left,
"right", direction::right);
sol::object obj = lua["direction"]["up"];
bool isdir = obj.is<direction>();
REQUIRE(isdir);
auto dir = obj.as<direction>();
REQUIRE(dir == direction::up);
}
TEST_CASE("tables/cleanup", "make sure tables leave the stack balanced") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries();
auto f = [] { return 5; };
@ -131,222 +79,6 @@ TEST_CASE("tables/nested cleanup", "make sure tables leave the stack balanced")
}
}
TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as values") {
enum class direction {
up,
down,
left,
right
};
SECTION("variadics") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_enum("direction",
"up", direction::up,
"down", direction::down,
"left", direction::left,
"right", direction::right);
direction d = lua["direction"]["left"];
REQUIRE(d == direction::left);
auto result = lua.safe_script("direction.left = 50", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
d = lua["direction"]["left"];
REQUIRE(d == direction::left);
}
SECTION("initializer_list") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_enum<direction>("direction", { { "up", direction::up }, { "down", direction::down }, { "left", direction::left }, { "right", direction::right } });
direction d = lua["direction"]["left"];
REQUIRE(d == direction::left);
auto result = lua.safe_script("direction.left = 50", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
d = lua["direction"]["left"];
REQUIRE(d == direction::left);
}
}
TEST_CASE("tables/for_each", "Testing the use of for_each to get values from a lua table") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script(
"arr = {\n"
"[0] = \"Hi\",\n"
"[1] = 123.45,\n"
"[2] = \"String value\",\n"
// Does nothing
//"[3] = nil,\n"
//"[nil] = 3,\n"
"[\"WOOF\"] = 123,\n"
"}");
sol::table tbl = lua["arr"];
std::size_t tablesize = 4;
std::size_t iterations = 0;
auto fx = [&iterations](sol::object key, sol::object value) {
++iterations;
sol::type keytype = key.get_type();
switch (keytype) {
case sol::type::number:
switch (key.as<int>()) {
case 0:
REQUIRE((value.as<std::string>() == "Hi"));
break;
case 1:
REQUIRE((value.as<double>() == 123.45));
break;
case 2:
REQUIRE((value.as<std::string>() == "String value"));
break;
case 3:
REQUIRE((value.is<sol::lua_nil_t>()));
break;
}
break;
case sol::type::string:
if (key.as<std::string>() == "WOOF") {
REQUIRE((value.as<double>() == 123));
}
break;
case sol::type::lua_nil:
REQUIRE((value.as<double>() == 3));
break;
default:
break;
}
};
auto fxpair = [&fx](std::pair<sol::object, sol::object> kvp) { fx(kvp.first, kvp.second); };
tbl.for_each(fx);
REQUIRE(iterations == tablesize);
iterations = 0;
tbl.for_each(fxpair);
REQUIRE(iterations == tablesize);
}
TEST_CASE("tables/for_each empty", "empty tables should not crash") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script("arr = {}");
sol::table tbl = lua["arr"];
REQUIRE(tbl.empty());
std::size_t tablesize = 0;
std::size_t iterations = 0;
auto fx = [&iterations](sol::object key, sol::object value) {
++iterations;
sol::type keytype = key.get_type();
switch (keytype) {
case sol::type::number:
switch (key.as<int>()) {
case 0:
REQUIRE((value.as<std::string>() == "Hi"));
break;
case 1:
REQUIRE((value.as<double>() == 123.45));
break;
case 2:
REQUIRE((value.as<std::string>() == "String value"));
break;
case 3:
REQUIRE((value.is<sol::lua_nil_t>()));
break;
}
break;
case sol::type::string:
if (key.as<std::string>() == "WOOF") {
REQUIRE((value.as<double>() == 123));
}
break;
case sol::type::lua_nil:
REQUIRE((value.as<double>() == 3));
break;
default:
break;
}
};
auto fxpair = [&fx](std::pair<sol::object, sol::object> kvp) { fx(kvp.first, kvp.second); };
tbl.for_each(fx);
REQUIRE(iterations == tablesize);
iterations = 0;
tbl.for_each(fxpair);
REQUIRE(iterations == tablesize);
iterations = 0;
for (const auto& kvp : tbl) {
fxpair(kvp);
++iterations;
}
REQUIRE(iterations == tablesize);
}
TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a lua table") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script(
"arr = {\n"
"[0] = \"Hi\",\n"
"[1] = 123.45,\n"
"[2] = \"String value\",\n"
// Does nothing
//"[3] = nil,\n"
//"[nil] = 3,\n"
"[\"WOOF\"] = 123,\n"
"}");
sol::table tbl = lua["arr"];
std::size_t tablesize = 4;
std::size_t iterations = 0;
int begintop = 0;
int endtop = 0;
{
test_stack_guard s(lua.lua_state(), begintop, endtop);
for (auto& kvp : tbl) {
[&iterations](sol::object key, sol::object value) {
++iterations;
sol::type keytype = key.get_type();
switch (keytype) {
case sol::type::number:
switch (key.as<int>()) {
case 0:
REQUIRE((value.as<std::string>() == "Hi"));
break;
case 1:
REQUIRE((value.as<double>() == 123.45));
break;
case 2:
REQUIRE((value.as<std::string>() == "String value"));
break;
case 3:
REQUIRE((value.is<sol::lua_nil_t>()));
break;
}
break;
case sol::type::string:
if (key.as<std::string>() == "WOOF") {
REQUIRE((value.as<double>() == 123));
}
break;
case sol::type::lua_nil:
REQUIRE((value.as<double>() == 3));
break;
default:
break;
}
}(kvp.first, kvp.second);
}
}
REQUIRE(begintop == endtop);
REQUIRE(iterations == tablesize);
}
TEST_CASE("tables/variables", "Check if tables and variables work as intended") {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::os);
@ -450,127 +182,6 @@ TEST_CASE("tables/function variables", "Check if tables and function calls work
REQUIRE_NOTHROW(run_script(lua));
}
TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script("foo = 20\nbar = \"hello world\"");
// basic retrieval
std::string bar = lua["bar"];
int foo = lua["foo"];
REQUIRE(bar == "hello world");
REQUIRE(foo == 20);
// test operator= for stringification
// errors due to ambiguous operators
bar = lua["bar"];
// basic setting
lua["bar"] = 20.4;
lua["foo"] = "goodbye";
// doesn't modify the actual values obviously.
REQUIRE(bar == "hello world");
REQUIRE(foo == 20);
// function setting
lua["test"] = plop_xyz;
{
auto result = lua.safe_script("assert(test(10, 11, \"hello\") == 11)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
// function retrieval
sol::function test = lua["test"];
REQUIRE(test.call<int>(10, 11, "hello") == 11);
// setting a lambda
lua["lamb"] = [](int x) {
return x * 2;
};
{
auto result = lua.safe_script("assert(lamb(220) == 440)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
// function retrieval of a lambda
sol::function lamb = lua["lamb"];
REQUIRE(lamb.call<int>(220) == 440);
// test const table retrieval
auto assert1 = [](const sol::table& t) {
std::string a = t["foo"];
double b = t["bar"];
REQUIRE(a == "goodbye");
REQUIRE(b == 20.4);
};
REQUIRE_NOTHROW(assert1(lua.globals()));
}
TEST_CASE("tables/operator[] valid", "Test if proxies on tables can lazily evaluate validity") {
sol::state lua;
bool isFullScreen = false;
auto fullscreennopers = lua["fullscreen"]["nopers"];
auto fullscreen = lua["fullscreen"];
REQUIRE_FALSE(fullscreennopers.valid());
REQUIRE_FALSE(fullscreen.valid());
lua["fullscreen"] = true;
REQUIRE_FALSE(fullscreennopers.valid());
REQUIRE(fullscreen.valid());
isFullScreen = lua["fullscreen"];
REQUIRE(isFullScreen);
lua["fullscreen"] = false;
REQUIRE_FALSE(fullscreennopers.valid());
REQUIRE(fullscreen.valid());
isFullScreen = lua["fullscreen"];
REQUIRE_FALSE(isFullScreen);
}
TEST_CASE("tables/operator[] optional", "Test if proxies on tables can lazily evaluate validity") {
sol::state lua;
sol::optional<int> test1 = lua["no_exist_yet"];
bool present = (bool)test1;
REQUIRE_FALSE(present);
lua["no_exist_yet"] = 262;
sol::optional<int> test2 = lua["no_exist_yet"];
present = (bool)test2;
REQUIRE(present);
REQUIRE(test2.value() == 262);
sol::optional<int> nope = lua["nope"]["kek"]["hah"];
auto nope2 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah"));
present = (bool)nope;
REQUIRE_FALSE(present);
present = (bool)nope2;
REQUIRE_FALSE(present);
lua.create_named_table("nope", "kek", lua.create_table_with("hah", 1));
sol::optional<int> non_nope = lua["nope"]["kek"]["hah"].get<sol::optional<int>>();
sol::optional<int> non_nope2 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah"));
present = (bool)non_nope;
REQUIRE(present);
present = (bool)non_nope2;
REQUIRE(present);
REQUIRE(non_nope.value() == 1);
REQUIRE(non_nope2.value() == 1);
INFO("Keys: nope, kek, hah");
lua.set(std::make_tuple("nope", "kek", "hah"), 35);
sol::optional<int> non_nope3 = lua["nope"]["kek"]["hah"].get<sol::optional<int>>();
sol::optional<int> non_nope4 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah"));
present = (bool)non_nope3;
REQUIRE(present);
present = (bool)non_nope4;
REQUIRE(present);
REQUIRE(non_nope3.value() == 35);
REQUIRE(non_nope4.value() == 35);
}
TEST_CASE("tables/add", "Basic test to make sure the 'add' feature works") {
static const int sz = 120;

View File

@ -0,0 +1,90 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
enum weak_direction { up, down, left, right };
enum class strong_direction { up, down, left, right };
TEST_CASE("tables/as enums", "Making sure enums can be put in and gotten out as values") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua["strong_direction"]
= lua.create_table_with("up", weak_direction::up, "down", weak_direction::down, "left", weak_direction::left, "right", weak_direction::right);
sol::object obj = lua["strong_direction"]["up"];
bool isdir = obj.is<weak_direction>();
REQUIRE(isdir);
auto dir = obj.as<weak_direction>();
REQUIRE(dir == weak_direction::up);
}
TEST_CASE("tables/as enum classes", "Making sure enums can be put in and gotten out as values") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua["strong_direction"]
= lua.create_table_with("up", strong_direction::up, "down", strong_direction::down, "left", strong_direction::left, "right", strong_direction::right);
sol::object obj = lua["strong_direction"]["up"];
bool isdir = obj.is<strong_direction>();
REQUIRE(isdir);
auto dir = obj.as<strong_direction>();
REQUIRE(dir == strong_direction::up);
}
TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as values") {
enum class strong_direction { up, down, left, right };
SECTION("variadics") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_enum("strong_direction", "up", strong_direction::up, "down", strong_direction::down, "left", strong_direction::left, "right", strong_direction::right);
strong_direction d = lua["strong_direction"]["left"];
REQUIRE(d == strong_direction::left);
auto result = lua.safe_script("strong_direction.left = 50", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
d = lua["strong_direction"]["left"];
REQUIRE(d == strong_direction::left);
}
SECTION("initializer_list") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_enum<strong_direction>(
"strong_direction", { { "up", strong_direction::up }, { "down", strong_direction::down }, { "left", strong_direction::left }, { "right", strong_direction::right } });
strong_direction d = lua["strong_direction"]["left"];
REQUIRE(d == strong_direction::left);
auto result = lua.safe_script("strong_direction.left = 50", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
d = lua["strong_direction"]["left"];
REQUIRE(d == strong_direction::left);
}
}

View File

@ -0,0 +1,151 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
int plop_xyz(int x, int y, std::string z) {
INFO(x << " " << y << " " << z);
return 11;
}
TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script("foo = 20\nbar = \"hello world\"");
// basic retrieval
std::string bar = lua["bar"];
int foo = lua["foo"];
REQUIRE(bar == "hello world");
REQUIRE(foo == 20);
// test operator= for stringification
// errors due to ambiguous operators
bar = lua["bar"];
// basic setting
lua["bar"] = 20.4;
lua["foo"] = "goodbye";
// doesn't modify the actual values obviously.
REQUIRE(bar == "hello world");
REQUIRE(foo == 20);
// function setting
lua["test"] = plop_xyz;
{
auto result = lua.safe_script("assert(test(10, 11, \"hello\") == 11)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
// function retrieval
sol::function test = lua["test"];
REQUIRE(test.call<int>(10, 11, "hello") == 11);
// setting a lambda
lua["lamb"] = [](int x) { return x * 2; };
{
auto result = lua.safe_script("assert(lamb(220) == 440)", sol::script_pass_on_error);
REQUIRE(result.valid());
}
// function retrieval of a lambda
sol::function lamb = lua["lamb"];
REQUIRE(lamb.call<int>(220) == 440);
// test const table retrieval
auto assert1 = [](const sol::table& t) {
std::string a = t["foo"];
double b = t["bar"];
REQUIRE(a == "goodbye");
REQUIRE(b == 20.4);
};
REQUIRE_NOTHROW(assert1(lua.globals()));
}
TEST_CASE("tables/operator[] valid", "Test if proxies on tables can lazily evaluate validity") {
sol::state lua;
bool isFullScreen = false;
auto fullscreennopers = lua["fullscreen"]["nopers"];
auto fullscreen = lua["fullscreen"];
REQUIRE_FALSE(fullscreennopers.valid());
REQUIRE_FALSE(fullscreen.valid());
lua["fullscreen"] = true;
REQUIRE_FALSE(fullscreennopers.valid());
REQUIRE(fullscreen.valid());
isFullScreen = lua["fullscreen"];
REQUIRE(isFullScreen);
lua["fullscreen"] = false;
REQUIRE_FALSE(fullscreennopers.valid());
REQUIRE(fullscreen.valid());
isFullScreen = lua["fullscreen"];
REQUIRE_FALSE(isFullScreen);
}
TEST_CASE("tables/operator[] optional", "Test if proxies on tables can lazily evaluate validity") {
sol::state lua;
sol::optional<int> test1 = lua["no_exist_yet"];
bool present = (bool)test1;
REQUIRE_FALSE(present);
lua["no_exist_yet"] = 262;
sol::optional<int> test2 = lua["no_exist_yet"];
present = (bool)test2;
REQUIRE(present);
REQUIRE(test2.value() == 262);
sol::optional<int> nope = lua["nope"]["kek"]["hah"];
auto nope2 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah"));
present = (bool)nope;
REQUIRE_FALSE(present);
present = (bool)nope2;
REQUIRE_FALSE(present);
lua.create_named_table("nope", "kek", lua.create_table_with("hah", 1));
sol::optional<int> non_nope = lua["nope"]["kek"]["hah"].get<sol::optional<int>>();
sol::optional<int> non_nope2 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah"));
present = (bool)non_nope;
REQUIRE(present);
present = (bool)non_nope2;
REQUIRE(present);
REQUIRE(non_nope.value() == 1);
REQUIRE(non_nope2.value() == 1);
INFO("Keys: nope, kek, hah");
lua.set(std::make_tuple("nope", "kek", "hah"), 35);
sol::optional<int> non_nope3 = lua["nope"]["kek"]["hah"].get<sol::optional<int>>();
sol::optional<int> non_nope4 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah"));
present = (bool)non_nope3;
REQUIRE(present);
present = (bool)non_nope4;
REQUIRE(present);
REQUIRE(non_nope3.value() == 35);
REQUIRE(non_nope4.value() == 35);
}

View File

@ -29,6 +29,7 @@
TEST_CASE("tables/proxy override_value", "allow override_value by way of key") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base, sol::lib::io);
sol::optional<int> not_there = lua["a"]["b"]["c"];
@ -42,6 +43,7 @@ TEST_CASE("tables/proxy override_value", "allow override_value by way of key") {
TEST_CASE("tables/insertion override", "allow override all non-table values plus final value") {
SECTION("traverse") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::optional<int> not_there = lua["a"]["b"]["c"];
REQUIRE_FALSE(static_cast<bool>(not_there));
@ -59,6 +61,7 @@ TEST_CASE("tables/insertion override", "allow override all non-table values plus
}
SECTION("proxy") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::optional<int> not_there = lua["a"]["b"]["c"];
REQUIRE_FALSE(static_cast<bool>(not_there));
@ -76,6 +79,7 @@ TEST_CASE("tables/insertion override", "allow override all non-table values plus
}
SECTION("complex proxy") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::optional<int> not_there = lua["a"]["b"]["c"];
REQUIRE_FALSE(static_cast<bool>(not_there));
@ -91,6 +95,7 @@ TEST_CASE("tables/insertion override", "allow override all non-table values plus
TEST_CASE("tables/insertion update_if_empty", "allow updating a value only if it's missing") {
SECTION("traverse") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::optional<int> not_there = lua["a"]["b"]["c"];
REQUIRE_FALSE(static_cast<bool>(not_there));
@ -101,6 +106,7 @@ TEST_CASE("tables/insertion update_if_empty", "allow updating a value only if it
}
SECTION("proxy") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::optional<int> not_there = lua["a"]["b"]["c"];
REQUIRE_FALSE(static_cast<bool>(not_there));
@ -116,6 +122,7 @@ TEST_CASE("tables/insertion update_if_empty", "allow updating a value only if it
}
SECTION("proxy invoker") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::optional<int> not_there = lua["a"]["b"]["c"];
REQUIRE_FALSE(static_cast<bool>(not_there));

View File

@ -0,0 +1,202 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_test.hpp"
#include <catch.hpp>
TEST_CASE("tables/for_each", "Testing the use of for_each to get values from a lua table") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script(
"arr = {\n"
"[0] = \"Hi\",\n"
"[1] = 123.45,\n"
"[2] = \"String value\",\n"
// Does nothing
//"[3] = nil,\n"
//"[nil] = 3,\n"
"[\"WOOF\"] = 123,\n"
"}");
sol::table tbl = lua["arr"];
std::size_t tablesize = 4;
std::size_t iterations = 0;
auto fx = [&iterations](sol::object key, sol::object value) {
++iterations;
sol::type keytype = key.get_type();
switch (keytype) {
case sol::type::number:
switch (key.as<int>()) {
case 0:
REQUIRE((value.as<std::string>() == "Hi"));
break;
case 1:
REQUIRE((value.as<double>() == 123.45));
break;
case 2:
REQUIRE((value.as<std::string>() == "String value"));
break;
case 3:
REQUIRE((value.is<sol::lua_nil_t>()));
break;
}
break;
case sol::type::string:
if (key.as<std::string>() == "WOOF") {
REQUIRE((value.as<double>() == 123));
}
break;
case sol::type::lua_nil:
REQUIRE((value.as<double>() == 3));
break;
default:
break;
}
};
auto fxpair = [&fx](std::pair<sol::object, sol::object> kvp) { fx(kvp.first, kvp.second); };
tbl.for_each(fx);
REQUIRE(iterations == tablesize);
iterations = 0;
tbl.for_each(fxpair);
REQUIRE(iterations == tablesize);
}
TEST_CASE("tables/for_each empty", "empty tables should not crash") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script("arr = {}");
sol::table tbl = lua["arr"];
REQUIRE(tbl.empty());
std::size_t tablesize = 0;
std::size_t iterations = 0;
auto fx = [&iterations](sol::object key, sol::object value) {
++iterations;
sol::type keytype = key.get_type();
switch (keytype) {
case sol::type::number:
switch (key.as<int>()) {
case 0:
REQUIRE((value.as<std::string>() == "Hi"));
break;
case 1:
REQUIRE((value.as<double>() == 123.45));
break;
case 2:
REQUIRE((value.as<std::string>() == "String value"));
break;
case 3:
REQUIRE((value.is<sol::lua_nil_t>()));
break;
}
break;
case sol::type::string:
if (key.as<std::string>() == "WOOF") {
REQUIRE((value.as<double>() == 123));
}
break;
case sol::type::lua_nil:
REQUIRE((value.as<double>() == 3));
break;
default:
break;
}
};
auto fxpair = [&fx](std::pair<sol::object, sol::object> kvp) { fx(kvp.first, kvp.second); };
tbl.for_each(fx);
REQUIRE(iterations == tablesize);
iterations = 0;
tbl.for_each(fxpair);
REQUIRE(iterations == tablesize);
iterations = 0;
for (const auto& kvp : tbl) {
fxpair(kvp);
++iterations;
}
REQUIRE(iterations == tablesize);
}
TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a lua table") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.safe_script(
"arr = {\n"
"[0] = \"Hi\",\n"
"[1] = 123.45,\n"
"[2] = \"String value\",\n"
// Does nothing
//"[3] = nil,\n"
//"[nil] = 3,\n"
"[\"WOOF\"] = 123,\n"
"}");
sol::table tbl = lua["arr"];
std::size_t tablesize = 4;
std::size_t iterations = 0;
int begintop = 0;
int endtop = 0;
{
test_stack_guard s(lua.lua_state(), begintop, endtop);
for (auto& kvp : tbl) {
[&iterations](sol::object key, sol::object value) {
++iterations;
sol::type keytype = key.get_type();
switch (keytype) {
case sol::type::number:
switch (key.as<int>()) {
case 0:
REQUIRE((value.as<std::string>() == "Hi"));
break;
case 1:
REQUIRE((value.as<double>() == 123.45));
break;
case 2:
REQUIRE((value.as<std::string>() == "String value"));
break;
case 3:
REQUIRE((value.is<sol::lua_nil_t>()));
break;
}
break;
case sol::type::string:
if (key.as<std::string>() == "WOOF") {
REQUIRE((value.as<double>() == 123));
}
break;
case sol::type::lua_nil:
REQUIRE((value.as<double>() == 3));
break;
default:
break;
}
}(kvp.first, kvp.second);
}
}
REQUIRE(begintop == endtop);
REQUIRE(iterations == tablesize);
}

View File

@ -30,6 +30,7 @@
TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
sol::state lua;
sol::stack_guard luasg(lua);
sol::usertype<fuser> lc = lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
@ -56,6 +57,7 @@ TEST_CASE("usertype/usertype", "Show that we can create classes from usertype an
TEST_CASE("usertype/usertype fundamentals", "Verify new_usertype registers basic member functions and a constructor") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);

View File

@ -54,6 +54,7 @@ struct self_test {
TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<self_test>("test", "g", &self_test::g, "f", &self_test::f);
@ -68,6 +69,7 @@ TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<giver>("giver",
@ -97,6 +99,8 @@ TEST_CASE("usertype/nonmember-functions", "let users set non-member functions th
TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);
lua.new_usertype<abstract_B>("B", sol::base_classes, sol::bases<abstract_A>());
REQUIRE_NOTHROW([&]() {
@ -114,7 +118,9 @@ TEST_CASE("usertype/as_function", "Ensure that variables can be turned into func
};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries();
lua.new_usertype<B>("B", "b", &B::bvar, "f", sol::as_function(&B::bvar));
B b;
@ -137,6 +143,7 @@ TEST_CASE("usertype/call-initializers", "Ensure call constructors with initializ
};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries();
lua.new_usertype<A>("A",
@ -153,6 +160,7 @@ TEST_CASE("usertype/missing-key", "make sure a missing key returns nil") {
struct thing {};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing");
@ -169,6 +177,7 @@ TEST_CASE("usertype/basic type information", "check that we can query some basic
struct my_thing {};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<my_thing>("my_thing");
@ -210,9 +219,8 @@ TEST_CASE("usertype/noexcept-methods", "make sure noexcept functions and methods
};
sol::state lua;
lua.new_usertype<T>("T",
"nf", &T::noexcept_function,
"nm", &T::noexcept_method);
sol::stack_guard luasg(lua);
lua.new_usertype<T>("T", "nf", &T::noexcept_function, "nm", &T::noexcept_method);
lua.safe_script("t = T.new()");
lua.safe_script("v1 = t.nf()");

View File

@ -30,6 +30,7 @@
TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<float, float, float>> ctor;
sol::usertype<Vec> udata
@ -57,7 +58,6 @@ TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as
sol::function f;
};
lua.open_libraries(sol::lib::base);
lua.set("b", breaks());
lua.new_usertype<breaks>("breaks", "f", &breaks::f);
@ -90,6 +90,8 @@ TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles prop
};
sol::state lua;
sol::stack_guard luasg(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);

View File

@ -40,6 +40,7 @@ struct overloading_test {
TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<woof>("woof", "var", &woof::var, "func", sol::overload(&woof::func, &woof::func2, &woof::func2s));
@ -61,6 +62,7 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.new_usertype<overloading_test>("overloading_test",
sol::constructors<>(),
"print",

View File

@ -105,7 +105,9 @@ TEST_CASE("usertype/properties", "Check if member properties/variables work") {
};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<bark>("bark",
"var",
&bark::var,
@ -172,6 +174,8 @@ TEST_CASE("usertype/copyability", "make sure user can write to a class variable
};
sol::state lua;
sol::stack_guard luasg(lua);
lua.new_usertype<NoCopy>("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set));
REQUIRE_NOTHROW(lua.safe_script(R"__(
@ -217,6 +221,7 @@ TEST_CASE("usertype/static-properties", "allow for static functions to get and s
test_t manager;
sol::state lua;
sol::stack_guard luasg(lua);
lua.new_usertype<test_t>(
"test", "f", std::function<std::size_t()>(std::bind(std::mem_fn(&test_t::func), &manager)), "g", sol::property(&test_t::s_func, &test_t::g_func));
@ -241,6 +246,7 @@ TEST_CASE("usertype/var-and-property", "make sure const vars are readonly and pr
};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries();
lua.new_usertype<test>(
@ -394,6 +400,8 @@ TEST_CASE("usertype/alignment", "ensure that alignment does not trigger weird al
struct aligned_derived : aligned_base {};
sol::state lua;
sol::stack_guard luasg(lua);
auto f = [](aligned_base&, float d) { REQUIRE(d == 5.0f); };
lua.new_usertype<aligned_base>("Base", "x", sol::writeonly_property(weird_aligned_wrapper<aligned_base>(std::ref(f))));
lua.new_usertype<aligned_derived>("Derived", sol::base_classes, sol::bases<aligned_base>());

View File

@ -29,10 +29,10 @@
#include <mutex>
#include <thread>
#ifdef SOL_CXX17_FEATURES
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
#include <string_view>
#include <variant>
#endif
#endif // C++17
std::mutex basic_init_require_mutex;
@ -109,6 +109,7 @@ TEST_CASE("utility/variant", "test that variant can be round-tripped") {
TEST_CASE("utility/optional-conversion", "test that regular optional will properly catch certain types") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.new_usertype<vars>("vars");
@ -129,6 +130,7 @@ TEST_CASE("utility/std optional", "test that shit optional can be round-tripped"
#ifdef SOL_CXX17_FEATURES
SECTION("okay") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.set_function("f", [](int v) {
@ -149,6 +151,7 @@ TEST_CASE("utility/std optional", "test that shit optional can be round-tripped"
}
SECTION("throws") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.set_function("f", [](int v) {
@ -169,6 +172,8 @@ TEST_CASE("utility/std optional", "test that shit optional can be round-tripped"
}
SECTION("in classes") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
struct opt_c {
@ -194,6 +199,7 @@ TEST_CASE("utility/std optional", "test that shit optional can be round-tripped"
TEST_CASE("utility/string_view", "test that string_view can be taken as an argument") {
#ifdef SOL_CXX17_FEATURES
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.set_function("f", [](std::string_view v) {
@ -224,6 +230,8 @@ TEST_CASE("utility/thread", "fire up lots of threads at the same time to make su
TEST_CASE("utility/pointer", "check we can get pointer value from references") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.set_function("f", [](bool aorb, sol::reference a, sol::stack_reference b) {
if (aorb) {
return a.pointer();
@ -259,6 +267,8 @@ TEST_CASE("utility/this_state", "Ensure this_state argument can be gotten anywhe
};
sol::state lua;
sol::stack_guard luasg(lua);
INFO("created lua state");
lua.open_libraries(sol::lib::base);
lua.new_usertype<bark>("bark",
@ -290,6 +300,7 @@ TEST_CASE("utility/this_state", "Ensure this_state argument can be gotten anywhe
TEST_CASE("safety/check_stack", "check to make sure that if we overflow the stack in safety mode, we get the appropriate error thrown") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua["okay"] = []() {

View File

@ -37,7 +37,9 @@ TEST_CASE("variadics/variadic_args", "Check to see we can receive multiple argum
};
sol::state lua;
sol::stack_guard luasg(lua);
lua.open_libraries(sol::lib::base);
lua.set_function("v", [](sol::this_state, sol::variadic_args va) -> structure {
int r = 0;
for (auto v : va) {
@ -83,6 +85,7 @@ TEST_CASE("variadics/required with variadic_args", "Check if a certain number of
TEST_CASE("variadics/variadic_args get type", "Make sure we can inspect types proper from variadic_args") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.set_function("f", [](sol::variadic_args va) {
sol::type types[] = {
@ -108,6 +111,7 @@ TEST_CASE("variadics/variadic_args get type", "Make sure we can inspect types pr
TEST_CASE("variadics/variadic_results", "returning a variable amount of arguments from C++") {
SECTION("as_returns - containers") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.set_function("f", []() {
std::set<std::string> results{ "arf", "bark", "woof" };
@ -139,17 +143,17 @@ TEST_CASE("variadics/variadic_results", "returning a variable amount of argument
}
SECTION("variadic_results - variadic_args") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.set_function("f", [](sol::variadic_args args) {
return sol::variadic_results(args.cbegin(), args.cend());
});
REQUIRE_NOTHROW([&]() {
lua.safe_script(R"(
v1, v2, v3 = f(1, 'bark', true)
v4, v5 = f(25, 82)
)");
}());
auto result1 = lua.safe_script(R"(
v1, v2, v3 = f(1, 'bark', true)
v4, v5 = f(25, 82)
)", sol::script_pass_on_error);
REQUIRE(result1.valid());
int v1 = lua["v1"];
std::string v2 = lua["v2"];
@ -165,6 +169,7 @@ TEST_CASE("variadics/variadic_results", "returning a variable amount of argument
}
SECTION("variadic_results") {
sol::state lua;
sol::stack_guard luasg(lua);
lua.set_function("f", [](sol::this_state ts, bool maybe) {
if (maybe) {
@ -184,12 +189,11 @@ TEST_CASE("variadics/variadic_results", "returning a variable amount of argument
}
});
REQUIRE_NOTHROW([&]() {
lua.safe_script(R"(
v1, v2, v3 = f(true)
v4, v5, v6, v7 = f(false)
)");
}());
auto result1 = lua.safe_script(R"(
v1, v2, v3 = f(true)
v4, v5, v6, v7 = f(false)
)", sol::script_pass_on_error);
REQUIRE(result1.valid());
int v1 = lua["v1"];
int v2 = lua["v2"];
@ -232,13 +236,15 @@ TEST_CASE("variadics/fallback_constructor", "ensure constructor matching behaves
}
return res; }));
REQUIRE_NOTHROW([&]() {
lua.safe_script("v0 = vec2x();");
lua.safe_script("v1 = vec2x(1);");
lua.safe_script("v2 = vec2x(1, 2);");
lua.safe_script("v3 = vec2x(v2)");
}());
auto result1 = lua.safe_script("v0 = vec2x();", sol::script_pass_on_error);
auto result2 = lua.safe_script("v1 = vec2x(1);", sol::script_pass_on_error);
auto result3 = lua.safe_script("v2 = vec2x(1, 2);", sol::script_pass_on_error);
auto result4 = lua.safe_script("v3 = vec2x(v2)", sol::script_pass_on_error);
REQUIRE(result1.valid());
REQUIRE(result2.valid());
REQUIRE(result3.valid());
REQUIRE(result4.valid());
vec2x& v0 = lua["v0"];
vec2x& v1 = lua["v1"];
vec2x& v2 = lua["v2"];