mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
container changes reverted
perhaps one day...
This commit is contained in:
parent
0aab55cea4
commit
6fbae52e9f
1
sol.hpp
1
sol.hpp
|
@ -25,6 +25,5 @@
|
|||
#include "sol/state.hpp"
|
||||
#include "sol/object.hpp"
|
||||
#include "sol/function.hpp"
|
||||
#include "sol/container.hpp"
|
||||
|
||||
#endif // SOL_HPP
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
#ifndef SOL_CONTAINER_HPP
|
||||
#define SOL_CONTAINER_HPP
|
||||
|
||||
#include "userdata.hpp"
|
||||
|
||||
namespace sol {
|
||||
|
||||
template <typename Tc, typename = void>
|
||||
struct container {
|
||||
typedef typename std::conditional<std::is_lvalue_reference<Tc>::value, Tc, Unqualified<Tc>>::type T;
|
||||
typedef Unqualified<decltype(*(std::declval<T>().begin()))> value_type;
|
||||
T cont;
|
||||
|
||||
template <typename... Args>
|
||||
container (Args&&... args) : cont(std::forward<Args>(args)...){
|
||||
|
||||
}
|
||||
|
||||
operator T& () const {
|
||||
return cont;
|
||||
}
|
||||
|
||||
void set(std::ptrdiff_t i, const value_type& value) {
|
||||
cont[ i ] = value;
|
||||
}
|
||||
|
||||
value_type& get(std::ptrdiff_t i) {
|
||||
return cont[ i ];
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return cont.size();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Tc>
|
||||
struct container<Tc, typename std::enable_if<has_key_value_pair<Unqualified<Tc>>::value>::type> {
|
||||
typedef typename std::conditional<std::is_lvalue_reference<Tc>::value, Tc, Decay<Tc>>::type T;
|
||||
typedef Unqualified<decltype((*(std::declval<T>().begin())).first)> key_type;
|
||||
typedef Unqualified<decltype((*(std::declval<T>().begin())).second)> value_type;
|
||||
T cont;
|
||||
|
||||
template <typename... Args>
|
||||
container (Args&&... args) : cont(std::forward<Args>(args)...){
|
||||
|
||||
}
|
||||
|
||||
operator T& () const {
|
||||
return cont;
|
||||
}
|
||||
|
||||
void set(key_type i, const value_type& value) {
|
||||
cont[ i ] = value;
|
||||
}
|
||||
|
||||
value_type& get(key_type i) {
|
||||
return cont.at(i);
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return cont.size();
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
template<typename T>
|
||||
struct pusher<T, typename std::enable_if<has_begin_end<T>::value>::type> {
|
||||
static void push(lua_State* L, const T& cont) {
|
||||
typedef container<T> container_t;
|
||||
// todo: NEED to find a different way of handling this...
|
||||
static std::vector<std::shared_ptr<void>> classes{};
|
||||
userdata<container_t> classdata(default_constructor,
|
||||
"__index", &container_t::get,
|
||||
"__newindex", &container_t::set,
|
||||
"__len", &container_t::size);
|
||||
classes.emplace_back(std::make_shared<userdata<container_t>>(std::move(classdata)));
|
||||
auto&& ptr = classes.back();
|
||||
auto udata = std::static_pointer_cast<userdata<container_t>>(ptr);
|
||||
stack::push(L, *udata);
|
||||
|
||||
container_t* c = static_cast<container_t*>(lua_newuserdata(L, sizeof(container_t)));
|
||||
std::allocator<container_t> alloc{};
|
||||
alloc.construct(c, cont);
|
||||
|
||||
auto&& meta = userdata_traits<container_t>::metatable;
|
||||
if (luaL_newmetatable(L, std::addressof(meta[0])) == 1) {
|
||||
std::string err("metatable not defined for ");
|
||||
err += meta;
|
||||
throw error(err);
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct getter<T, typename std::enable_if<has_begin_end<T>::value>::type> {
|
||||
static Unqualified<T>& get(lua_State* L, int index = -1) {
|
||||
typedef container<Unqualified<T>> container_t;
|
||||
container_t& data = stack::get<container_t>(L, index);
|
||||
return data.cont;
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
} // sol
|
||||
#endif // SOL_CONTAINER_HPP
|
|
@ -83,7 +83,7 @@ struct static_function {
|
|||
return_type r = stack::get_call(L, fx, t);
|
||||
std::ptrdiff_t nargs = sizeof...(Args);
|
||||
lua_pop(L, nargs);
|
||||
stack::push(L, std::move(r));
|
||||
stack::push(L, std::forward<return_type>(r));
|
||||
return sizeof...(Ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -184,38 +184,8 @@ struct pusher {
|
|||
lua_pushunsigned(L, value);
|
||||
}
|
||||
|
||||
template<typename U = T, EnableIf<std::is_base_of<reference, U>> = 0>
|
||||
static void push(lua_State*, T& ref) {
|
||||
ref.push();
|
||||
}
|
||||
|
||||
template<typename U = T, EnableIf<Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||
static void push(lua_State* L, T& t) {
|
||||
pusher<T*>{}.push(L, std::addressof(t));
|
||||
}
|
||||
|
||||
template<typename U = Unqualified<T>, EnableIf<Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||
static void push(lua_State* L, T&& t) {
|
||||
detail::push_userdata<U>(L, userdata_traits<T*>::metatable, std::move(t));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*> {
|
||||
static void push(lua_State* L, T* obj) {
|
||||
detail::push_userdata<T*>(L, userdata_traits<T*>::metatable, obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pusher<table> {
|
||||
template<typename T, typename U = Unqualified<T>, EnableIf<std::is_base_of<reference, U>> = 0>
|
||||
static void push_as(lua_State *L, T&& ref) {
|
||||
ref.push();
|
||||
}
|
||||
|
||||
template<typename T, typename U = Unqualified<T>, EnableIf<has_begin_end<U>, Not<has_key_value_pair<U>>> = 0>
|
||||
static void push_as(lua_State* L, const T& cont) {
|
||||
template<typename U = T, EnableIf<has_begin_end<U>, Not<has_key_value_pair<U>>> = 0>
|
||||
static void push(lua_State* L, const T& cont) {
|
||||
lua_createtable(L, cont.size(), 0);
|
||||
unsigned index = 1;
|
||||
for(auto&& i : cont) {
|
||||
|
@ -228,8 +198,8 @@ struct pusher<table> {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T, typename U = Unqualified<T>, EnableIf<has_begin_end<U>, has_key_value_pair<U>> = 0>
|
||||
static void push_as(lua_State* L, const T& cont) {
|
||||
template<typename U = T, EnableIf<has_begin_end<U>, has_key_value_pair<U>> = 0>
|
||||
static void push(lua_State* L, const T& cont) {
|
||||
lua_createtable(L, cont.size(), 0);
|
||||
for(auto&& pair : cont) {
|
||||
pusher<Unqualified<decltype(pair.first)>>{}.push(L, pair.first);
|
||||
|
@ -238,9 +208,26 @@ struct pusher<table> {
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void push(lua_State *L, T&& table) {
|
||||
push_as(L, std::forward<T>(table));
|
||||
template<typename U = T, EnableIf<std::is_base_of<reference, U>> = 0>
|
||||
static void push(lua_State*, T& ref) {
|
||||
ref.push();
|
||||
}
|
||||
|
||||
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||
static void push(lua_State* L, T& t) {
|
||||
pusher<T*>{}.push(L, std::addressof(t));
|
||||
}
|
||||
|
||||
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
|
||||
static void push(lua_State* L, T&& t) {
|
||||
detail::push_userdata<U>(L, userdata_traits<T*>::metatable, std::move(t));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pusher<T*> {
|
||||
static void push(lua_State* L, T* obj) {
|
||||
detail::push_userdata<T*>(L, userdata_traits<T*>::metatable, obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -375,7 +362,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_t>(L, index++);
|
||||
voiddata[i] = get<upvalue_t>(L, index++);
|
||||
}
|
||||
return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index);
|
||||
}
|
||||
|
|
|
@ -85,8 +85,15 @@ private:
|
|||
T* obj = static_cast<T*>(udata);
|
||||
match_constructor(L, obj, syntax, argcount - static_cast<int>(syntax), typename std::common_type<TTypes>::type()...);
|
||||
|
||||
luaL_getmetatable(L, std::addressof(meta[0]));
|
||||
lua_setmetatable(L, -1);
|
||||
|
||||
if (luaL_newmetatable(L, std::addressof(meta[0])) == 1) {
|
||||
lua_pop(L, 1);
|
||||
std::string err = "Unable to get userdata metatable for ";
|
||||
err += meta;
|
||||
throw error(err);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -103,10 +110,10 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
template<std::size_t N>
|
||||
template<std::size_t N, std::size_t M>
|
||||
void build_function_tables() {}
|
||||
|
||||
template<std::size_t N, typename... Args, typename TBase, typename Ret>
|
||||
template<std::size_t N, std::size_t M, typename... Args, typename TBase, typename Ret>
|
||||
void build_function_tables(std::string funcname, Ret TBase::* func, Args&&... args) {
|
||||
static_assert(std::is_base_of<TBase, T>::value, "Any registered function must be part of the class");
|
||||
typedef typename std::decay<decltype(func)>::type function_type;
|
||||
|
@ -118,14 +125,15 @@ private:
|
|||
ptrmetafuncs.emplace_back(detail::make_unique<userdata_function<function_type, typename std::add_pointer<T>::type>>(std::move(func)));
|
||||
metafunctiontable.push_back({ name.c_str(), &base_function::userdata<N>::call });
|
||||
ptrmetafunctiontable.push_back({ name.c_str(), &base_function::userdata<N>::call });
|
||||
build_function_tables<N + 1, M>(std::forward<Args>(args)...);
|
||||
}
|
||||
else {
|
||||
funcs.emplace_back(detail::make_unique<userdata_function<function_type, T>>(std::move(func)));
|
||||
ptrfuncs.emplace_back(detail::make_unique<userdata_function<function_type, typename std::add_pointer<T>::type>>(std::move(func)));
|
||||
functiontable.push_back({ name.c_str(), &base_function::userdata<N>::call });
|
||||
ptrfunctiontable.push_back({ name.c_str(), &base_function::userdata<N>::call });
|
||||
functiontable.push_back({ name.c_str(), &base_function::userdata<M>::call });
|
||||
ptrfunctiontable.push_back({ name.c_str(), &base_function::userdata<M>::call });
|
||||
build_function_tables<N, M + 1>(std::forward<Args>(args)...);
|
||||
}
|
||||
build_function_tables<N + 1>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -146,7 +154,7 @@ public:
|
|||
ptrfuncs.reserve(sizeof...(args) + 2);
|
||||
metafuncs.reserve(sizeof...(args) + 2);
|
||||
ptrmetafuncs.reserve(sizeof...(args) + 2);
|
||||
build_function_tables<0>(std::forward<Args>(args)...);
|
||||
build_function_tables<0, 0>(std::forward<Args>(args)...);
|
||||
|
||||
functionnames.push_back("new");
|
||||
functiontable.push_back({ functionnames.back().c_str(), &constructor<CArgs...>::construct });
|
||||
|
@ -238,22 +246,24 @@ struct pusher<userdata<T>> {
|
|||
static void push_metatable(lua_State* L, Meta&& meta, Funcs&& funcs, FuncTable&& functable, MetaFuncs&& metafuncs, MetaFuncTable&& metafunctable) {
|
||||
luaL_newmetatable(L, std::addressof(meta[0]));
|
||||
// regular functions accessed through __index semantics
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -1, "__index");
|
||||
for (std::size_t u = 0; u < funcs.size(); ++u) {
|
||||
stack::push<upvalue_t>(L, funcs[ u ].get());
|
||||
stack::push<upvalue_t>(L, funcs[u].get());
|
||||
}
|
||||
luaL_setfuncs(L, functable.data(), static_cast<uint32_t>(funcs.size()));
|
||||
// meta functions
|
||||
for (std::size_t u = 0; u < metafuncs.size(); ++u) {
|
||||
stack::push<upvalue_t>(L, metafuncs[ u ].get());
|
||||
stack::push<upvalue_t>(L, metafuncs[u].get());
|
||||
}
|
||||
luaL_setfuncs(L, metafunctable.data(), static_cast<uint32_t>(metafuncs.size()));
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -1, "__index");
|
||||
}
|
||||
|
||||
static void push (lua_State* L, userdata<T>& user) {
|
||||
push_metatable(L, userdata_traits<T>::metatable, user.functions(), user.function_table(), user.meta_functions(), user.meta_function_table());
|
||||
// push pointer tables first,
|
||||
// but leave the regular T table on last so it can be linked to a type for usage with `.new(...)`
|
||||
push_metatable(L, userdata_traits<T*>::metatable, user.reference_functions(), user.reference_function_table(), user.meta_reference_functions(), user.meta_reference_function_table());
|
||||
push_metatable(L, userdata_traits<T>::metatable, user.functions(), user.function_table(), user.meta_functions(), user.meta_function_table());
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
|
|
|
@ -36,7 +36,7 @@ template<typename T>
|
|||
const std::string userdata_traits<T>::name = detail::demangle(typeid(T));
|
||||
|
||||
template<typename T>
|
||||
const std::string userdata_traits<T>::metatable = std::string("sol.stateful.").append(detail::demangle(typeid(T)));
|
||||
const std::string userdata_traits<T>::metatable = std::string("sol.").append(detail::demangle(typeid(T)));
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user