diff options
Diffstat (limited to '3rdparty/sol2/sol/usertype_metatable.hpp')
-rw-r--r-- | 3rdparty/sol2/sol/usertype_metatable.hpp | 609 |
1 files changed, 0 insertions, 609 deletions
diff --git a/3rdparty/sol2/sol/usertype_metatable.hpp b/3rdparty/sol2/sol/usertype_metatable.hpp deleted file mode 100644 index b496d388010..00000000000 --- a/3rdparty/sol2/sol/usertype_metatable.hpp +++ /dev/null @@ -1,609 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 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_USERTYPE_METATABLE_HPP -#define SOL_USERTYPE_METATABLE_HPP - -#include "wrapper.hpp" -#include "call.hpp" -#include "stack.hpp" -#include "types.hpp" -#include "stack_reference.hpp" -#include "usertype_traits.hpp" -#include "inheritance.hpp" -#include "raii.hpp" -#include "deprecate.hpp" -#include <unordered_map> -#include <cstdio> - -namespace sol { - namespace usertype_detail { - struct no_comp { - template <typename A, typename B> - bool operator()(A&&, B&&) const { - return false; - } - }; - - typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); - typedef int(*member_search)(lua_State*, void*); - - struct find_call_pair { - member_search first; - member_search second; - - find_call_pair(member_search first, member_search second) : first(first), second(second) {} - }; - - inline bool is_indexer(string_detail::string_shim s) { - return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); - } - - inline bool is_indexer(meta_function mf) { - return mf == meta_function::index || mf == meta_function::new_index; - } - - inline bool is_indexer(call_construction) { - return false; - } - - inline bool is_indexer(base_classes_tag) { - return false; - } - - inline auto make_shim(string_detail::string_shim s) { - return s; - } - - inline auto make_shim(call_construction) { - return string_detail::string_shim(name_of(meta_function::call_function)); - } - - inline auto make_shim(meta_function mf) { - return string_detail::string_shim(name_of(mf)); - } - - inline auto make_shim(base_classes_tag) { - return string_detail::string_shim(detail::base_class_cast_key()); - } - - template <typename Arg> - inline std::string make_string(Arg&& arg) { - string_detail::string_shim s = make_shim(arg); - return std::string(s.c_str(), s.size()); - } - - template <typename N> - inline luaL_Reg make_reg(N&& n, lua_CFunction f) { - luaL_Reg l{ make_shim(std::forward<N>(n)).c_str(), f }; - return l; - } - - struct registrar { - virtual int push_um(lua_State* L) = 0; - virtual ~registrar() {} - }; - - template <bool is_index> - inline int indexing_fail(lua_State* L) { - auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2); - string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); - if (is_index) - return luaL_error(L, "sol: attempt to index (get) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); - else - return luaL_error(L, "sol: attempt to index (set) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); - } - - template <bool is_index, typename Base> - static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { - if (found) - return; - const char* metakey = &usertype_traits<Base>::metatable()[0]; - const char* gcmetakey = &usertype_traits<Base>::gc_table()[0]; - const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); - - luaL_getmetatable(L, metakey); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return; - } - - stack::get_field(L, basewalkkey); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 2); - return; - } - lua_CFunction basewalkfunc = stack::pop<lua_CFunction>(L); - lua_pop(L, 1); - - stack::get_field<true>(L, gcmetakey); - int value = basewalkfunc(L); - if (value > -1) { - found = true; - ret = value; - } - } - - template <bool is_index, typename... Bases> - static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { - (void)L; - (void)found; - (void)ret; - (void)accessor; - (void)detail::swallow{ 0, (walk_single_base<is_index, Bases>(L, found, ret, accessor), 0)... }; - } - - template <typename T, typename Op> - inline int operator_wrap(lua_State* L) { - auto maybel = stack::check_get<T>(L, 1); - if (maybel) { - auto mayber = stack::check_get<T>(L, 2); - if (mayber) { - auto& l = *maybel; - auto& r = *mayber; - if (std::is_same<no_comp, Op>::value) { - return stack::push(L, detail::ptr(l) == detail::ptr(r)); - } - else { - Op op; - return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); - } - } - } - return stack::push(L, false); - } - - template <typename T, typename Op, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler> - inline void make_reg_op(Regs& l, int& index, const char* name) { - l[index] = { name, &operator_wrap<T, Op> }; - ++index; - } - - template <typename T, typename Op, typename Supports, typename Regs, meta::disable<Supports> = meta::enabler> - inline void make_reg_op(Regs&, int&, const char*) { - // Do nothing if there's no support - } - - struct add_destructor_tag {}; - struct check_destructor_tag {}; - struct verified_tag {} const verified{}; - - template <typename T> - struct is_non_factory_constructor : std::false_type {}; - - template <typename... Args> - struct is_non_factory_constructor<constructors<Args...>> : std::true_type {}; - - template <typename... Args> - struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {}; - - template <> - struct is_non_factory_constructor<no_construction> : std::true_type {}; - - template <typename T> - struct is_constructor : is_non_factory_constructor<T> {}; - - template <typename... Args> - struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; - - template <typename... Args> - using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; - - template <typename T> - struct is_destructor : std::false_type {}; - - template <typename Fx> - struct is_destructor<destructor_wrapper<Fx>> : std::true_type {}; - - template <typename... Args> - using has_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>; - - } // usertype_detail - - template <typename T> - struct clean_type { - typedef std::conditional_t<std::is_array<meta::unqualified_t<T>>::value, T&, std::decay_t<T>> type; - }; - - template <typename T> - using clean_type_t = typename clean_type<T>::type; - - template <typename T, typename IndexSequence, typename... Tn> - struct usertype_metatable : usertype_detail::registrar {}; - - template <typename T, std::size_t... I, typename... Tn> - struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_detail::registrar { - typedef std::make_index_sequence<sizeof...(I) * 2> indices; - typedef std::index_sequence<I...> half_indices; - typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 3> regs_t; - typedef std::tuple<Tn...> RawTuple; - typedef std::tuple<clean_type_t<Tn> ...> Tuple; - template <std::size_t Idx> - struct check_binding : is_variable_binding<meta::unqualified_tuple_element_t<Idx, Tuple>> {}; - typedef std::unordered_map<std::string, usertype_detail::find_call_pair> mapping_t; - Tuple functions; - mapping_t mapping; - lua_CFunction indexfunc; - lua_CFunction newindexfunc; - lua_CFunction destructfunc; - lua_CFunction callconstructfunc; - lua_CFunction indexbase; - lua_CFunction newindexbase; - usertype_detail::base_walk indexbaseclasspropogation; - usertype_detail::base_walk newindexbaseclasspropogation; - void* baseclasscheck; - void* baseclasscast; - bool mustindex; - bool secondarymeta; - bool hasequals; - bool hasless; - bool haslessequals; - - template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> - inline lua_CFunction make_func() { - return std::get<Idx + 1>(functions); - } - - template <std::size_t Idx, meta::disable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> - inline lua_CFunction make_func() { - return call<Idx + 1>; - } - - static bool contains_variable() { - typedef meta::any<check_binding<(I * 2 + 1)>...> has_variables; - return has_variables::value; - } - - bool contains_index() const { - bool idx = false; - (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get<I * 2>(functions))), 0) ... }; - return idx; - } - - int finish_regs(regs_t& l, int& index) { - if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); - usertype_detail::make_reg_op<T, std::less<>, meta::supports_op_less<T>>(l, index, name); - } - if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); - usertype_detail::make_reg_op<T, std::less_equal<>, meta::supports_op_less_equal<T>>(l, index, name); - } - if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); - usertype_detail::make_reg_op<T, std::conditional_t<meta::supports_op_equal<T>::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); - } - if (destructfunc != nullptr) { - l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; - ++index; - } - return index; - } - - template <std::size_t Idx, typename F> - void make_regs(regs_t&, int&, call_construction, F&&) { - callconstructfunc = call<Idx + 1>; - secondarymeta = true; - } - - template <std::size_t, typename... Bases> - void make_regs(regs_t&, int&, base_classes_tag, bases<Bases...>) { - if (sizeof...(Bases) < 1) { - return; - } - mustindex = true; - (void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... }; - - 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...>::type_check; - baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast; - indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; - newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; - } - - template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>> - void make_regs(regs_t& l, int& index, N&& n, F&&) { - if (is_variable_binding<meta::unqualified_t<F>>::value) { - return; - } - luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>()); - // Returnable scope - // That would be a neat keyword for C++ - // returnable { ... }; - if (reg.name == name_of(meta_function::equal_to)) { - hasequals = true; - } - if (reg.name == name_of(meta_function::less_than)) { - hasless = true; - } - if (reg.name == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - if (reg.name == name_of(meta_function::garbage_collect)) { - destructfunc = reg.func; - return; - } - else if (reg.name == name_of(meta_function::index)) { - indexfunc = reg.func; - mustindex = true; - return; - } - else if (reg.name == name_of(meta_function::new_index)) { - newindexfunc = reg.func; - mustindex = true; - return; - } - l[index] = reg; - ++index; - } - - template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == sizeof...(Tn)>> - usertype_metatable(Args&&... args) : functions(std::forward<Args>(args)...), - mapping(), - indexfunc(usertype_detail::indexing_fail<true>), newindexfunc(usertype_detail::indexing_fail<false>), - destructfunc(nullptr), callconstructfunc(nullptr), - indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), - indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), - baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()), - hasequals(false), hasless(false), haslessequals(false) { - std::initializer_list<typename mapping_t::value_type> ilist{ { - std::pair<std::string, usertype_detail::find_call_pair>( - usertype_detail::make_string(std::get<I * 2>(functions)), - usertype_detail::find_call_pair(&usertype_metatable::real_find_call<I * 2, I * 2 + 1, false>, - &usertype_metatable::real_find_call<I * 2, I * 2 + 1, true>) - ) - }... }; - mapping.insert(ilist); - } - - template <std::size_t I0, std::size_t I1, bool is_index> - static int real_find_call(lua_State* L, void* um) { - auto& f = *static_cast<usertype_metatable*>(um); - if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) { - return real_call_with<I1, is_index, true>(L, f); - } - return stack::push(L, c_closure(call<I1, is_index>, stack::push(L, light<usertype_metatable>(f)))); - } - - template <bool is_index, bool toplevel = false> - static int core_indexing_call(lua_State* L) { - usertype_metatable& f = toplevel ? stack::get<light<usertype_metatable>>(L, upvalue_index(1)) : stack::pop<light<usertype_metatable>>(L); - static const int keyidx = -2 + static_cast<int>(is_index); - if (toplevel && stack::get<type>(L, keyidx) != type::string) { - return is_index ? f.indexfunc(L) : f.newindexfunc(L); - } - std::string name = stack::get<std::string>(L, keyidx); - auto memberit = f.mapping.find(name); - if (memberit != f.mapping.cend()) { - auto& member = is_index ? memberit->second.second : memberit->second.first; - return (member)(L, static_cast<void*>(&f)); - } - string_detail::string_shim accessor = name; - int ret = 0; - bool found = false; - // Otherwise, we need to do propagating calls through the bases - if (is_index) - f.indexbaseclasspropogation(L, found, ret, accessor); - else - f.newindexbaseclasspropogation(L, found, ret, accessor); - if (found) { - return ret; - } - return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; - } - - static int real_index_call(lua_State* L) { - return core_indexing_call<true, true>(L); - } - - static int real_new_index_call(lua_State* L) { - return core_indexing_call<false, true>(L); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int real_call(lua_State* L) { - usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(1)); - return real_call_with<Idx, is_index, is_variable>(L, f); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int real_call_with(lua_State* L, usertype_metatable& um) { - typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K; - typedef meta::unqualified_tuple_element_t<Idx, Tuple> F; - static const int boost = - !usertype_detail::is_non_factory_constructor<F>::value - && std::is_same<K, call_construction>::value ? - 1 : 0; - auto& f = std::get<Idx>(um.functions); - return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call<Idx, is_index, is_variable>)>(L); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int call_with(lua_State* L) { - return detail::static_trampoline<(&real_call_with<Idx, is_index, is_variable>)>(L); - } - - static int index_call(lua_State* L) { - return detail::static_trampoline<(&real_index_call)>(L); - } - - static int new_index_call(lua_State* L) { - return detail::static_trampoline<(&real_new_index_call)>(L); - } - - virtual int push_um(lua_State* L) override { - return stack::push(L, std::move(*this)); - } - - ~usertype_metatable() override { - - } - }; - - namespace stack { - - template <typename T, std::size_t... I, typename... Args> - struct pusher<usertype_metatable<T, std::index_sequence<I...>, Args...>> { - typedef usertype_metatable<T, std::index_sequence<I...>, Args...> umt_t; - typedef typename umt_t::regs_t regs_t; - - static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { - // ensure some sort of uniqueness - static int uniqueness = 0; - std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); - // std::to_string doesn't exist in android still, with NDK, so this bullshit - // is necessary - // thanks, Android :v - int appended = snprintf(nullptr, 0, "%d", uniqueness); - std::size_t insertionpoint = uniquegcmetakey.length() - 1; - uniquegcmetakey.append(appended, '\0'); - char* uniquetarget = &uniquegcmetakey[insertionpoint]; - snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); - ++uniqueness; - - const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; - // Make sure userdata's memory is properly in lua first, - // otherwise all the light userdata we make later will become invalid - stack::push_specific<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx)); - // Create the top level thing that will act as our deleter later on - stack_reference umt(L, -1); - stack::set_field<true>(L, gcmetakey, umt); - umt.pop(); - - stack::get_field<true>(L, gcmetakey); - return stack::pop<light<umt_t>>(L); - } - - static int push(lua_State* L, umt_t&& umx) { - - umt_t& um = make_cleanup(L, std::move(umx)); - regs_t value_table{ {} }; - int lastreg = 0; - (void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... }; - um.finish_regs(value_table, lastreg); - value_table[lastreg] = { nullptr, nullptr }; - regs_t ref_table = value_table; - regs_t unique_table = value_table; - bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; - if (hasdestructor) { - ref_table[lastreg - 1] = { nullptr, nullptr }; - unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> }; - } - - // Now use um - const bool& mustindex = um.mustindex; - for (std::size_t i = 0; i < 3; ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - luaL_Reg* metaregs = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - metaregs = ref_table.data(); - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - metaregs = unique_table.data(); - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - metaregs = value_table.data(); - break; - } - luaL_newmetatable(L, metakey); - stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, metaregs, 1); - - if (um.baseclasscheck != nullptr) { - stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); - } - if (um.baseclasscast != nullptr) { - stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); - } - - stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um)), t.stack_index()); - stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um)), t.stack_index()); - - if (mustindex) { - // Basic index pushing: specialize - // index and newindex to give variables and stuff - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), t.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), t.stack_index()); - } - else { - // If there's only functions, we can use the fast index version - stack::set_field(L, meta_function::index, t, t.stack_index()); - } - // metatable on the metatable - // for call constructor purposes and such - lua_createtable(L, 0, 3); - stack_reference metabehind(L, -1); - if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - // We want to just leave the table - // in the registry only, otherwise we return it - t.pop(); - } - - // Now for the shim-table that actually gets assigned to the name - luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); - stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, value_table.data(), 1); - { - lua_createtable(L, 0, 3); - stack_reference metabehind(L, -1); - if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - } - - return 1; - } - }; - - } // stack - -} // sol - -#endif // SOL_USERTYPE_METATABLE_HPP |