mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Fix up the API; prepare for release.
This commit is contained in:
parent
5d722af1b0
commit
1a9c7484b1
|
@ -39,6 +39,7 @@ cxx = os.environ.get('CXX', "g++")
|
|||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--debug', action='store_true', help='compile with debug flags')
|
||||
parser.add_argument('--cxx', metavar='<compiler>', help='compiler name to use (default: env.CXX=%s)' % cxx, default=cxx)
|
||||
parser.add_argument('--cxx-flags', help='additional flags passed to the compiler', default='')
|
||||
parser.add_argument('--ci', action='store_true', help=argparse.SUPPRESS)
|
||||
parser.add_argument('--testing', action='store_true', help=argparse.SUPPRESS)
|
||||
parser.add_argument('--lua-lib', help='lua library name (without the lib on *nix).', default='lua')
|
||||
|
@ -55,6 +56,7 @@ args = parser.parse_args()
|
|||
include = [ '.', './include' ]
|
||||
depends = [os.path.join('Catch', 'include')]
|
||||
cxxflags = [ '-Wall', '-Wextra', '-pedantic', '-pedantic-errors', '-std=c++14' ]
|
||||
cxxflags.extend([p for p in re.split("( |\\\".*?\\\"|'.*?')", args.cxx_flags) if p.strip()])
|
||||
ldflags = []
|
||||
script_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
sol_dir = os.path.join(script_dir, 'sol')
|
||||
|
|
1
sol.hpp
1
sol.hpp
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "sol/state.hpp"
|
||||
#include "sol/object.hpp"
|
||||
#include "sol/userdata.hpp"
|
||||
#include "sol/function.hpp"
|
||||
#include "sol/coroutine.hpp"
|
||||
|
||||
|
|
|
@ -71,26 +71,26 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
coroutine(lua_State* L, int index = -1) : reference(L, index) {}
|
||||
coroutine() = default;
|
||||
coroutine(const coroutine&) = default;
|
||||
coroutine& operator=(const coroutine&) = default;
|
||||
coroutine(lua_State* L, int index = -1) noexcept : reference(L, index) {}
|
||||
coroutine() noexcept = default;
|
||||
coroutine(const coroutine&) noexcept = default;
|
||||
coroutine& operator=(const coroutine&) noexcept = default;
|
||||
|
||||
call_status status() const {
|
||||
call_status status() const noexcept {
|
||||
return stats;
|
||||
}
|
||||
|
||||
bool error() const {
|
||||
bool error() const noexcept {
|
||||
call_status cs = status();
|
||||
return cs != call_status::ok && cs != call_status::yielded;
|
||||
}
|
||||
|
||||
bool runnable () const {
|
||||
bool runnable () const noexcept {
|
||||
return valid()
|
||||
&& (status() == call_status::yielded);
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
explicit operator bool() const noexcept {
|
||||
return runnable();
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call( Args&&... args ) {
|
||||
push();
|
||||
int pushcount = stack::push_args( lua_state(), std::forward<Args>( args )... );
|
||||
int pushcount = stack::multi_push( lua_state(), std::forward<Args>( args )... );
|
||||
return invoke( types<Ret...>( ), std::index_sequence_for<Ret...>(), pushcount );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
namespace sol {
|
||||
namespace detail {
|
||||
#ifndef SOL_NO_RTTI
|
||||
#ifdef _MSC_VER
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
return id.name();
|
||||
|
@ -49,9 +50,66 @@ inline std::string get_type_name(const std::type_info& id) {
|
|||
#else
|
||||
#error Compiler not supported for demangling
|
||||
#endif // compilers
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
template <typename T>
|
||||
inline std::string get_type_name() {
|
||||
std::string name = __FUNCSIG__;
|
||||
std::size_t start = name.find_last_of('<');
|
||||
std::size_t end = name.find_last_of('>');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
name = name.substr(start, end - start);
|
||||
return name;
|
||||
}
|
||||
|
||||
inline std::string demangle(const std::type_info& id) {
|
||||
std::string realname = get_type_name(id);
|
||||
#elif defined(__GNUC__)
|
||||
template <typename T>
|
||||
inline std::string get_type_name() {
|
||||
std::string name = __PRETTY_FUNCTION__;
|
||||
std::size_t start = name.find_first_of('=');
|
||||
std::size_t end = name.find_last_of(';');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
if (start < name.size() - 1)
|
||||
start += 2;
|
||||
name = name.substr(start, end - start);
|
||||
return name;
|
||||
}
|
||||
#elif defined(__clang__)
|
||||
template <typename T>
|
||||
inline std::string get_type_name() {
|
||||
std::string name = __PRETTY_FUNCTION__;
|
||||
std::size_t start = name.find_last_of('[');
|
||||
start = name.find_first_of('=', start);
|
||||
std::size_t end = name.find_last_of(']');
|
||||
if (end == std::string::npos)
|
||||
end = name.size();
|
||||
if (start == std::string::npos)
|
||||
start = 0;
|
||||
if (start < name.size() - 1)
|
||||
start += 1;
|
||||
name = name.substr(start, end - start);
|
||||
return name;
|
||||
}
|
||||
#else
|
||||
#error Compiler not supported for demangling
|
||||
#endif // compilers
|
||||
#endif // No Runtime Type information
|
||||
|
||||
template <typename T>
|
||||
inline std::string demangle() {
|
||||
#ifndef SOL_NO_RTTI
|
||||
std::string realname = get_type_name(typeid(T));
|
||||
#else
|
||||
std::string realname = get_type_name<T>();
|
||||
#endif // No Runtime Type Information
|
||||
const static std::array<std::string, 2> removals = {{ "struct ", "class " }};
|
||||
const static std::array<std::string, 2> replacements = {{ "::", "_" }};
|
||||
for(std::size_t r = 0; r < removals.size(); ++r) {
|
||||
|
|
|
@ -92,7 +92,7 @@ public:
|
|||
template<typename... Ret, typename... Args>
|
||||
decltype(auto) call( Args&&... args ) const {
|
||||
push( );
|
||||
int pushcount = stack::push_args( lua_state( ), std::forward<Args>( args )... );
|
||||
int pushcount = stack::multi_push( lua_state( ), std::forward<Args>( args )... );
|
||||
return invoke( types<Ret...>( ), std::index_sequence_for<Ret...>(), pushcount );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -41,10 +41,10 @@ struct constructor_match {
|
|||
|
||||
constructor_match(T* obj) : obj(obj) {}
|
||||
|
||||
template <bool b, typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(meta::Bool<b>, types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int operator()(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const {
|
||||
default_construct func{};
|
||||
return stack::call_into_lua<b ? false : stack::stack_detail::default_check_arguments>(r, a, func, L, start, obj);
|
||||
return stack::call_into_lua<false>(r, a, func, L, start, obj);
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
@ -86,11 +86,7 @@ inline int construct(lua_State* L) {
|
|||
|
||||
template <typename T>
|
||||
inline int destruct(lua_State* L) {
|
||||
userdata udata = stack::get<userdata>(L, 1);
|
||||
// The first sizeof(T*) bytes are the reference: the rest is
|
||||
// the actual data itself (if there is a reference at all)
|
||||
T** pobj = reinterpret_cast<T**>(udata.value);
|
||||
T*& obj = *pobj;
|
||||
T* obj = stack::get<non_null<T*>>(L, 1);
|
||||
std::allocator<T> alloc{};
|
||||
alloc.destroy(obj);
|
||||
return 0;
|
||||
|
@ -109,8 +105,8 @@ struct usertype_constructor_function : base_function {
|
|||
|
||||
usertype_constructor_function(Functions... fxs) : overloads(fxs...) {}
|
||||
|
||||
template <bool b, typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(meta::Bool<b>, types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
T*& referencepointer = *pointerpointer;
|
||||
|
@ -120,7 +116,7 @@ struct usertype_constructor_function : base_function {
|
|||
userdataref.pop();
|
||||
|
||||
auto& func = std::get<I>(overloads);
|
||||
stack::call_into_lua<b ? false : stack::stack_detail::default_check_arguments>(r, a, func, L, start, function_detail::implicit_wrapper<T>(obj));
|
||||
stack::call_into_lua<false>(r, a, func, L, start, function_detail::implicit_wrapper<T>(obj));
|
||||
|
||||
userdataref.push();
|
||||
luaL_getmetatable(L, &meta[0]);
|
||||
|
|
|
@ -205,10 +205,10 @@ static void func_gc(std::true_type, lua_State*) {
|
|||
template <std::size_t limit>
|
||||
static void func_gc(std::false_type, lua_State* L) {
|
||||
for (std::size_t i = 0; i < limit; ++i) {
|
||||
upvalue up = stack::get<upvalue>(L, static_cast<int>(i + 1));
|
||||
if (up.value == nullptr)
|
||||
void* value = stack::get<light_userdata_value>(L, up_value_index(static_cast<int>(i + 1)));
|
||||
if (value == nullptr)
|
||||
continue;
|
||||
base_function* obj = static_cast<base_function*>(up.value);
|
||||
base_function* obj = static_cast<base_function*>(value);
|
||||
std::allocator<base_function> alloc{};
|
||||
alloc.destroy(obj);
|
||||
alloc.deallocate(obj, 1);
|
||||
|
@ -216,19 +216,21 @@ static void func_gc(std::false_type, lua_State* L) {
|
|||
}
|
||||
|
||||
inline int call(lua_State* L) {
|
||||
void** pinheritancedata = static_cast<void**>(stack::get<upvalue>(L, 1).value);
|
||||
void* ludata = stack::get<light_userdata_value>(L, up_value_index(1));
|
||||
void** pinheritancedata = static_cast<void**>(ludata);
|
||||
return base_call(L, *pinheritancedata);
|
||||
}
|
||||
|
||||
inline int gc(lua_State* L) {
|
||||
void** pudata = static_cast<void**>(stack::get<userdata>(L, 1).value);
|
||||
void* udata = stack::get<userdata_value>(L, 1);
|
||||
void** pudata = static_cast<void**>(udata);
|
||||
return base_gc(L, *pudata);
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
inline int usertype_call(lua_State* L) {
|
||||
// Zero-based template parameter, but upvalues start at 1
|
||||
return base_call(L, stack::get<upvalue>(L, I + 1));
|
||||
return base_call(L, stack::get<light_userdata_value>(L, up_value_index(static_cast<int>(I + 1))));
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
|
|
|
@ -57,10 +57,10 @@ inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>
|
|||
if (traits::arity != fxarity) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
if (sizeof...(Fxs) != 0 && !function_detail::check_types(args_type(), args_indices(), L, start)) {
|
||||
if (!function_detail::check_types(args_type(), args_indices(), L, start)) {
|
||||
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
return matchfx(meta::Bool<sizeof...(Fxs) != 0>(), types<Fx>(), Index<I>(), return_types(), args_type(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
return matchfx(types<Fx>(), Index<I>(), return_types(), args_type(), L, fxarity, start, std::forward<Args>(args)...);
|
||||
}
|
||||
} // internals
|
||||
|
||||
|
@ -93,10 +93,10 @@ struct overloaded_function : base_function {
|
|||
|
||||
}
|
||||
|
||||
template <bool b, typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(meta::Bool<b>, types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
auto& func = std::get<I>(overloads);
|
||||
return stack::call_into_lua<b ? false : stack::stack_detail::default_check_arguments>(r, a, func, L, start);
|
||||
return stack::call_into_lua<false>(r, a, func, L, start);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
@ -113,11 +113,11 @@ struct usertype_overloaded_function : base_function {
|
|||
|
||||
usertype_overloaded_function(std::tuple<Functions...> set) : overloads(std::move(set)) {}
|
||||
|
||||
template <bool b,typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(meta::Bool<b>, types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||
int call(types<Fx>, Index<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) {
|
||||
auto& func = std::get<I>(overloads);
|
||||
func.item = detail::ptr(stack::get<T>(L, 1));
|
||||
return stack::call_into_lua<b ? false : stack::stack_detail::default_check_arguments>(r, a, func, L, start);
|
||||
return stack::call_into_lua<false>(r, a, func, L, start);
|
||||
}
|
||||
|
||||
virtual int operator()(lua_State* L) override {
|
||||
|
|
|
@ -151,7 +151,7 @@ struct usertype_indexing_function : base_function {
|
|||
if (functionpair != functions.end()) {
|
||||
std::pair<bool, base_function*>& target = functionpair->second;
|
||||
if (target.first) {
|
||||
stack::push<upvalue>(L, target.second);
|
||||
stack::push<light_userdata_value>(L, target.second);
|
||||
stack::push(L, c_closure(usertype_call<0>, 1));
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#define SOL_INHERITANCE_HPP
|
||||
|
||||
#include "types.hpp"
|
||||
#if defined(SOL_NO_RTTI) && defined(SOL_NO_EXCEPTIONS)
|
||||
#include <atomic>
|
||||
#endif // No Runtime Type Information and No Exceptions
|
||||
|
||||
namespace sol {
|
||||
template <typename... Args>
|
||||
|
@ -30,53 +33,69 @@ struct base_list { };
|
|||
template <typename... Args>
|
||||
using bases = base_list<Args...>;
|
||||
|
||||
const auto base_classes = bases<>();
|
||||
typedef bases<> base_classes_tag;
|
||||
const auto base_classes = base_classes_tag();
|
||||
|
||||
namespace detail {
|
||||
#if defined(SOL_NO_RTTI) && defined(SOL_NO_EXCEPTIONS)
|
||||
inline std::size_t unique_id () {
|
||||
static std::atomic<std::size_t> x(0);
|
||||
return ++x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct id_for {
|
||||
static const std::size_t value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const std::size_t id_for<T>::value = unique_id();
|
||||
#endif // No Runtime Type Information / No Exceptions
|
||||
|
||||
const auto& base_class_check_key = u8"♡o。.(✿ฺ。 ✿ฺ)";
|
||||
const auto& base_class_cast_key = u8"(◕‿◕✿)";
|
||||
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
|
||||
template <typename T>
|
||||
void throw_as(void* p) {
|
||||
throw static_cast<T*>(p);
|
||||
template <typename T>
|
||||
void throw_as(void* p) {
|
||||
throw static_cast<T*>(p);
|
||||
}
|
||||
|
||||
using throw_cast = decltype(&throw_as<void>);
|
||||
|
||||
template <typename T>
|
||||
inline T* catch_cast(void* p, throw_cast f) {
|
||||
try {
|
||||
f(static_cast<void*>(p));
|
||||
}
|
||||
|
||||
using throw_cast = decltype(&throw_as<void>);
|
||||
|
||||
template <typename T>
|
||||
T* catch_cast(void* p, throw_cast f) {
|
||||
try {
|
||||
f(static_cast<void*>(p));
|
||||
}
|
||||
catch (T* ptr) {
|
||||
return ptr;
|
||||
}
|
||||
catch (...) {
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
catch (T* ptr) {
|
||||
return ptr;
|
||||
}
|
||||
catch (...) {
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool catch_check(throw_cast f) {
|
||||
try {
|
||||
f( nullptr );
|
||||
}
|
||||
catch (T*) {
|
||||
return true;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
template <typename T>
|
||||
inline bool catch_check(throw_cast f) {
|
||||
try {
|
||||
f( nullptr );
|
||||
}
|
||||
catch (T*) {
|
||||
return true;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
template <typename T, typename... Bases>
|
||||
struct inheritance {
|
||||
static bool type_check(types<>, const std::type_info& typeinfo) {
|
||||
static bool type_check(types<>, const std::type_info&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -89,26 +108,61 @@ struct inheritance {
|
|||
return ti != typeid(T) || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
static void* type_cast(types<>, T*, const std::type_info& typeinfo) {
|
||||
static void* type_cast(types<>, T*, const std::type_info& ti) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Base, typename... Args>
|
||||
static void* type_cast(types<Base, Args...>, T* data, const std::type_info& ti) {
|
||||
// Make sure to convert to T first, and then dynamic cast to the proper type
|
||||
return ti != typeid(Base) ? type_check(types<Bases...>(), ti) : dynamic_cast<Base*>(static_cast<T*>(data));
|
||||
return ti != typeid(Base) ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(dynamic_cast<Base*>(static_cast<T*>(data)));
|
||||
}
|
||||
|
||||
static void* cast(void* data, const std::type_info& ti) {
|
||||
return ti != typeid(T) ? type_check(types<Bases...>(), ti) : static_cast<T*>(data);
|
||||
static void* cast(void* voiddata, const std::type_info& ti) {
|
||||
T* data = static_cast<T*>(voiddata);
|
||||
return static_cast<void*>(ti != typeid(T) ? type_cast(types<Bases...>(), data, ti) : data);
|
||||
}
|
||||
};
|
||||
|
||||
using inheritance_check_function = decltype(&inheritance<void>::check);
|
||||
using inheritance_cast_function = decltype(&inheritance<void>::cast);
|
||||
#endif // No Runtime Type Information
|
||||
#else
|
||||
template <typename T, typename... Bases>
|
||||
struct inheritance {
|
||||
static bool type_check(types<>, std::size_t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // usertype_detail
|
||||
template <typename Base, typename... Args>
|
||||
static bool type_check(types<Base, Args...>, std::size_t ti) {
|
||||
return ti != id_for<Base>::value || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
static bool check(std::size_t ti) {
|
||||
return ti != id_for<T>::value || type_check(types<Bases...>(), ti);
|
||||
}
|
||||
|
||||
static void* type_cast(types<>, T*, std::size_t) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Base, typename... Args>
|
||||
static void* type_cast(types<Base, Args...>, T* data, std::size_t ti) {
|
||||
// Make sure to convert to T first, and then dynamic cast to the proper type
|
||||
return ti != id_for<Base>::value ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
|
||||
}
|
||||
|
||||
static void* cast(void* voiddata, std::size_t ti) {
|
||||
T* data = static_cast<T*>(voiddata);
|
||||
return static_cast<void*>(ti != id_for<T>::value ? type_cast(types<Bases...>(), data, ti) : data);
|
||||
}
|
||||
};
|
||||
|
||||
using inheritance_check_function = decltype(&inheritance<void>::check);
|
||||
using inheritance_cast_function = decltype(&inheritance<void>::cast);
|
||||
#endif // No Exceptions and/or No Runtime Type Information
|
||||
|
||||
} // detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_INHERITANCE_HPP
|
||||
|
|
|
@ -30,8 +30,7 @@
|
|||
namespace sol {
|
||||
class object : public reference {
|
||||
public:
|
||||
object(lua_State* L, int index = -1): reference(L, index) {}
|
||||
object() = default;
|
||||
using reference::reference;
|
||||
|
||||
template<typename T>
|
||||
decltype(auto) as() const {
|
||||
|
@ -41,21 +40,10 @@ public:
|
|||
|
||||
template<typename T>
|
||||
bool is() const {
|
||||
if (!reference::valid())
|
||||
if (!valid())
|
||||
return false;
|
||||
auto expected = type_of<T>();
|
||||
auto actual = get_type();
|
||||
return (expected == actual) || (expected == type::poly);
|
||||
}
|
||||
|
||||
bool valid() const {
|
||||
if (!reference::valid())
|
||||
return false;
|
||||
return !this->is<nil_t>();
|
||||
}
|
||||
|
||||
explicit operator bool() {
|
||||
return valid();
|
||||
auto pp = stack::push_pop(*this);
|
||||
return stack::check<T>(lua_state(), -1, no_panic);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -93,17 +93,17 @@ private:
|
|||
int returncount = 0;
|
||||
call_status code = call_status::ok;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
auto onexcept = [&](const char* error) {
|
||||
auto onexcept = [&](const char* error) {
|
||||
h.stackindex = 0;
|
||||
if (h.target.valid()) {
|
||||
h.target.push();
|
||||
stack::push(lua_state(), error);
|
||||
lua_call(lua_state(), 1, 1);
|
||||
}
|
||||
else {
|
||||
else {
|
||||
stack::push(lua_state(), error);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
try {
|
||||
#endif // No Exceptions
|
||||
code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
|
||||
|
@ -132,7 +132,7 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
sol::reference error_handler;
|
||||
reference error_handler;
|
||||
|
||||
protected_function() = default;
|
||||
protected_function(lua_State* L, int index = -1): reference(L, index), error_handler(get_default_handler()) {
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
decltype(auto) call(Args&&... args) const {
|
||||
handler h(error_handler);
|
||||
push();
|
||||
int pushcount = stack::push_args(lua_state(), std::forward<Args>(args)...);
|
||||
int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...);
|
||||
return invoke(types<Ret...>(), std::index_sequence_for<Ret...>(), pushcount, h);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -34,16 +34,16 @@ private:
|
|||
int index;
|
||||
int returncount;
|
||||
int popcount;
|
||||
call_status error;
|
||||
call_status err;
|
||||
|
||||
public:
|
||||
protected_function_result() = default;
|
||||
protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status error = call_status::ok): L(L), index(index), returncount(returncount), popcount(popcount), error(error) {
|
||||
protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status error = call_status::ok): L(L), index(index), returncount(returncount), popcount(popcount), err(error) {
|
||||
|
||||
}
|
||||
protected_function_result(const protected_function_result&) = default;
|
||||
protected_function_result& operator=(const protected_function_result&) = default;
|
||||
protected_function_result(protected_function_result&& o) : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), error(o.error) {
|
||||
protected_function_result(protected_function_result&& o) : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) {
|
||||
// Must be manual, otherwise destructor will screw us
|
||||
// return count being 0 is enough to keep things clean
|
||||
// but will be thorough
|
||||
|
@ -51,14 +51,14 @@ public:
|
|||
o.index = 0;
|
||||
o.returncount = 0;
|
||||
o.popcount = 0;
|
||||
o.error = call_status::runtime;
|
||||
o.err = call_status::runtime;
|
||||
}
|
||||
protected_function_result& operator=(protected_function_result&& o) {
|
||||
L = o.L;
|
||||
index = o.index;
|
||||
returncount = o.returncount;
|
||||
popcount = o.popcount;
|
||||
error = o.error;
|
||||
err = o.err;
|
||||
// Must be manual, otherwise destructor will screw us
|
||||
// return count being 0 is enough to keep things clean
|
||||
// but will be thorough
|
||||
|
@ -66,12 +66,16 @@ public:
|
|||
o.index = 0;
|
||||
o.returncount = 0;
|
||||
o.popcount = 0;
|
||||
o.error = call_status::runtime;
|
||||
o.err = call_status::runtime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
call_status error() const {
|
||||
return err;
|
||||
}
|
||||
|
||||
bool valid() const {
|
||||
return error == call_status::ok;
|
||||
return error() == call_status::ok;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -83,6 +87,28 @@ public:
|
|||
stack::remove(L, index, popcount);
|
||||
}
|
||||
};
|
||||
|
||||
struct protected_result {
|
||||
private:
|
||||
protected_function_result result;
|
||||
|
||||
public:
|
||||
template <typename... Args>
|
||||
protected_result( Args&&... args ) : result(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
bool valid() const {
|
||||
return result.valid();
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
return valid();
|
||||
}
|
||||
|
||||
protected_function_result& operator* () {
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
#endif // SOL_FUNCTION_RESULT_HPP
|
||||
|
|
|
@ -50,7 +50,7 @@ struct constructor_wrapper : std::tuple<Functions...> {
|
|||
};
|
||||
|
||||
template <typename... Functions>
|
||||
constructor_wrapper<Functions...> constructor(Functions&&... functions) {
|
||||
constructor_wrapper<Functions...> initializers(Functions&&... functions) {
|
||||
return constructor_wrapper<Functions...>(std::forward<Functions>(functions)...);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ private:
|
|||
lua_State* L = nullptr; // non-owning
|
||||
int ref = LUA_NOREF;
|
||||
|
||||
int copy() const {
|
||||
int copy() const noexcept {
|
||||
if (ref == LUA_NOREF)
|
||||
return LUA_NOREF;
|
||||
push();
|
||||
|
@ -60,7 +60,7 @@ private:
|
|||
}
|
||||
|
||||
protected:
|
||||
reference(lua_State* L, detail::global_tag) : L(L) {
|
||||
reference(lua_State* L, detail::global_tag) noexcept : L(L) {
|
||||
lua_pushglobaltable(L);
|
||||
ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
@ -68,12 +68,12 @@ protected:
|
|||
public:
|
||||
reference() noexcept = default;
|
||||
|
||||
reference(lua_State* L, int index = -1): L(L) {
|
||||
reference(lua_State* L, int index = -1) noexcept : L(L) {
|
||||
lua_pushvalue(L, index);
|
||||
ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
virtual ~reference() {
|
||||
virtual ~reference() noexcept {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, ref);
|
||||
}
|
||||
|
||||
|
@ -115,19 +115,19 @@ public:
|
|||
lua_pop(lua_state( ), n);
|
||||
}
|
||||
|
||||
int get_index() const {
|
||||
int registry_index() const noexcept {
|
||||
return ref;
|
||||
}
|
||||
|
||||
bool valid () const {
|
||||
return !(ref == LUA_NOREF);
|
||||
bool valid () const noexcept {
|
||||
return !(ref == LUA_NOREF || ref == LUA_REFNIL);
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
explicit operator bool () const noexcept {
|
||||
return valid();
|
||||
}
|
||||
|
||||
type get_type() const {
|
||||
type get_type() const noexcept {
|
||||
push();
|
||||
int result = lua_type(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
|
156
sol/stack.hpp
156
sol/stack.hpp
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "error.hpp"
|
||||
#include "reference.hpp"
|
||||
#include "userdata.hpp"
|
||||
#include "tuple.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "usertype_traits.hpp"
|
||||
|
@ -60,13 +61,13 @@ inline int push(lua_State* L, Arg&& arg, Args&&... args) {
|
|||
return pusher<meta::Unqualified<T>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline int push_args(lua_State*) {
|
||||
inline int multi_push(lua_State*) {
|
||||
// do nothing
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
inline int push_args(lua_State* L, T&& t, Args&&... args) {
|
||||
inline int multi_push(lua_State* L, T&& t, Args&&... args) {
|
||||
int pushcount = push(L, std::forward<T>(t));
|
||||
void(sol::detail::swallow{(pushcount += sol::stack::push(L, std::forward<Args>(args)), 0)... });
|
||||
return pushcount;
|
||||
|
@ -92,8 +93,8 @@ bool check(lua_State* L, int index, Handler&& handler) {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
bool check(lua_State* L, int index) {
|
||||
auto handler = type_panic;
|
||||
bool check(lua_State* L, int index = -1) {
|
||||
auto handler = no_panic;
|
||||
return check<T>(L, index, handler);
|
||||
}
|
||||
|
||||
|
@ -130,10 +131,10 @@ static int push_upvalues(lua_State* L, TCont&& cont) {
|
|||
int n = 0;
|
||||
for(auto& c : cont) {
|
||||
if(releasemem) {
|
||||
stack::push<upvalue>(L, c.release());
|
||||
stack::push<light_userdata_value>(L, c.release());
|
||||
}
|
||||
else {
|
||||
stack::push<upvalue>(L, c.get());
|
||||
stack::push<light_userdata_value>(L, c.get());
|
||||
}
|
||||
++n;
|
||||
}
|
||||
|
@ -144,7 +145,7 @@ template <typename T>
|
|||
struct userdata_pusher {
|
||||
template <typename Key, typename... Args>
|
||||
static void push (lua_State* L, Key&& metatablekey, Args&&... args) {
|
||||
// Basically, we store all user0data like this:
|
||||
// Basically, we store all user-data like this:
|
||||
// If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new
|
||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||
// do the actual object. Things that are std::ref or plain T* are stored as
|
||||
|
@ -255,26 +256,19 @@ struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value>> {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct getter<userdata> {
|
||||
static userdata get(lua_State* L, int index = -1) {
|
||||
struct getter<userdata_value> {
|
||||
static userdata_value get(lua_State* L, int index = -1) {
|
||||
return{ lua_touserdata(L, index) };
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<light_userdata> {
|
||||
static light_userdata get(lua_State* L, int index = -1) {
|
||||
struct getter<light_userdata_value> {
|
||||
static light_userdata_value get(lua_State* L, int index = -1) {
|
||||
return{ lua_touserdata(L, index) };
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<upvalue> {
|
||||
static upvalue get(lua_State* L, int index = 1) {
|
||||
return{ lua_touserdata(L, lua_upvalueindex(index)) };
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getter<void*> {
|
||||
static void* get(lua_State* L, int index = -1) {
|
||||
|
@ -286,24 +280,36 @@ template<typename T>
|
|||
struct getter<T*> {
|
||||
static T* get_no_nil(lua_State* L, int index = -1) {
|
||||
void** pudata = static_cast<void**>(lua_touserdata(L, index));
|
||||
void* udata = *pudata;
|
||||
void* udata = *pudata;
|
||||
return get_no_nil_from(L, udata, index);
|
||||
}
|
||||
|
||||
static T* get_no_nil_from(lua_State* L, void* udata, int index = -1) {
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
if (luaL_getmetafield(L, -1, &detail::base_class_check_key[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata>(L);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_check_key[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
udata = detail::catch_cast<T>( udata, basecast );
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
udata = detail::catch_cast<T>(udata, basecast);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
if (luaL_getmetafield(L, -1, &detail::base_class_check_key[0]) != 0) {
|
||||
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)stack::get<light_userdata>(L);
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_cast_key[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata;
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
udata = ic(udata, typeid(T));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
#else
|
||||
// Lol, inheritance could never work like this
|
||||
// Lol, you motherfucker
|
||||
if (luaL_getmetafield(L, index, &detail::base_class_cast_key[0]) != 0) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata;
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
udata = ic(udata, detail::id_for<T>::value);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
#endif // No Runtime Type Information || Exceptions
|
||||
T* obj = static_cast<T*>(udata);
|
||||
return obj;
|
||||
|
@ -313,7 +319,14 @@ struct getter<T*> {
|
|||
type t = type_of(L, index);
|
||||
if (t == type::nil)
|
||||
return nullptr;
|
||||
return get_no_nil(L, index);
|
||||
return get_no_nil(L, index);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<non_null<T*>> {
|
||||
static T* get(lua_State* L, int index = -1) {
|
||||
return getter<T*>::get_no_nil(L, index);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -421,7 +434,7 @@ struct checker<T*, type::userdata, C> {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T,typename C>
|
||||
template <typename T, typename C>
|
||||
struct checker<T, type::userdata, C> {
|
||||
template <typename Handler>
|
||||
static bool check (lua_State* L, type indextype, int index, const Handler& handler) {
|
||||
|
@ -429,6 +442,8 @@ struct checker<T, type::userdata, C> {
|
|||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
}
|
||||
if (meta::Or<std::is_same<T, light_userdata_value>, std::is_same<T, userdata_value>>::value)
|
||||
return true;
|
||||
if (lua_getmetatable(L, index) == 0) {
|
||||
handler(L, index, type::userdata, indextype);
|
||||
return false;
|
||||
|
@ -442,20 +457,34 @@ struct checker<T, type::userdata, C> {
|
|||
}
|
||||
bool success = lua_rawequal(L, -1, -2) == 1;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
if (!success) {
|
||||
if (!success) {
|
||||
lua_getfield(L, -2, &detail::base_class_check_key[0]);
|
||||
void* basecastdata = stack::get<light_userdata>(L);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
success |= detail::catch_check<T>(basecast);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
|
||||
success |= detail::catch_check<T>(basecast);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
if (!success) {
|
||||
if (!success) {
|
||||
lua_getfield(L, -2, &detail::base_class_check_key[0]);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)stack::get<light_userdata>(L);
|
||||
success |= ic(typeid(T));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
if (stack::get<type>(L) != type::nil) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
success |= ic(typeid(T));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
#else
|
||||
// Topkek
|
||||
if (!success) {
|
||||
lua_getfield(L, -2, &detail::base_class_check_key[0]);
|
||||
if (stack::get<type>(L) != type::nil) {
|
||||
void* basecastdata = stack::get<light_userdata_value>(L);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
success |= ic(detail::id_for<T>::value);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
#endif // No Runtime Type Information || Exceptions
|
||||
lua_pop(L, 2);
|
||||
return success;
|
||||
|
@ -522,30 +551,25 @@ struct pusher<T, std::enable_if_t<meta::And<std::is_integral<T>, std::is_unsigne
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T, std::enable_if_t<meta::And<meta::has_begin_end<T>, meta::Not<meta::has_key_value_pair<T>>>::value>> {
|
||||
struct pusher<T, std::enable_if_t<meta::And<meta::has_begin_end<T>, meta::Not<meta::has_key_value_pair<T>>, meta::Not<std::is_base_of<reference, T>>>::value>> {
|
||||
static int push(lua_State* L, const T& cont) {
|
||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||
int tableindex = lua_gettop(L);
|
||||
unsigned index = 1;
|
||||
for(auto&& i : cont) {
|
||||
// push the index
|
||||
pusher<unsigned>{}.push(L, index++);
|
||||
// push the value
|
||||
pusher<meta::Unqualified<decltype(i)>>{}.push(L, i);
|
||||
// set the table
|
||||
lua_settable(L, -3);
|
||||
set_field(L, index++, i, tableindex);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T, std::enable_if_t<meta::And<meta::has_begin_end<T>, meta::has_key_value_pair<T>>::value>> {
|
||||
struct pusher<T, std::enable_if_t<meta::And<meta::has_begin_end<T>, meta::has_key_value_pair<T>, meta::Not<std::is_base_of<reference, T>>>::value>> {
|
||||
static int push(lua_State* L, const T& cont) {
|
||||
lua_createtable(L, static_cast<int>(cont.size()), 0);
|
||||
int tableindex = lua_gettop(L);
|
||||
for(auto&& pair : cont) {
|
||||
pusher<meta::Unqualified<decltype(pair.first)>>{}.push(L, pair.first);
|
||||
pusher<meta::Unqualified<decltype(pair.second)>>{}.push(L, pair.second);
|
||||
lua_settable(L, -3);
|
||||
set_field(L, pair.first, pair.second, tableindex);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -556,6 +580,10 @@ struct pusher<T, std::enable_if_t<std::is_base_of<reference, T>::value>> {
|
|||
static int push(lua_State*, T& ref) {
|
||||
return ref.push();
|
||||
}
|
||||
|
||||
static int push(lua_State*, T&& ref) {
|
||||
return ref.push();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -621,24 +649,16 @@ struct pusher<void*> {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct pusher<upvalue> {
|
||||
static int push(lua_State* L, upvalue upv) {
|
||||
lua_pushlightuserdata(L, upv);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<light_userdata> {
|
||||
static int push(lua_State* L, light_userdata userdata) {
|
||||
struct pusher<light_userdata_value> {
|
||||
static int push(lua_State* L, light_userdata_value userdata) {
|
||||
lua_pushlightuserdata(L, userdata);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct pusher<userdata> {
|
||||
static int push(lua_State* L, userdata data) {
|
||||
struct pusher<userdata_value> {
|
||||
static int push(lua_State* L, userdata_value data) {
|
||||
void** ud = static_cast<void**>(lua_newuserdata(L, sizeof(void*)));
|
||||
*ud = data.value;
|
||||
return 1;
|
||||
|
@ -782,7 +802,7 @@ inline int push_as_upvalues(lua_State* L, T& item) {
|
|||
std::memcpy(&data[0], std::addressof(item), itemsize);
|
||||
int pushcount = 0;
|
||||
for(auto&& v : data) {
|
||||
pushcount += push(L, upvalue(v));
|
||||
pushcount += push(L, light_userdata_value(v));
|
||||
}
|
||||
return pushcount;
|
||||
}
|
||||
|
@ -793,7 +813,7 @@ inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
|||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata{ {} };
|
||||
for(std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) {
|
||||
voiddata[i] = get<upvalue>(L, index++);
|
||||
voiddata[i] = get<light_userdata_value>(L, up_value_index(index++));
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
state(lua_CFunction panic = detail::atpanic) : unique_base(luaL_newstate(), lua_close),
|
||||
state_view(unique_base::get()) {
|
||||
set_panic(panic);
|
||||
stack::luajit_exception_handler(unique_base::get());
|
||||
stack::luajit_exception_handler(unique_base::get());
|
||||
}
|
||||
|
||||
using state_view::get;
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace detail {
|
|||
inline int atpanic(lua_State* L) {
|
||||
#ifdef SOL_NO_EXCEPTIONS
|
||||
(void)L;
|
||||
return -1;
|
||||
#else
|
||||
const char* message = lua_tostring(L, -1);
|
||||
std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
|
||||
|
@ -57,12 +58,12 @@ class state_view {
|
|||
private:
|
||||
lua_State* L;
|
||||
table reg;
|
||||
global_table globals;
|
||||
global_table global;
|
||||
public:
|
||||
state_view(lua_State* L):
|
||||
L(L),
|
||||
reg(L, LUA_REGISTRYINDEX),
|
||||
globals(L, detail::global_) {
|
||||
global(L, detail::global_) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -142,81 +143,30 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void open_file(const std::string& filename) {
|
||||
void script_file(const std::string& filename) {
|
||||
if(luaL_dofile(L, filename.c_str())) {
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args, typename... Keys>
|
||||
decltype(auto) get(Keys&&... keys) const {
|
||||
return globals.get<Args...>(std::forward<Keys>(keys)...);
|
||||
table_iterator begin () const {
|
||||
return global.begin();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
state_view& set(Args&&... args) {
|
||||
globals.set(std::forward<Args>(args)...);
|
||||
return *this;
|
||||
table_iterator end() const {
|
||||
return global.end();
|
||||
}
|
||||
|
||||
template<typename T, typename... Keys>
|
||||
decltype(auto) traverse_get(Keys&&... keys) const {
|
||||
return globals.traverse_get<T>(std::forward<Keys>(keys)...);
|
||||
table_iterator cbegin() const {
|
||||
return global.cbegin();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
state_view& traverse_set(Args&&... args) {
|
||||
globals.traverse_set(std::forward<Args>(args)...);
|
||||
return *this;
|
||||
table_iterator cend() const {
|
||||
return global.cend();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
state_view& set_usertype(usertype<T>& user) {
|
||||
return set_usertype(usertype_traits<T>::name, user);
|
||||
}
|
||||
|
||||
template<typename Key, typename T>
|
||||
state_view& set_usertype(Key&& key, usertype<T>& user) {
|
||||
globals.set_usertype(std::forward<Key>(key), user);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, Args&&... args) {
|
||||
usertype<Class> utype(std::forward<Args>(args)...);
|
||||
set_usertype(name, utype);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename CTor0, typename... CTor, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, Args&&... args) {
|
||||
constructors<types<CTor0, CTor...>> ctor{};
|
||||
return new_usertype<Class>(name, ctor, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Class, typename... CArgs, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) {
|
||||
usertype<Class> utype(ctor, std::forward<Args>(args)...);
|
||||
set_usertype(name, utype);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
void for_each(Fx&& fx) {
|
||||
globals.for_each(std::forward<Fx>(fx));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
table create_table(T&& key, int narr = 0, int nrec = 0) {
|
||||
lua_createtable(L, narr, nrec);
|
||||
table result(L);
|
||||
lua_pop(L, 1);
|
||||
globals.set(std::forward<T>(key), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
global_table global() const {
|
||||
return globals;
|
||||
global_table globals() const {
|
||||
return global;
|
||||
}
|
||||
|
||||
table registry() const {
|
||||
|
@ -227,45 +177,110 @@ public:
|
|||
lua_atpanic(L, panic);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<global_table&, T> operator[](T&& key) {
|
||||
return globals[std::forward<T>(key)];
|
||||
template<typename... Args, typename... Keys>
|
||||
decltype(auto) get(Keys&&... keys) const {
|
||||
return global.get<Args...>(std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
state_view& set(Args&&... args) {
|
||||
global.set(std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename... Keys>
|
||||
decltype(auto) traverse_get(Keys&&... keys) const {
|
||||
return global.traverse_get<T>(std::forward<Keys>(keys)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
state_view& traverse_set(Args&&... args) {
|
||||
global.traverse_set(std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<const global_table, T> operator[](T&& key) const {
|
||||
return globals[std::forward<T>(key)];
|
||||
state_view& set_usertype(usertype<T>& user) {
|
||||
return set_usertype(usertype_traits<T>::name, user);
|
||||
}
|
||||
|
||||
template<typename Key, typename T>
|
||||
state_view& set_usertype(Key&& key, usertype<T>& user) {
|
||||
global.set_usertype(std::forward<Key>(key), user);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, Args&&... args) {
|
||||
global.new_usertype<Class>(name, std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename CTor0, typename... CTor, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, Args&&... args) {
|
||||
global.new_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename... CArgs, typename... Args>
|
||||
state_view& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) {
|
||||
global.new_usertype<Class>(name, ctor, std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Fx>
|
||||
void for_each(Fx&& fx) {
|
||||
global.for_each(std::forward<Fx>(fx));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<global_table&, T> operator[](T&& key) {
|
||||
return global[std::forward<T>(key)];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
proxy<const global_table&, T> operator[](T&& key) const {
|
||||
return global[std::forward<T>(key)];
|
||||
}
|
||||
|
||||
template<typename... Args, typename R, typename Key>
|
||||
state_view& set_function(Key&& key, R fun_ptr(Args...)){
|
||||
globals.set_function(std::forward<Key>(key), fun_ptr);
|
||||
global.set_function(std::forward<Key>(key), fun_ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Sig, typename Key>
|
||||
state_view& set_function(Key&& key, Sig* fun_ptr){
|
||||
globals.set_function(std::forward<Key>(key), fun_ptr);
|
||||
global.set_function(std::forward<Key>(key), fun_ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Args, typename R, typename C, typename T, typename Key>
|
||||
state_view& set_function(Key&& key, R (C::*mem_ptr)(Args...), T&& obj) {
|
||||
globals.set_function(std::forward<Key>(key), mem_ptr, std::forward<T>(obj));
|
||||
global.set_function(std::forward<Key>(key), mem_ptr, std::forward<T>(obj));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Sig, typename C, typename T, typename Key>
|
||||
state_view& set_function(Key&& key, Sig C::* mem_ptr, T&& obj) {
|
||||
globals.set_function(std::forward<Key>(key), mem_ptr, std::forward<T>(obj));
|
||||
global.set_function(std::forward<Key>(key), mem_ptr, std::forward<T>(obj));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Sig, typename Fx, typename Key>
|
||||
state_view& set_function(Key&& key, Fx&& fx) {
|
||||
globals.set_function<Sig...>(std::forward<Key>(key), std::forward<Fx>(fx));
|
||||
global.set_function<Sig...>(std::forward<Key>(key), std::forward<Fx>(fx));
|
||||
return *this;
|
||||
}
|
||||
|
||||
static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) {
|
||||
return global_table::create(L, narr, nrec);
|
||||
}
|
||||
|
||||
template <typename Key, typename Value, typename... Args>
|
||||
static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
|
||||
return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "stack.hpp"
|
||||
#include "function_types.hpp"
|
||||
#include "usertype.hpp"
|
||||
#include "table_iterator.hpp"
|
||||
|
||||
namespace sol {
|
||||
template <bool top_level>
|
||||
|
@ -36,6 +37,31 @@ class table_core : public reference {
|
|||
template <typename... Args>
|
||||
using is_global = meta::And<meta::Bool<top_level>, meta::is_c_str<Args>...>;
|
||||
|
||||
template<typename Fx>
|
||||
void for_each(std::true_type, Fx&& fx) const {
|
||||
auto pp = stack::push_pop( *this );
|
||||
stack::push( lua_state( ), nil );
|
||||
while ( lua_next( this->lua_state( ), -2 ) ) {
|
||||
sol::object key( lua_state( ), -2 );
|
||||
sol::object value( lua_state( ), -1 );
|
||||
std::pair<sol::object&, sol::object&> keyvalue(key, value);
|
||||
fx( keyvalue );
|
||||
lua_pop( lua_state( ), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Fx>
|
||||
void for_each(std::false_type, Fx&& fx) const {
|
||||
auto pp = stack::push_pop( *this );
|
||||
stack::push( lua_state( ), nil );
|
||||
while ( lua_next( this->lua_state( ), -2 ) ) {
|
||||
sol::object key( lua_state( ), -2 );
|
||||
sol::object value( lua_state( ), -1 );
|
||||
fx( key, value );
|
||||
lua_pop( lua_state( ), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Ret, std::size_t... I, typename Keys>
|
||||
auto tuple_get( types<Ret...>, std::index_sequence<I...>, Keys&& keys ) const
|
||||
-> decltype(stack::pop<std::tuple<Ret...>>(nullptr)){
|
||||
|
@ -85,11 +111,27 @@ class table_core : public reference {
|
|||
|
||||
public:
|
||||
table_core( ) noexcept : reference( ) { }
|
||||
table_core( const table_core<true>& global ) : reference( global ) { }
|
||||
table_core( const table_core<true>& global ) noexcept : reference( global ) { }
|
||||
table_core( lua_State* L, int index = -1 ) : reference( L, index ) {
|
||||
type_assert( L, index, type::table );
|
||||
}
|
||||
|
||||
table_iterator begin () const {
|
||||
return table_iterator(*this);
|
||||
}
|
||||
|
||||
table_iterator end() const {
|
||||
return table_iterator();
|
||||
}
|
||||
|
||||
table_iterator cbegin() const {
|
||||
return begin();
|
||||
}
|
||||
|
||||
table_iterator cend() const {
|
||||
return end();
|
||||
}
|
||||
|
||||
template<typename... Ret, typename... Keys>
|
||||
decltype(auto) get( Keys&&... keys ) const {
|
||||
return tuple_get( types<Ret...>( ), std::index_sequence_for<Ret...>( ), std::forward_as_tuple(std::forward<Keys>(keys)...));
|
||||
|
@ -126,16 +168,30 @@ public:
|
|||
return set(std::forward<Key>(key), user);
|
||||
}
|
||||
|
||||
template<typename Class, typename... Args>
|
||||
table_core& new_usertype(const std::string& name, Args&&... args) {
|
||||
usertype<Class> utype(std::forward<Args>(args)...);
|
||||
set_usertype(name, utype);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Class, typename CTor0, typename... CTor, typename... Args>
|
||||
table_core& new_usertype(const std::string& name, Args&&... args) {
|
||||
constructors<types<CTor0, CTor...>> ctor{};
|
||||
return new_usertype<Class>(name, ctor, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Class, typename... CArgs, typename... Args>
|
||||
table_core& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) {
|
||||
usertype<Class> utype(ctor, std::forward<Args>(args)...);
|
||||
set_usertype(name, utype);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Fx>
|
||||
void for_each( Fx&& fx ) const {
|
||||
auto pp = stack::push_pop( *this );
|
||||
stack::push( lua_state( ), nil );
|
||||
while ( lua_next( this->lua_state( ), -2 ) ) {
|
||||
sol::object key( lua_state( ), -2 );
|
||||
sol::object value( lua_state( ), -1 );
|
||||
fx( key, value );
|
||||
lua_pop( lua_state( ), 1 );
|
||||
}
|
||||
typedef meta::is_callable<Fx( std::pair<sol::object, sol::object> )> is_paired;
|
||||
for_each(is_paired(), std::forward<Fx>(fx));
|
||||
}
|
||||
|
||||
size_t size( ) const {
|
||||
|
@ -221,6 +277,8 @@ public:
|
|||
|
||||
template <typename Key, typename Value, typename... Args>
|
||||
static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) {
|
||||
if (narr == 0) narr = static_cast<int>(meta::count_if_pack<std::is_integral, Key, Value, Args...>::value);
|
||||
if (nrec == 0) nrec = static_cast<int>(( sizeof...(Args) + 2 ) - narr);
|
||||
lua_createtable(L, narr, nrec);
|
||||
table result(L);
|
||||
result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...);
|
||||
|
|
|
@ -135,6 +135,16 @@ using at_in_pack_t = typename at_in_pack<I, Args...>::type;
|
|||
template<std::size_t I, typename Arg, typename... Args>
|
||||
struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {};
|
||||
|
||||
namespace meta_detail {
|
||||
template<std::size_t I, template<typename...> class Pred, typename... Ts>
|
||||
struct count_if_pack {};
|
||||
template<std::size_t I, template<typename...> class Pred, typename T, typename... Ts>
|
||||
struct count_if_pack<I, Pred, T, Ts...> : std::conditional_t<sizeof...(Ts) == 0, std::integral_constant<std::size_t, I>, count_if_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...>> { };
|
||||
} // meta_detail
|
||||
|
||||
template<template<typename...> class Pred, typename... Ts>
|
||||
struct count_if_pack : meta_detail::count_if_pack<0, Pred, Ts...> { };
|
||||
|
||||
template<typename... Args>
|
||||
struct return_type {
|
||||
typedef std::tuple<Args...> type;
|
||||
|
@ -153,7 +163,22 @@ struct return_type<> {
|
|||
template <typename... Args>
|
||||
using return_type_t = typename return_type<Args...>::type;
|
||||
|
||||
namespace detail {
|
||||
namespace meta_detail {
|
||||
template <typename> struct always_true : std::true_type {};
|
||||
struct is_callable_tester {
|
||||
template <typename Fun, typename... Args>
|
||||
always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
|
||||
template <typename...>
|
||||
std::false_type static test(...);
|
||||
};
|
||||
} // meta_detail
|
||||
|
||||
template <typename T>
|
||||
struct is_callable;
|
||||
template <typename Fun, typename... Args>
|
||||
struct is_callable<Fun(Args...)> : decltype(meta_detail::is_callable_tester::test<Fun, Args...>(0)) {};
|
||||
|
||||
namespace meta_detail {
|
||||
|
||||
template<typename T, bool isclass = std::is_class<Unqualified<T>>::value>
|
||||
struct is_function_impl : std::is_function<std::remove_pointer_t<T>> {};
|
||||
|
@ -186,15 +211,15 @@ struct check_deducible_signature {
|
|||
|
||||
using type = std::is_void<decltype(test<F>(0))>;
|
||||
};
|
||||
} // detail
|
||||
} // meta_detail
|
||||
|
||||
template<class F>
|
||||
struct has_deducible_signature : detail::check_deducible_signature<F>::type { };
|
||||
struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { };
|
||||
|
||||
template<typename T>
|
||||
struct Function : Bool<detail::is_function_impl<T>::value> {};
|
||||
struct Function : Bool<meta_detail::is_function_impl<T>::value> {};
|
||||
|
||||
namespace detail {
|
||||
namespace meta_detail {
|
||||
template<typename Signature, bool b = has_deducible_signature<Signature>::value>
|
||||
struct fx_traits;
|
||||
|
||||
|
@ -263,10 +288,10 @@ struct fx_traits<R(*)(Args...), false> {
|
|||
using arg = std::tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // meta_detail
|
||||
|
||||
template<typename Signature>
|
||||
struct function_traits : detail::fx_traits<std::decay_t<Signature>> {};
|
||||
struct function_traits : meta_detail::fx_traits<std::decay_t<Signature>> {};
|
||||
|
||||
template<typename Signature>
|
||||
using function_args_t = typename function_traits<Signature>::args_type;
|
||||
|
@ -277,7 +302,7 @@ using function_signature_t = typename function_traits<Signature>::signature_type
|
|||
template<typename Signature>
|
||||
using function_return_t = typename function_traits<Signature>::return_type;
|
||||
|
||||
namespace detail {
|
||||
namespace meta_detail {
|
||||
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
|
||||
struct callable_traits : function_traits<Signature> {
|
||||
|
||||
|
@ -299,10 +324,10 @@ struct callable_traits<Signature, true> {
|
|||
template<std::size_t i>
|
||||
using arg = std::tuple_element_t<i, args_tuple_type>;
|
||||
};
|
||||
} // detail
|
||||
} // meta_detail
|
||||
|
||||
template<typename Signature>
|
||||
struct callable_traits : detail::callable_traits<std::remove_volatile_t<Signature>> {
|
||||
struct callable_traits : meta_detail::callable_traits<std::remove_volatile_t<Signature>> {
|
||||
|
||||
};
|
||||
|
||||
|
@ -339,7 +364,7 @@ using is_string_constructible = Or<std::is_same<Unqualified<T>, const char*>, st
|
|||
template <typename T>
|
||||
using is_c_str = Or<std::is_same<std::decay_t<Unqualified<T>>, char*>, std::is_same<Unqualified<T>, std::string>>;
|
||||
|
||||
namespace detail {
|
||||
namespace meta_detail {
|
||||
template <typename T, meta::DisableIf<meta::is_specialization_of<meta::Unqualified<T>, std::tuple>> = 0>
|
||||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward_as_tuple(x);
|
||||
|
@ -349,11 +374,11 @@ template <typename T, meta::EnableIf<meta::is_specialization_of<meta::Unqualifie
|
|||
decltype(auto) force_tuple(T&& x) {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
} // detail
|
||||
} // meta_detail
|
||||
|
||||
template <typename... X>
|
||||
decltype(auto) tuplefy(X&&... x ) {
|
||||
return std::tuple_cat(detail::force_tuple(x)...);
|
||||
return std::tuple_cat(meta_detail::force_tuple(x)...);
|
||||
}
|
||||
} // meta
|
||||
namespace detail {
|
||||
|
@ -411,7 +436,7 @@ template<typename T>
|
|||
inline T* ptr(T* val) {
|
||||
return val;
|
||||
}
|
||||
} // detail
|
||||
} // meta_detail
|
||||
} // sol
|
||||
|
||||
#endif // SOL_TRAITS_HPP
|
||||
|
|
|
@ -87,27 +87,27 @@ const nil_t nil {};
|
|||
inline bool operator==(nil_t, nil_t) { return true; }
|
||||
inline bool operator!=(nil_t, nil_t) { return false; }
|
||||
|
||||
struct void_type : types<void> {}; // This is important because it allows myobject.call( Void, ... ) to work
|
||||
const void_type Void {};
|
||||
template <typename T>
|
||||
struct non_null {};
|
||||
|
||||
template<typename... Args>
|
||||
struct function_sig {};
|
||||
|
||||
struct upvalue {
|
||||
struct up_value_index {
|
||||
int index;
|
||||
up_value_index(int idx) : index(lua_upvalueindex(idx)) {}
|
||||
operator int() const { return index; }
|
||||
};
|
||||
|
||||
struct light_userdata_value {
|
||||
void* value;
|
||||
upvalue(void* data) : value(data) {}
|
||||
light_userdata_value(void* data) : value(data) {}
|
||||
operator void*() const { return value; }
|
||||
};
|
||||
|
||||
struct light_userdata {
|
||||
struct userdata_value {
|
||||
void* value;
|
||||
light_userdata(void* data) : value(data) {}
|
||||
operator void*() const { return value; }
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
void* value;
|
||||
userdata(void* data) : value(data) {}
|
||||
userdata_value(void* data) : value(data) {}
|
||||
operator void*() const { return value; }
|
||||
};
|
||||
|
||||
|
@ -161,7 +161,7 @@ inline int type_panic(lua_State* L, int index, type expected, type actual) {
|
|||
}
|
||||
|
||||
// Specify this function as the handler for lua::check if you know there's nothing wrong
|
||||
inline int no_panic(lua_State*, int, type, type) {
|
||||
inline int no_panic(lua_State*, int, type, type) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -202,6 +202,8 @@ class protected_function;
|
|||
class coroutine;
|
||||
class thread;
|
||||
class object;
|
||||
class userdata;
|
||||
class light_userdata;
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct lua_type_of : std::integral_constant<type, type::userdata> {};
|
||||
|
@ -230,9 +232,18 @@ struct lua_type_of<global_table> : std::integral_constant<type, type::table> { }
|
|||
template <>
|
||||
struct lua_type_of<object> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<light_userdata_value> : std::integral_constant<type, type::lightuserdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<light_userdata> : std::integral_constant<type, type::lightuserdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<userdata> : std::integral_constant<type, type::userdata> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> {};
|
||||
|
||||
|
|
|
@ -121,12 +121,12 @@ inline void push_metatable(lua_State* L, bool needsindexfunction, Funcs&& funcs,
|
|||
int metatableindex = lua_gettop(L);
|
||||
#if !defined(SOL_NO_EXCEPTIONS) || !defined(SOL_NO_RTTI)
|
||||
if (baseclasscheck != nullptr) {
|
||||
stack::push(L, light_userdata(baseclasscheck));
|
||||
lua_setfield(L, metatableindex, &detail::base_class_check_key[0]);
|
||||
stack::push(L, light_userdata_value(baseclasscheck));
|
||||
lua_setfield(L, metatableindex, &detail::base_class_check_key[0]);
|
||||
}
|
||||
if (baseclasscast != nullptr) {
|
||||
stack::push(L, light_userdata(baseclasscast));
|
||||
lua_setfield(L, metatableindex, &detail::base_class_cast_key[0]);
|
||||
stack::push(L, light_userdata_value(baseclasscast));
|
||||
lua_setfield(L, metatableindex, &detail::base_class_cast_key[0]);
|
||||
}
|
||||
#endif // No Exceptions || RTTI
|
||||
if (funcs.size() < 1 && metafunctable.size() < 2) {
|
||||
|
@ -342,17 +342,24 @@ private:
|
|||
}
|
||||
|
||||
template<std::size_t N, typename... Bases, typename... Args>
|
||||
void build_function_tables(bases<>, bases<Bases...>, Args&&... args) {
|
||||
void build_function_tables(base_classes_tag, bases<Bases...>, Args&&... args) {
|
||||
build_function_tables<N>(std::forward<Args>(args)...);
|
||||
if (sizeof...(Bases) < 1)
|
||||
return;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
static_assert(sizeof(void*) <= sizeof(detail::throw_cast), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscast = (void*)&detail::throw_as<T>;
|
||||
static_assert(sizeof(void*) <= sizeof(detail::throw_cast), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscast = (void*)&detail::throw_as<T>;
|
||||
#elif !defined(SOL_NO_RTTI)
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::userdata_check<T, Bases...>::check;
|
||||
baseclasscast = (void*)&detail::userdata_check<T, Bases...>::cast;
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::cast;
|
||||
#else
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::cast;
|
||||
#endif // No Runtime Type Information vs. Throw-Style Inheritance
|
||||
build_function_tables<N>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
|
|
|
@ -35,16 +35,16 @@ struct usertype_traits {
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::name = detail::demangle(typeid(T));
|
||||
const std::string usertype_traits<T>::name = detail::demangle<T>();
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle(typeid(T)));
|
||||
const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::variable_metatable = std::string("sol.").append(detail::demangle(typeid(T))).append(".variables");
|
||||
const std::string usertype_traits<T>::variable_metatable = std::string("sol.").append(detail::demangle<T>()).append(".variables");
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::gc_table = std::string("sol.").append(detail::demangle(typeid(T))).append(".\xE2\x99\xBB");
|
||||
const std::string usertype_traits<T>::gc_table = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB"));
|
||||
|
||||
}
|
||||
|
||||
|
|
93
tests.cpp
93
tests.cpp
|
@ -1,5 +1,6 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
|
||||
#include <catch.hpp>
|
||||
#include <sol.hpp>
|
||||
#include <vector>
|
||||
|
@ -546,6 +547,17 @@ TEST_CASE("tables/variables", "Check if tables and variables work as intended")
|
|||
REQUIRE_NOTHROW(lua.script("assert(os.name == \"windows\")"));
|
||||
}
|
||||
|
||||
TEST_CASE("tables/create", "Check if creating a table is kosher") {
|
||||
sol::state lua;
|
||||
lua["testtable"] = sol::table::create(lua.lua_state(), 0, 0, "Woof", "Bark", 1, 2, 3, 4);
|
||||
sol::object testobj = lua["testtable"];
|
||||
REQUIRE(testobj.is<sol::table>());
|
||||
sol::table testtable = testobj.as<sol::table>();
|
||||
REQUIRE((testtable["Woof"] == std::string("Bark")));
|
||||
REQUIRE((testtable[1] == 2));
|
||||
REQUIRE((testtable[3] == 4));
|
||||
}
|
||||
|
||||
TEST_CASE("tables/functions-variables", "Check if tables and function calls work as intended") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base, sol::lib::os);
|
||||
|
@ -754,7 +766,7 @@ TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works
|
|||
REQUIRE(b == 20.4);
|
||||
};
|
||||
|
||||
REQUIRE_NOTHROW(assert1(lua.global()));
|
||||
REQUIRE_NOTHROW(assert1(lua.globals()));
|
||||
}
|
||||
|
||||
TEST_CASE("tables/usertype", "Show that we can create classes from usertype and use them") {
|
||||
|
@ -771,7 +783,7 @@ TEST_CASE("tables/usertype", "Show that we can create classes from usertype and
|
|||
sol::object a = lua.get<sol::object>("a");
|
||||
sol::object b = lua.get<sol::object>("b");
|
||||
sol::object c = lua.get<sol::object>("c");
|
||||
REQUIRE((a.is<sol::userdata>()));
|
||||
REQUIRE((a.is<sol::userdata_value>()));
|
||||
auto atype = a.get_type();
|
||||
auto btype = b.get_type();
|
||||
auto ctype = c.get_type();
|
||||
|
@ -839,7 +851,7 @@ TEST_CASE("tables/usertype-utility", "Show internal management of classes regist
|
|||
sol::object a = lua.get<sol::object>("a");
|
||||
sol::object b = lua.get<sol::object>("b");
|
||||
sol::object c = lua.get<sol::object>("c");
|
||||
REQUIRE((a.is<sol::userdata>()));
|
||||
REQUIRE((a.is<sol::userdata_value>()));
|
||||
auto atype = a.get_type();
|
||||
auto btype = b.get_type();
|
||||
auto ctype = c.get_type();
|
||||
|
@ -941,8 +953,7 @@ TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a l
|
|||
sol::table tbl = lua[ "arr" ];
|
||||
std::size_t tablesize = 4;
|
||||
std::size_t iterations = 0;
|
||||
tbl.for_each(
|
||||
[&iterations](sol::object key, sol::object value) {
|
||||
auto fx = [&iterations](sol::object key, sol::object value) {
|
||||
++iterations;
|
||||
sol::type keytype = key.get_type();
|
||||
switch (keytype) {
|
||||
|
@ -973,8 +984,72 @@ TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a l
|
|||
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/iterators", "Testing the use of iteratrs to get values from a lua table") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.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;
|
||||
{
|
||||
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::nil_t>()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case sol::type::string:
|
||||
if (key.as<std::string>() == "WOOF") {
|
||||
REQUIRE((value.as<double>() == 123));
|
||||
}
|
||||
break;
|
||||
case sol::type::nil:
|
||||
REQUIRE((value.as<double>() == 3));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}(kvp.first, kvp.second);
|
||||
}
|
||||
} REQUIRE(begintop == endtop);
|
||||
REQUIRE(iterations == tablesize);
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1440,7 @@ TEST_CASE("usertype/private-constructible", "Check to make sure special snowflak
|
|||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<factory_test>("factory_test",
|
||||
"new", sol::constructor(factory_test::save),
|
||||
"new", sol::initializers(factory_test::save),
|
||||
"__gc", sol::destructor(factory_test::kill),
|
||||
"a", &factory_test::a
|
||||
);
|
||||
|
@ -1470,7 +1545,7 @@ end
|
|||
lua.script(script);
|
||||
sol::thread runner = sol::thread::create(lua.lua_state());
|
||||
sol::state_view runnerstate = runner.state();
|
||||
sol::coroutine cr = lua["loop"];
|
||||
sol::coroutine cr = runnerstate["loop"];
|
||||
|
||||
int counter;
|
||||
for (counter = 20; counter < 31 && cr; ++counter) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user