diff options
author | 2016-11-06 10:05:36 +0100 | |
---|---|---|
committer | 2016-11-06 10:05:36 +0100 | |
commit | c2a75cb1799a31aa5687e576d1c0bdd50825fded (patch) | |
tree | 59144f444d666ae20ac8fb2bc4e4553d330945ca /3rdparty/sol2/sol | |
parent | fffd464d345a6368cda7d90945d3409151218a06 (diff) |
Updated sol2, made lua console not crash for nil data (nw)
Diffstat (limited to '3rdparty/sol2/sol')
-rw-r--r-- | 3rdparty/sol2/sol/call.hpp | 57 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/compatibility/5.1.0.h | 2 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/compatibility/5.2.0.h | 43 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/compatibility/5.x.x.inl | 1 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/container_usertype_metatable.hpp | 259 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/error.hpp | 1 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/load_result.hpp | 2 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/object.hpp | 2 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/optional.hpp | 3 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/optional_implementation.hpp | 1127 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/proxy.hpp | 12 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/simple_usertype_metatable.hpp | 163 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/stack_check.hpp | 65 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/stack_get.hpp | 38 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/stack_push.hpp | 18 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/state.hpp | 8 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/state_view.hpp | 30 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/table_core.hpp | 3 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/types.hpp | 20 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/usertype_metatable.hpp | 37 | ||||
-rw-r--r-- | 3rdparty/sol2/sol/usertype_traits.hpp | 44 |
21 files changed, 1704 insertions, 231 deletions
diff --git a/3rdparty/sol2/sol/call.hpp b/3rdparty/sol2/sol/call.hpp index 0abeeefaa18..9f6a3af8c4c 100644 --- a/3rdparty/sol2/sol/call.hpp +++ b/3rdparty/sol2/sol/call.hpp @@ -57,7 +57,7 @@ namespace sol { template <typename Fx, std::size_t I, typename... R, typename... Args> int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const { detail::default_construct func{}; - return stack::call_into_lua<false>(r, a, L, start, func, obj); + return stack::call_into_lua<stack::stack_detail::default_check_arguments>(r, a, L, start, func, obj); } }; @@ -85,11 +85,50 @@ namespace sol { } return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); } + + template <std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + + template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; + typedef meta::tuple_types<typename traits::return_type> return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { + return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + if (traits::free_arity != fxarity) { + return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); + } + + template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; + typedef meta::tuple_types<typename traits::return_type> return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { + return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + if (traits::free_arity != fxarity) { + return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + stack::record tracking{}; + if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); + } } // overload_detail template <typename... Functions, typename Match, typename... Args> inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_detail::overload_match_arity(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); } template <typename... Functions, typename Match, typename... Args> @@ -106,9 +145,9 @@ namespace sol { template <typename T, typename... TypeLists> inline int construct(lua_State* L) { - static const auto& meta = usertype_traits<T>::metatable; + static const auto& meta = usertype_traits<T>::metatable(); int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot; argcount -= static_cast<int>(syntax); T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); @@ -344,9 +383,9 @@ namespace sol { typedef constructor_list<Args...> F; static int call(lua_State* L, F&) { - const auto& metakey = usertype_traits<T>::metatable; + const auto& metakey = usertype_traits<T>::metatable(); int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot; argcount -= static_cast<int>(syntax); T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); @@ -376,7 +415,7 @@ namespace sol { struct onmatch { template <typename Fx, std::size_t I, typename... R, typename... Args> int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) { - const auto& metakey = usertype_traits<T>::metatable; + const auto& metakey = usertype_traits<T>::metatable(); T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); reference userdataref(L, -1); T*& referencepointer = *pointerpointer; @@ -391,7 +430,7 @@ namespace sol { if (type_of(L, -1) == type::nil) { lua_pop(L, 1); std::string err = "sol: unable to get usertype metatable for "; - err += usertype_traits<T>::name; + err += usertype_traits<T>::name(); return luaL_error(L, err.c_str()); } lua_setmetatable(L, -2); @@ -401,7 +440,7 @@ namespace sol { }; static int call(lua_State* L, F& f) { - call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable); + call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0]); int syntaxval = static_cast<int>(syntax); int argcount = lua_gettop(L) - syntaxval; return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f); diff --git a/3rdparty/sol2/sol/compatibility/5.1.0.h b/3rdparty/sol2/sol/compatibility/5.1.0.h index 0050b24eca4..7484aedf18f 100644 --- a/3rdparty/sol2/sol/compatibility/5.1.0.h +++ b/3rdparty/sol2/sol/compatibility/5.1.0.h @@ -158,7 +158,7 @@ inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t* return ls->s; } -#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 020100) <= 0) +#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 20100) <= 0) // Luajit 2.1.0 has this function already inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { diff --git a/3rdparty/sol2/sol/compatibility/5.2.0.h b/3rdparty/sol2/sol/compatibility/5.2.0.h new file mode 100644 index 00000000000..7068f2a3291 --- /dev/null +++ b/3rdparty/sol2/sol/compatibility/5.2.0.h @@ -0,0 +1,43 @@ +// 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_5_2_0_H +#define SOL_5_2_0_H +#include "version.hpp" + +#if SOL_LUA_VERSION < 503 + +inline int lua_isinteger(lua_State* L, int idx) { + if (lua_type(L, idx) != LUA_TNUMBER) + return 0; + // This is a very slipshod way to do the testing + // but lua_totingerx doesn't play ball nicely + // on older versions... + lua_Number n = lua_tonumber(L, idx); + lua_Integer i = lua_tointeger(L, idx); + if (i != n) + return 0; + // it's DEFINITELY an integer + return 1; +} + +#endif // SOL_LUA_VERSION == 502 +#endif // SOL_5_2_0_H diff --git a/3rdparty/sol2/sol/compatibility/5.x.x.inl b/3rdparty/sol2/sol/compatibility/5.x.x.inl index 1d420e3f3f6..17bab23cb57 100644 --- a/3rdparty/sol2/sol/compatibility/5.x.x.inl +++ b/3rdparty/sol2/sol/compatibility/5.x.x.inl @@ -23,6 +23,7 @@ #define SOL_5_X_X_INL #include "version.hpp" +#include "5.2.0.h" #include "5.1.0.h" #include "5.0.0.h" #include "5.x.x.h" diff --git a/3rdparty/sol2/sol/container_usertype_metatable.hpp b/3rdparty/sol2/sol/container_usertype_metatable.hpp index a07b85be851..268f8db1616 100644 --- a/3rdparty/sol2/sol/container_usertype_metatable.hpp +++ b/3rdparty/sol2/sol/container_usertype_metatable.hpp @@ -42,6 +42,19 @@ namespace sol { }; template <typename T> + struct has_push_back { + private: + typedef std::array<char, 1> one; + typedef std::array<char, 2> two; + + template <typename C> static one test(decltype(&C::push_back)); + template <typename C> static two test(...); + + public: + static const bool value = sizeof(test<T>(0)) == sizeof(char); + }; + + template <typename T> T& get_first(const T& t) { return std::forward<T>(t); } @@ -96,58 +109,65 @@ namespace sol { static int real_index_call(lua_State* L) { auto& src = get_src(L); -#ifdef SOL_SAFE_USERTYPE auto maybek = stack::check_get<K>(L, 2); if (maybek) { using std::begin; auto it = begin(src); K k = *maybek; - if (k <= src.size() && k > 0) { - --k; - std::advance(it, k); - return stack::push_reference(L, *it); +#ifdef SOL_SAFE_USERTYPE + if (k > src.size() || k < 1) { + return stack::push(L, nil); } - } - return stack::push(L, nil); #else - using std::begin; - auto it = begin(src); - K k = stack::get<K>(L, 2); - --k; - std::advance(it, k); - return stack::push_reference(L, *it); #endif // Safety + --k; + std::advance(it, k); + return stack::push_reference(L, *it); + } + else { + auto maybename = stack::check_get<string_detail::string_shim>(L, 2); + if (maybename) { + auto& name = *maybename; + if (name == "add") { + return stack::push(L, &add_call); + } + else if (name == "insert") { + return stack::push(L, &insert_call); + } + else if (name == "clear") { + return stack::push(L, &clear_call); + } + } + } + + return stack::push(L, nil); } - template <bool b, meta::disable<meta::boolean<b>> = meta::enabler> - static int real_new_index_call_const(std::integral_constant<bool, b>, lua_State* L) { + static int real_new_index_call_const(std::false_type, lua_State* L) { luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); return 0; } - template <bool b, meta::enable<meta::boolean<b>> = meta::enabler> - static int real_new_index_call_const(std::integral_constant<bool, b>, lua_State* L) { + static int real_new_index_call_const(std::true_type, lua_State* L) { auto& src = get_src(L); #ifdef SOL_SAFE_USERTYPE auto maybek = stack::check_get<K>(L, 2); - if (maybek) { - K k = *maybek; - if (k <= src.size() && k > 0) { - --k; - using std::begin; - auto it = begin(src); - std::advance(it, k); - *it = stack::get<V>(L, 3); - } + if (!maybek) { + return stack::push(L, nil); } + K k = *maybek; #else + K k = stack::get<K>(L, 2); +#endif using std::begin; auto it = begin(src); - K k = stack::get<K>(L, 2); + if (k == src.size()) { + real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src, 1); + return 0; + } --k; std::advance(it, k); *it = stack::get<V>(L, 3); -#endif return 0; } @@ -183,13 +203,22 @@ namespace sol { return stack::push(L, src.size()); } -#if 0 - static int real_push_back_call(lua_State*L) { - auto& src = get_src(L); - src.push_back(stack::get<V>(L, 2)); + static int real_add_call_push(std::true_type, lua_State*L, T& src, int boost = 0) { + src.push_back(stack::get<V>(L, 2 + boost)); + return 0; + } + + static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) { + using std::end; + src.insert(end(src), stack::get<V>(L, 2 + boost)); return 0; } + static int real_add_call(lua_State*L) { + auto& src = get_src(L); + return real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src); + } + static int real_insert_call(lua_State*L) { using std::begin; auto& src = get_src(L); @@ -197,14 +226,23 @@ namespace sol { return 0; } - static int push_back_call(lua_State*L) { - return detail::static_trampoline<(&real_length_call)>(L); + static int real_clear_call(lua_State*L) { + auto& src = get_src(L); + src.clear(); + return 0; + } + + static int add_call(lua_State*L) { + return detail::static_trampoline<(&real_add_call)>(L); } static int insert_call(lua_State*L) { return detail::static_trampoline<(&real_insert_call)>(L); } -#endif // Sometime later, in a distant universe... + + static int clear_call(lua_State*L) { + return detail::static_trampoline<(&real_clear_call)>(L); + } static int length_call(lua_State*L) { return detail::static_trampoline<(&real_length_call)>(L); @@ -254,9 +292,9 @@ namespace sol { } static int real_index_call(lua_State* L) { - auto& src = get_src(L); auto k = stack::check_get<K>(L, 2); if (k) { + auto& src = get_src(L); using std::end; auto it = detail::find(src, *k); if (it != end(src)) { @@ -264,6 +302,21 @@ namespace sol { return stack::push_reference(L, v.second); } } + else { + auto maybename = stack::check_get<string_detail::string_shim>(L, 2); + if (maybename) { + auto& name = *maybename; + if (name == "add") { + return stack::push(L, &add_call); + } + else if (name == "insert") { + return stack::push(L, &insert_call); + } + else if (name == "clear") { + return stack::push(L, &clear_call); + } + } + } return stack::push(L, nil); } @@ -298,11 +351,12 @@ namespace sol { iter& i = stack::get<user<iter>>(L, 1); auto& source = i.source; auto& it = i.it; - std::advance(it, 1); if (it == end(source)) { return 0; } - return stack::multi_push_reference(L, it->first, it->second); + int p = stack::multi_push_reference(L, it->first, it->second); + std::advance(it, 1); + return p; } static int real_pairs_call(lua_State* L) { @@ -319,6 +373,28 @@ namespace sol { return stack::push(L, src.size()); } + static int real_insert_call(lua_State*L) { + return real_new_index_call(L); + } + + static int real_clear_call(lua_State*L) { + auto& src = get_src(L); + src.clear(); + return 0; + } + + static int add_call(lua_State*L) { + return detail::static_trampoline<(&real_insert_call)>(L); + } + + static int insert_call(lua_State*L) { + return detail::static_trampoline<(&real_insert_call)>(L); + } + + static int clear_call(lua_State*L) { + return detail::static_trampoline<(&real_clear_call)>(L); + } + static int length_call(lua_State*L) { return detail::static_trampoline<(&real_length_call)>(L); } @@ -341,67 +417,80 @@ namespace sol { }; namespace stack { + namespace stack_detail { + template <typename T> + inline auto container_metatable() { + typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt; + std::array<luaL_Reg, 10> reg = { { + { "__index", &meta_cumt::index_call }, + { "__newindex", &meta_cumt::new_index_call }, + { "__pairs", &meta_cumt::pairs_call }, + { "__ipairs", &meta_cumt::pairs_call }, + { "__len", &meta_cumt::length_call }, + { "clear", &meta_cumt::clear_call }, + { "insert", &meta_cumt::insert_call }, + { "add", &meta_cumt::add_call }, + std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy<T> }, + { nullptr, nullptr } + } }; + return reg; + } - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<meta::has_begin_end<T>, meta::neg<meta::any<std::is_base_of<reference, T>, std::is_base_of<stack_reference, T>>>>::value>> { - typedef container_usertype_metatable<T> cumt; - static int push(lua_State* L, const T& cont) { - auto fx = [&L]() { - const char* metakey = &usertype_traits<T>::metatable[0]; + template <typename T> + inline auto container_metatable_behind() { + typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt; + std::array<luaL_Reg, 3> reg = { { + { "__index", &meta_cumt::index_call }, + { "__newindex", &meta_cumt::new_index_call }, + { nullptr, nullptr } + } }; + return reg; + } + + template <typename T> + struct metatable_setup { + lua_State* L; + + metatable_setup(lua_State* L) : L(L) {} + + void operator()() { + static const auto reg = container_metatable<T>(); + static const auto containerreg = container_metatable_behind<T>(); + static const char* metakey = &usertype_traits<T>::metatable()[0]; + if (luaL_newmetatable(L, metakey) == 1) { - luaL_Reg reg[] = { - { "__index", &cumt::index_call }, - { "__newindex", &cumt::new_index_call }, - { "__pairs", &cumt::pairs_call }, - { "__len", &cumt::length_call }, - { "__gc", &detail::usertype_alloc_destroy<T> }, - { nullptr, nullptr } - }; - luaL_setfuncs(L, reg, 0); + stack_reference metatable(L, -1); + luaL_setfuncs(L, reg.data(), 0); + + lua_createtable(L, 0, static_cast<int>(containerreg.size())); + stack_reference metabehind(L, -1); + luaL_setfuncs(L, containerreg.data(), 0); + + stack::set_field(L, metatable_key, metabehind, metatable.stack_index()); + metabehind.pop(); } lua_setmetatable(L, -2); - }; + } + }; + } + + template<typename T> + struct pusher<T, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { + static int push(lua_State* L, const T& cont) { + stack_detail::metatable_setup<T> fx(L); return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, cont); } static int push(lua_State* L, T&& cont) { - auto fx = [&L]() { - const char* metakey = &usertype_traits<T>::metatable[0]; - if (luaL_newmetatable(L, metakey) == 1) { - luaL_Reg reg[] = { - { "__index", &cumt::index_call }, - { "__newindex", &cumt::new_index_call }, - { "__pairs", &cumt::pairs_call }, - { "__len", &cumt::length_call }, - { "__gc", &detail::usertype_alloc_destroy<T> }, - { nullptr, nullptr } - }; - luaL_setfuncs(L, reg, 0); - } - lua_setmetatable(L, -2); - }; + stack_detail::metatable_setup<T> fx(L); return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::move(cont)); } }; template<typename T> - struct pusher<T*, std::enable_if_t<meta::all<meta::has_begin_end<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - typedef container_usertype_metatable<T> cumt; + struct pusher<T*, std::enable_if_t<meta::all<is_container<T>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { static int push(lua_State* L, T* cont) { - auto fx = [&L]() { - const char* metakey = &usertype_traits<meta::unqualified_t<T>*>::metatable[0]; - if (luaL_newmetatable(L, metakey) == 1) { - luaL_Reg reg[] = { - { "__index", &cumt::index_call }, - { "__newindex", &cumt::new_index_call }, - { "__pairs", &cumt::pairs_call }, - { "__len", &cumt::length_call }, - { nullptr, nullptr } - }; - luaL_setfuncs(L, reg, 0); - } - lua_setmetatable(L, -2); - }; + stack_detail::metatable_setup<T*> fx(L); return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont); } }; diff --git a/3rdparty/sol2/sol/error.hpp b/3rdparty/sol2/sol/error.hpp index 0458e0a5f65..e24861effe9 100644 --- a/3rdparty/sol2/sol/error.hpp +++ b/3rdparty/sol2/sol/error.hpp @@ -37,6 +37,7 @@ namespace sol { std::string w; public: error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} + error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {} error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} diff --git a/3rdparty/sol2/sol/load_result.hpp b/3rdparty/sol2/sol/load_result.hpp index 1a91cc6f3dc..0f465a2bc5a 100644 --- a/3rdparty/sol2/sol/load_result.hpp +++ b/3rdparty/sol2/sol/load_result.hpp @@ -119,7 +119,7 @@ namespace sol { template<typename... Ret, typename... Args> decltype(auto) call(Args&&... args) { - return get<function>().template call<Ret...>(std::forward<Args>(args)...); + return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...); } template<typename... Args> diff --git a/3rdparty/sol2/sol/object.hpp b/3rdparty/sol2/sol/object.hpp index 42b46f9c41e..87d8f229b5d 100644 --- a/3rdparty/sol2/sol/object.hpp +++ b/3rdparty/sol2/sol/object.hpp @@ -22,11 +22,11 @@ #ifndef SOL_OBJECT_HPP #define SOL_OBJECT_HPP -#include "optional.hpp" #include "reference.hpp" #include "stack.hpp" #include "userdata.hpp" #include "variadic_args.hpp" +#include "optional.hpp" namespace sol { diff --git a/3rdparty/sol2/sol/optional.hpp b/3rdparty/sol2/sol/optional.hpp index 823bdc3d5c3..16f805e4ebf 100644 --- a/3rdparty/sol2/sol/optional.hpp +++ b/3rdparty/sol2/sol/optional.hpp @@ -22,11 +22,12 @@ #ifndef SOL_OPTIONAL_HPP #define SOL_OPTIONAL_HPP +#include "compatibility.hpp" #include "in_place.hpp" #if defined(SOL_USE_BOOST) #include <boost/optional.hpp> #else -#include "../Optional/optional.hpp" +#include "optional_implementation.hpp" #endif // Boost vs. Better optional namespace sol { diff --git a/3rdparty/sol2/sol/optional_implementation.hpp b/3rdparty/sol2/sol/optional_implementation.hpp new file mode 100644 index 00000000000..374b80e7c36 --- /dev/null +++ b/3rdparty/sol2/sol/optional_implementation.hpp @@ -0,0 +1,1127 @@ +// 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. + +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP +# define SOL_OPTIONAL_IMPLEMENTATION_HPP + +# include <utility> +# include <type_traits> +# include <initializer_list> +# include <cassert> +# include <functional> +# include <string> +# include <stdexcept> +#ifdef SOL_NO_EXCEPTIONS +#include <cstdlib> +#endif // Exceptions + +# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __GNUC__ // NOTE: GNUC is also defined for Clang +# if (__GNUC__ >= 5) +# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# endif +# endif +# +# if defined __clang_major__ +# if (__clang_major__ == 3 && __clang_minor__ >= 5) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# elif (__clang_major__ > 3) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# endif +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# endif +# endif +# +# if defined _MSC_VER +# if (_MSC_VER >= 1900) +# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# endif +# endif + +# if defined __clang__ +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif + + +# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +# else +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +# define OPTIONAL_CONSTEXPR_INIT_LIST +# endif + +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) +# define OPTIONAL_HAS_MOVE_ACCESSORS 1 +# else +# define OPTIONAL_HAS_MOVE_ACCESSORS 0 +# endif + +# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +# if (defined __cplusplus) && (__cplusplus == 201103L) +# define OPTIONAL_MUTABLE_CONSTEXPR +# else +# define OPTIONAL_MUTABLE_CONSTEXPR constexpr +# endif + +namespace sol { + + // BEGIN workaround for missing is_trivially_destructible +# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it: it is already there +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + template <typename T> + using is_trivially_destructible = ::std::has_trivial_destructor<T>; +# endif + // END workaround for missing is_trivially_destructible + +# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + + +// workaround for missing traits in GCC and CLANG + template <class T> + struct is_nothrow_move_constructible + { + constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value; + }; + + + template <class T, class U> + struct is_assignable + { + template <class X, class Y> + constexpr static bool has_assign(...) { return false; } + + template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) > + // the comma operator is necessary for the cases where operator= returns void + constexpr static bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign<T, U>(true); + }; + + + template <class T> + struct is_nothrow_move_assignable + { + template <class X, bool has_any_move_assign> + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template <class X> + struct has_nothrow_move_assign<X, true> { + constexpr static bool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>()); + }; + + constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; + }; + // end workaround + + +# endif + + + +// 20.5.4, optional for object types + template <class T> class optional; + + // 20.5.5, optional for lvalue reference types + template <class T> class optional<T&>; + + + // workaround: std utility functions aren't constexpr yet + template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept + { + return static_cast<T&&>(t); + } + + template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept + { + static_assert(!::std::is_lvalue_reference<T>::value, "!!"); + return static_cast<T&&>(t); + } + + template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept + { + return static_cast<typename ::std::remove_reference<T>::type&&>(t); + } + + +#if defined NDEBUG +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#endif + + + namespace detail_ + { + + // static_addressof: a constexpr version of addressof + template <typename T> + struct has_overloaded_addressof + { + template <class X> + constexpr static bool has_overload(...) { return false; } + + template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) > + constexpr static bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload<T>(true); + }; + + template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> + constexpr T* static_addressof(T& ref) + { + return &ref; + } + + template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> + T* static_addressof(T& ref) + { + return ::std::addressof(ref); + } + + + // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A + template <class U> + constexpr U convert(U v) { return v; } + + } // namespace detail_ + + constexpr struct trivial_init_t {} trivial_init{}; + + // 20.5.7, Disengaged state indicator + struct nullopt_t + { + struct init {}; + constexpr explicit nullopt_t(init) {} + }; + constexpr nullopt_t nullopt{ nullopt_t::init() }; + + + // 20.5.8, class bad_optional_access + class bad_optional_access : public ::std::logic_error { + public: + explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {} + explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {} + }; + + + template <class T> + struct optional_base + { + bool init_; + char storage_[sizeof(T)]; + + constexpr optional_base() noexcept : init_(false), storage_() {}; + + explicit optional_base(const T& v) : init_(true), storage_() { + new (&storage())T(v); + } + + explicit optional_base(T&& v) : init_(true), storage_() { + new (&storage())T(constexpr_move(v)); + } + + template <class... Args> explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward<Args>(args)...); + } + + template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> + explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward<Args>(args)...); + } +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return *reinterpret_cast<T*>(&storage_[0]); + } + + constexpr const T& storage() const { + return *reinterpret_cast<T const*>(&storage_[0]); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~optional_base() { if (init_) { storage().T::~T(); } } + }; + +#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ + // Sorry, GCC 4.x; you're just a piece of shit + template <typename T> + using constexpr_optional_base = optional_base<T>; +#else + template <class T> + struct constexpr_optional_base + { + bool init_; + char storage_[sizeof(T)]; + constexpr constexpr_optional_base() noexcept : init_(false), storage_() {} + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() { + new (&storage())T(v); + } + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() { + new (&storage())T(constexpr_move(v)); + } + + template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward<Args>(args)...); + } + + template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward<Args>(args)...); + } + +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return (*reinterpret_cast<T*>(&storage_[0])); + } + + constexpr const T& storage() const { + return (*reinterpret_cast<T const*>(&storage_[0])); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~constexpr_optional_base() = default; + }; +#endif + + template <class T> + using OptionalBase = typename ::std::conditional< + ::std::is_trivially_destructible<T>::value, + constexpr_optional_base<typename ::std::remove_const<T>::type>, + optional_base<typename ::std::remove_const<T>::type> + >::type; + + + + template <class T> + class optional : private OptionalBase<T> + { + static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T"); + static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T"); + + + constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; } + typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); } + constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); } +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); } + OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); } +# else + T& contained_val() & { return OptionalBase<T>::storage(); } + T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); } +# endif +# else + constexpr const T& contained_val() const { return OptionalBase<T>::storage(); } + T& contained_val() { return OptionalBase<T>::storage(); } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase<T>::init_ = false; + } + + template <class... Args> + void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...))) + { + assert(!OptionalBase<T>::init_); + ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...); + OptionalBase<T>::init_ = true; + } + + template <class U, class... Args> + void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...))) + { + assert(!OptionalBase<T>::init_); + ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...); + OptionalBase<T>::init_ = true; + } + + public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase<T>() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {}; + + optional(const optional& rhs) + : OptionalBase<T>() + { + if (rhs.initialized()) { + ::new (static_cast<void*>(dataptr())) T(*rhs); + OptionalBase<T>::init_ = true; + } + } + + optional(const optional<T&>& rhs) : optional() + { + if (rhs) { + ::new (static_cast<void*>(dataptr())) T(*rhs); + OptionalBase<T>::init_ = true; + } + } + + + optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value) + : OptionalBase<T>() + { + if (rhs.initialized()) { + ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs)); + OptionalBase<T>::init_ = true; + } + } + + constexpr optional(const T& v) : OptionalBase<T>(v) {} + + constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {} + + template <class... Args> + explicit constexpr optional(in_place_t, Args&&... args) + : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {} + + template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args) + : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {} + + // 20.5.4.2, Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs); + return *this; + } + + template <class U> + auto operator=(U&& v) + -> typename ::std::enable_if + < + ::std::is_same<typename ::std::decay<U>::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = ::std::forward<U>(v); } + else { initialize(::std::forward<U>(v)); } + return *this; + } + + + template <class... Args> + void emplace(Args&&... args) + { + clear(); + initialize(::std::forward<Args>(args)...); + } + + template <class U, class... Args> + void emplace(::std::initializer_list<U> il, Args&&... args) + { + clear(); + initialize<U, Args...>(il, ::std::forward<Args>(args)...); + } + + // 20.5.4.4, Swap + void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5, Observers + + explicit constexpr operator bool() const noexcept { return initialized(); } + + constexpr T const* operator ->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { + assert(initialized()); + return dataptr(); + } + + constexpr T const& operator *() const& { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { + assert(initialized()); + return contained_val(); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { + assert(initialized()); + return constexpr_move(contained_val()); + } + + constexpr T const& value() const& { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : *(T*)nullptr; +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + + OPTIONAL_MUTABLE_CONSTEXPR T& value() & { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + : *(T*)nullptr; +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : std::move(*(T*)nullptr); +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + +# else + + T* operator ->() { + assert(initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert(initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : *(T*)nullptr; +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + + T& value() { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can abort here + // but the others are constexpr, so we can't... + : (std::abort(), *(T*)nullptr) +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + +# endif + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template <class V> + constexpr T value_or(V&& v) const& + { + return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + template <class V> + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); + } + +# else + + template <class V> + T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); + } + +# endif + +# else + + template <class V> + constexpr T value_or(V&& v) const + { + return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); + } + +# endif + + }; + + + template <class T> + class optional<T&> + { + static_assert(!::std::is_same<T, nullopt_t>::value, "bad T"); + static_assert(!::std::is_same<T, in_place_t>::value, "bad T"); + T* ref; + + public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template <typename U> + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template <typename U> + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = detail_::static_addressof(v); + } + + void emplace(T&&) = delete; + + + void swap(optional<T&>& rhs) noexcept + { + ::std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { + return ref ? + *ref +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : *(T*)nullptr; +#else + : throw bad_optional_access("bad optional access"); +#endif + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + template <typename V> + constexpr T& value_or(V&& v) const + { + return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v)); + } + }; + + + template <class T> + class optional<T&&> + { + static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); + }; + + + // 20.5.8, Relational operators + template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y) + { + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; + } + + template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y) + { + return !(x == y); + } + + template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y) + { + return (!y) ? false : (!x) ? true : *x < *y; + } + + template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y) + { + return (y < x); + } + + template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y) + { + return !(y < x); + } + + template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y) + { + return !(x < y); + } + + + // 20.5.9, Comparison with nullopt + template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept + { + return (!x); + } + + template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept + { + return (!x); + } + + template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept + { + return bool(x); + } + + template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept + { + return bool(x); + } + + template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept + { + return false; + } + + template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept + { + return bool(x); + } + + template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept + { + return (!x); + } + + template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept + { + return true; + } + + template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept + { + return bool(x); + } + + template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept + { + return false; + } + + template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept + { + return true; + } + + template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept + { + return (!x); + } + + + + // 20.5.10, Comparison with T + template <class T> constexpr bool operator==(const optional<T>& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template <class T> constexpr bool operator==(const T& v, const optional<T>& x) + { + return bool(x) ? v == *x : false; + } + + template <class T> constexpr bool operator!=(const optional<T>& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template <class T> constexpr bool operator!=(const T& v, const optional<T>& x) + { + return bool(x) ? v != *x : true; + } + + template <class T> constexpr bool operator<(const optional<T>& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template <class T> constexpr bool operator>(const T& v, const optional<T>& x) + { + return bool(x) ? v > *x : true; + } + + template <class T> constexpr bool operator>(const optional<T>& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template <class T> constexpr bool operator<(const T& v, const optional<T>& x) + { + return bool(x) ? v < *x : false; + } + + template <class T> constexpr bool operator>=(const optional<T>& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template <class T> constexpr bool operator<=(const T& v, const optional<T>& x) + { + return bool(x) ? v <= *x : false; + } + + template <class T> constexpr bool operator<=(const optional<T>& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template <class T> constexpr bool operator>=(const T& v, const optional<T>& x) + { + return bool(x) ? v >= *x : true; + } + + + // Comparison of optional<T&> with T + template <class T> constexpr bool operator==(const optional<T&>& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template <class T> constexpr bool operator==(const T& v, const optional<T&>& x) + { + return bool(x) ? v == *x : false; + } + + template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x) + { + return bool(x) ? v != *x : true; + } + + template <class T> constexpr bool operator<(const optional<T&>& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template <class T> constexpr bool operator>(const T& v, const optional<T&>& x) + { + return bool(x) ? v > *x : true; + } + + template <class T> constexpr bool operator>(const optional<T&>& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template <class T> constexpr bool operator<(const T& v, const optional<T&>& x) + { + return bool(x) ? v < *x : false; + } + + template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x) + { + return bool(x) ? v <= *x : false; + } + + template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x) + { + return bool(x) ? v >= *x : true; + } + + // Comparison of optional<T const&> with T + template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x) + { + return bool(x) ? v == *x : false; + } + + template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x) + { + return bool(x) ? v != *x : true; + } + + template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x) + { + return bool(x) ? v > *x : true; + } + + template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x) + { + return bool(x) ? v < *x : false; + } + + template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x) + { + return bool(x) ? v <= *x : false; + } + + template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x) + { + return bool(x) ? v >= *x : true; + } + + + // 20.5.12, Specialized algorithms + template <class T> + void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) { + x.swap(y); + } + + + template <class T> + constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) { + return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v)); + } + + template <class X> + constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) { + return optional<X&>(v.get()); + } + + +} // namespace + +namespace std +{ + template <typename T> + struct hash<sol::optional<T>> { + typedef typename hash<T>::result_type result_type; + typedef sol::optional<T> argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash<T>{}(*arg) : result_type{}; + } + }; + + template <typename T> + struct hash<sol::optional<T&>> { + typedef typename hash<T>::result_type result_type; + typedef sol::optional<T&> argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash<T>{}(*arg) : result_type{}; + } + }; +} + +# undef TR2_OPTIONAL_REQUIRES +# undef TR2_OPTIONAL_ASSERTED_EXPRESSION + +# endif // SOL_OPTIONAL_IMPLEMENTATION_HPP diff --git a/3rdparty/sol2/sol/proxy.hpp b/3rdparty/sol2/sol/proxy.hpp index 22247a8d818..20bb0666598 100644 --- a/3rdparty/sol2/sol/proxy.hpp +++ b/3rdparty/sol2/sol/proxy.hpp @@ -123,22 +123,26 @@ namespace sol { template<typename Table, typename Key, typename T> inline bool operator==(T&& left, const proxy<Table, Key>& right) { - return left == right.template get<std::decay_t<T>>(); + typedef decltype(stack::get<T>(nullptr, 0)) U; + return right.template get<optional<U>>() == left; } template<typename Table, typename Key, typename T> inline bool operator==(const proxy<Table, Key>& right, T&& left) { - return right.template get<std::decay_t<T>>() == left; + typedef decltype(stack::get<T>(nullptr, 0)) U; + return right.template get<optional<U>>() == left; } template<typename Table, typename Key, typename T> inline bool operator!=(T&& left, const proxy<Table, Key>& right) { - return right.template get<std::decay_t<T>>() != left; + typedef decltype(stack::get<T>(nullptr, 0)) U; + return right.template get<optional<U>>() == left; } template<typename Table, typename Key, typename T> inline bool operator!=(const proxy<Table, Key>& right, T&& left) { - return right.template get<std::decay_t<T>>() != left; + typedef decltype(stack::get<T>(nullptr, 0)) U; + return right.template get<optional<U>>() == left; } template<typename Table, typename Key> diff --git a/3rdparty/sol2/sol/simple_usertype_metatable.hpp b/3rdparty/sol2/sol/simple_usertype_metatable.hpp index 586e0d18527..482ad8037dc 100644 --- a/3rdparty/sol2/sol/simple_usertype_metatable.hpp +++ b/3rdparty/sol2/sol/simple_usertype_metatable.hpp @@ -31,6 +31,8 @@ namespace sol { namespace usertype_detail { + const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001); + struct variable_wrapper { virtual int index(lua_State* L) = 0; virtual int new_index(lua_State* L) = 0; @@ -68,8 +70,31 @@ namespace sol { template <typename T> inline int simple_metatable_newindex(lua_State* L) { - if (stack::stack_detail::check_metatable<T, false>(L, 1)) { - stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), 1); + int isnum = 0; + lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum); + if (isnum != 0 && magic == toplevel_magic) { + for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits<T*>::metatable()[0]; + break; + case 1: + metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; + break; + case 2: + default: + metakey = &usertype_traits<T>::metatable()[0]; + break; + } + luaL_getmetatable(L, metakey); + int tableindex = lua_gettop(L); + if (type_of(L, tableindex) == type::nil) { + continue; + } + stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex); + } lua_settop(L, 0); return 0; } @@ -259,15 +284,15 @@ namespace sol { template <typename... Bases> void add(lua_State*, base_classes_tag, bases<Bases...>) { - static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform"); + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report."); 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."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please 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: Please 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...>; @@ -278,11 +303,11 @@ namespace sol { template<std::size_t... I, typename Tuple> simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args) : callconstructfunc(nil), - indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::simple_metatable_newindex<T>), + indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>), indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>), baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(true), secondarymeta(true) { + mustindex(false), secondarymeta(false) { (void)detail::swallow{ 0, (add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)... }; @@ -329,7 +354,7 @@ namespace sol { static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { static int uniqueness = 0; - std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable; + 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 @@ -340,8 +365,11 @@ namespace sol { snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); ++uniqueness; - const char* gcmetakey = &usertype_traits<T>::gc_table[0]; - stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable[0], umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, std::move(umx.varmap), std::move(umx.registrations)); + const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; + stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0], + umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, + std::move(umx.varmap), std::move(umx.registrations) + ); stack_reference stackvarmap(L, -1); stack::set_field<true>(L, gcmetakey, stackvarmap); stackvarmap.pop(); @@ -356,19 +384,53 @@ namespace sol { bool hasequals = false; bool hasless = false; bool haslessequals = false; + auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { + if (first == name_of(meta_function::equal_to)) { + hasequals = true; + } + else if (first == name_of(meta_function::less_than)) { + hasless = true; + } + else if (first == name_of(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + else if (first == name_of(meta_function::index)) { + umx.indexfunc = second.template as<lua_CFunction>(); + } + else if (first == name_of(meta_function::new_index)) { + umx.newindexfunc = second.template as<lua_CFunction>(); + } + switch (i) { + case 0: + if (first == name_of(meta_function::garbage_collect)) { + return; + } + break; + case 1: + if (first == name_of(meta_function::garbage_collect)) { + stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index()); + return; + } + break; + case 2: + default: + break; + } + stack::set_field(L, first, second, t.stack_index()); + }; for (std::size_t i = 0; i < 3; ++i) { // Pointer types, AKA "references" from C++ const char* metakey = nullptr; switch (i) { case 0: - metakey = &usertype_traits<T*>::metatable[0]; + metakey = &usertype_traits<T*>::metatable()[0]; break; case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0]; + metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; break; case 2: default: - metakey = &usertype_traits<T>::metatable[0]; + metakey = &usertype_traits<T>::metatable()[0]; break; } luaL_newmetatable(L, metakey); @@ -376,38 +438,7 @@ namespace sol { for (auto& kvp : varmap.functions) { auto& first = std::get<0>(kvp); auto& second = std::get<1>(kvp); - if (first == name_of(meta_function::equal_to)) { - hasequals = true; - } - else if (first == name_of(meta_function::less_than)) { - hasless = true; - } - else if (first == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - else if (first == name_of(meta_function::index)) { - umx.indexfunc = second.template as<lua_CFunction>(); - } - else if (first == name_of(meta_function::new_index)) { - umx.newindexfunc = second.template as<lua_CFunction>(); - } - switch (i) { - case 0: - if (first == name_of(meta_function::garbage_collect)) { - continue; - } - break; - case 1: - if (first == name_of(meta_function::garbage_collect)) { - stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index()); - continue; - } - break; - case 2: - default: - break; - } - stack::set_field(L, first, second, t.stack_index()); + register_kvp(i, t, first, second); } luaL_Reg opregs[4]{}; int opregsindex = 0; @@ -440,7 +471,6 @@ namespace sol { if (umx.mustindex) { // use indexing function - static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report."); stack::set_field(L, meta_function::index, make_closure(&usertype_detail::simple_index_call, make_light(varmap), @@ -460,7 +490,7 @@ namespace sol { } // metatable on the metatable // for call constructor purposes and such - lua_createtable(L, 0, 1); + lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid())); stack_reference metabehind(L, -1); if (umx.callconstructfunc.valid()) { stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); @@ -482,9 +512,44 @@ namespace sol { stack::set_field(L, metatable_key, metabehind, t.stack_index()); metabehind.pop(); - if (i < 2) - t.pop(); + t.pop(); + } + + // Now for the shim-table that actually gets pushed + luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); + stack_reference t(L, -1); + for (auto& kvp : varmap.functions) { + auto& first = std::get<0>(kvp); + auto& second = std::get<1>(kvp); + register_kvp(2, t, first, second); } + { + lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid())); + stack_reference metabehind(L, -1); + if (umx.callconstructfunc.valid()) { + stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); + } + // use indexing function + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + &usertype_detail::simple_index_call, + &usertype_detail::simple_metatable_newindex<T>, + usertype_detail::toplevel_magic + ), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + &usertype_detail::simple_index_call, + &usertype_detail::simple_metatable_newindex<T>, + usertype_detail::toplevel_magic + ), metabehind.stack_index()); + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + } + + // Don't pop the table when we're done; + // return it return 1; } }; diff --git a/3rdparty/sol2/sol/stack_check.hpp b/3rdparty/sol2/sol/stack_check.hpp index bf9faa1ed52..5a8610f270a 100644 --- a/3rdparty/sol2/sol/stack_check.hpp +++ b/3rdparty/sol2/sol/stack_check.hpp @@ -34,7 +34,7 @@ namespace sol { namespace stack_detail { template <typename T, bool poptable = true> inline bool check_metatable(lua_State* L, int index = -2) { - const auto& metakey = usertype_traits<T>::metatable; + const auto& metakey = usertype_traits<T>::metatable(); luaL_getmetatable(L, &metakey[0]); const type expectedmetatabletype = static_cast<type>(lua_type(L, -1)); if (expectedmetatabletype != type::nil) { @@ -77,6 +77,34 @@ namespace sol { } }; + template<typename T> + struct checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> { + template <typename Handler> + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = lua_isinteger(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, type::number, type_of(L, index)); + } + return success; + } + }; + + template<typename T> + struct checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> { + template <typename Handler> + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = lua_isnumber(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, type::number, type_of(L, index)); + } + return success; + } + }; + template <type expected, typename C> struct checker<nil_t, expected, C> { template <typename Handler> @@ -239,21 +267,7 @@ namespace sol { }; template <typename T, typename C> - struct checker<T*, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - const type indextype = type_of(L, index); - // Allow nil to be transformed to nullptr - if (indextype == type::nil) { - tracking.use(1); - return true; - } - return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(types<meta::unqualified_t<T>>(), L, indextype, index, std::forward<Handler>(handler), tracking); - } - }; - - template <typename T, typename C> - struct checker<T, type::userdata, C> { + struct checker<detail::as_value_tag<T>, type::userdata, C> { template <typename U, typename Handler> static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { tracking.use(1); @@ -292,11 +306,28 @@ namespace sol { lua_pop(L, 1); return true; } + }; + + template <typename T, typename C> + struct checker<T, type::userdata, C> { + template <typename Handler> + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking); + } + }; + template <typename T, typename C> + struct checker<T*, type::userdata, C> { template <typename Handler> static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { const type indextype = type_of(L, index); - return check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking); + // Allow nil to be transformed to nullptr + if (indextype == type::nil) { + tracking.use(1); + return true; + } + return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking); } }; diff --git a/3rdparty/sol2/sol/stack_get.hpp b/3rdparty/sol2/sol/stack_get.hpp index 52c52efa10e..7cb7f2b82c9 100644 --- a/3rdparty/sol2/sol/stack_get.hpp +++ b/3rdparty/sol2/sol/stack_get.hpp @@ -41,7 +41,7 @@ namespace sol { template<typename T, typename> struct getter { static T& get(lua_State* L, int index, record& tracking) { - return getter<T&>{}.get(L, index, tracking); + return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking); } }; @@ -437,7 +437,7 @@ namespace sol { }; template<typename T> - struct getter<T*> { + struct getter<detail::as_value_tag<T>> { static T* get_no_nil(lua_State* L, int index, record& tracking) { tracking.use(1); void** pudata = static_cast<void**>(lua_touserdata(L, index)); @@ -456,28 +456,49 @@ namespace sol { T* obj = static_cast<T*>(udata); return obj; } + + static T& get(lua_State* L, int index, record& tracking) { + return *get_no_nil(L, index, tracking); + } + }; + template<typename T> + struct getter<detail::as_pointer_tag<T>> { static T* get(lua_State* L, int index, record& tracking) { type t = type_of(L, index); if (t == type::nil) { tracking.use(1); return nullptr; } - return get_no_nil(L, index, tracking); + return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking); } }; template<typename T> struct getter<non_null<T*>> { static T* get(lua_State* L, int index, record& tracking) { - return getter<T*>::get_no_nil(L, index, tracking); + return getter<detail::as_value_tag<T>>::get_no_nil(L, index, tracking); } }; template<typename T> struct getter<T&> { static T& get(lua_State* L, int index, record& tracking) { - return *getter<T*>::get_no_nil(L, index, tracking); + return getter<detail::as_value_tag<T>>::get(L, index, tracking); + } + }; + + template<typename T> + struct getter<std::reference_wrapper<T>> { + static T& get(lua_State* L, int index, record& tracking) { + return getter<T&>{}.get(L, index, tracking); + } + }; + + template<typename T> + struct getter<T*> { + static T* get(lua_State* L, int index, record& tracking) { + return getter<detail::as_pointer_tag<T>>::get(L, index, tracking); } }; @@ -495,13 +516,6 @@ namespace sol { } }; - template<typename T> - struct getter<std::reference_wrapper<T>> { - static T& get(lua_State* L, int index, record& tracking) { - return getter<T&>{}.get(L, index, tracking); - } - }; - template<typename... Args> struct getter<std::tuple<Args...>> { typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R; diff --git a/3rdparty/sol2/sol/stack_push.hpp b/3rdparty/sol2/sol/stack_push.hpp index 27d28fc081e..cf39d1e40c8 100644 --- a/3rdparty/sol2/sol/stack_push.hpp +++ b/3rdparty/sol2/sol/stack_push.hpp @@ -62,7 +62,7 @@ namespace sol { template <typename... Args> static int push(lua_State* L, Args&&... args) { - return push_keyed(L, usertype_traits<T>::metatable, std::forward<Args>(args)...); + return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Args>(args)...); } }; @@ -87,7 +87,7 @@ namespace sol { } static int push(lua_State* L, T* obj) { - return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable, obj); + return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable(), obj); } }; @@ -140,7 +140,7 @@ namespace sol { *fx = detail::special_destruct<P, Real>; detail::default_construct::construct(mem, std::forward<Args>(args)...); *pref = unique_usertype_traits<T>::get(*mem); - if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable[0]) == 1) { + if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) { set_field(L, "__gc", detail::unique_destruct<P>); } lua_setmetatable(L, -2); @@ -362,13 +362,13 @@ namespace sol { template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_key_t>> = meta::enabler> static int push(lua_State* L, Arg&& arg, Args&&... args) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0]; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...); } template <typename... Args> static int push(lua_State* L, no_metatable_t, Args&&... args) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0]; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; return push_with<false>(L, name, std::forward<Args>(args)...); } @@ -379,22 +379,22 @@ namespace sol { } static int push(lua_State* L, const user<T>& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0]; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; return push_with(L, name, u.value); } static int push(lua_State* L, user<T>&& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0]; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; return push_with(L, name, std::move(u.value)); } static int push(lua_State* L, no_metatable_t, const user<T>& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0]; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; return push_with<false>(L, name, u.value); } static int push(lua_State* L, no_metatable_t, user<T>&& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable[0]; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; return push_with<false>(L, name, std::move(u.value)); } }; diff --git a/3rdparty/sol2/sol/state.hpp b/3rdparty/sol2/sol/state.hpp index 18c32db5010..b2b03622748 100644 --- a/3rdparty/sol2/sol/state.hpp +++ b/3rdparty/sol2/sol/state.hpp @@ -31,8 +31,12 @@ namespace sol { 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"; - throw error(err); + if (message) { + std::string err = message; + lua_pop(L, 1); + throw error(err); + } + throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic")); #endif } diff --git a/3rdparty/sol2/sol/state_view.hpp b/3rdparty/sol2/sol/state_view.hpp index 3efb3674d25..d3c12d3bd4a 100644 --- a/3rdparty/sol2/sol/state_view.hpp +++ b/3rdparty/sol2/sol/state_view.hpp @@ -115,6 +115,10 @@ namespace sol { } + state_view(this_state L) : state_view(L.L){ + + } + lua_State* lua_state() const { return L; } @@ -222,18 +226,30 @@ namespace sol { return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); } + protected_function_result do_string(const std::string& code) { + sol::protected_function pf = load(code); + return pf(); + } + + protected_function_result do_file(const std::string& filename) { + sol::protected_function pf = load_file(filename); + return pf(); + } + function_result script(const std::string& code) { - int index = (::std::max)(lua_gettop(L), 1); + int index = lua_gettop(L); stack::script(L, code); - int returns = lua_gettop(L) - (index - 1); - return function_result(L, index, returns); + int postindex = lua_gettop(L); + int returns = postindex - index; + return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); } function_result script_file(const std::string& filename) { - int index = (::std::max)(lua_gettop(L), 1); + int index = lua_gettop(L); stack::script_file(L, filename); - int returns = lua_gettop(L) - (index - 1); - return function_result(L, index, returns); + int postindex = lua_gettop(L); + int returns = postindex - index; + return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); } load_result load(const std::string& code) { @@ -317,7 +333,7 @@ namespace sol { template<typename T> state_view& set_usertype(usertype<T>& user) { - return set_usertype(usertype_traits<T>::name, user); + return set_usertype(usertype_traits<T>::name(), user); } template<typename Key, typename T> diff --git a/3rdparty/sol2/sol/table_core.hpp b/3rdparty/sol2/sol/table_core.hpp index 918f3d4ad76..107cd19776e 100644 --- a/3rdparty/sol2/sol/table_core.hpp +++ b/3rdparty/sol2/sol/table_core.hpp @@ -244,7 +244,7 @@ namespace sol { template<typename T> basic_table_core& set_usertype(usertype<T>& user) { - return set_usertype(usertype_traits<T>::name, user); + return set_usertype(usertype_traits<T>::name(), user); } template<typename Key, typename T> @@ -419,6 +419,7 @@ namespace sol { template <typename... Args> static inline table create_with(lua_State* L, Args&&... args) { + static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...); } diff --git a/3rdparty/sol2/sol/types.hpp b/3rdparty/sol2/sol/types.hpp index 86ac4806532..7761be6d0f2 100644 --- a/3rdparty/sol2/sol/types.hpp +++ b/3rdparty/sol2/sol/types.hpp @@ -361,6 +361,7 @@ namespace sol { new_index, mode, call, + call_function = call, metatable, to_string, length, @@ -377,7 +378,13 @@ namespace sol { less_than, less_than_or_equal_to, garbage_collect, - call_function = call, + floor_division, + bitwise_left_shift, + bitwise_right_shift, + bitwise_not, + bitwise_and, + bitwise_or, + bitwise_xor, }; typedef meta_function meta_method; @@ -393,7 +400,7 @@ namespace sol { "__newindex", "__mode", "__call", - "__metatable", + "__mt", "__tostring", "__len", "__unm", @@ -643,6 +650,12 @@ namespace sol { template <typename T> struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {}; + template <typename T, typename C = void> + struct is_container : std::false_type {}; + + template <typename T> + struct is_container<T, std::enable_if_t<meta::has_begin_end<meta::unqualified_t<T>>::value>> : std::true_type {}; + template <> struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {}; @@ -747,6 +760,9 @@ namespace sol { template <typename T> struct is_userdata<basic_userdata<T>> : std::true_type {}; + template <typename T> + struct is_container : detail::is_container<T>{}; + template<typename T> inline type type_of() { return lua_type_of<meta::unqualified_t<T>>::value; diff --git a/3rdparty/sol2/sol/usertype_metatable.hpp b/3rdparty/sol2/sol/usertype_metatable.hpp index cd57f2679b9..fff5f60dab8 100644 --- a/3rdparty/sol2/sol/usertype_metatable.hpp +++ b/3rdparty/sol2/sol/usertype_metatable.hpp @@ -116,8 +116,8 @@ namespace sol { 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* 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); @@ -466,7 +466,7 @@ namespace sol { 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::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 @@ -477,7 +477,7 @@ namespace sol { snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); ++uniqueness; - const char* gcmetakey = &usertype_traits<T>::gc_table[0]; + 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<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx)); @@ -514,16 +514,16 @@ namespace sol { luaL_Reg* metaregs = nullptr; switch (i) { case 0: - metakey = &usertype_traits<T*>::metatable[0]; + metakey = &usertype_traits<T*>::metatable()[0]; metaregs = ref_table.data(); break; case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0]; + metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; metaregs = unique_table.data(); break; case 2: default: - metakey = &usertype_traits<T>::metatable[0]; + metakey = &usertype_traits<T>::metatable()[0]; metaregs = value_table.data(); break; } @@ -554,7 +554,7 @@ namespace sol { } // metatable on the metatable // for call constructor purposes and such - lua_createtable(L, 0, 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()); @@ -567,9 +567,26 @@ namespace sol { metabehind.pop(); // We want to just leave the table // in the registry only, otherwise we return it - if (i < 2) { - t.pop(); + 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; diff --git a/3rdparty/sol2/sol/usertype_traits.hpp b/3rdparty/sol2/sol/usertype_traits.hpp index 2dd3d62cbaf..0857b30e0c2 100644 --- a/3rdparty/sol2/sol/usertype_traits.hpp +++ b/3rdparty/sol2/sol/usertype_traits.hpp @@ -28,28 +28,32 @@ namespace sol { template<typename T> struct usertype_traits { - static const std::string name; - static const std::string qualified_name; - static const std::string metatable; - static const std::string user_gc_metatable; - static const std::string gc_table; + static const std::string& name() { + static const std::string n = detail::short_demangle<T>(); + return n; + } + static const std::string& qualified_name() { + static const std::string q_n = detail::demangle<T>(); + return q_n; + } + static const std::string& metatable() { + static const std::string m = std::string("sol.").append(detail::demangle<T>()); + return m; + } + static const std::string& user_metatable() { + static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user"); + return u_m; + } + static const std::string& user_gc_metatable() { + static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB"); + return u_g_m; + } + static const std::string& gc_table() { + static const std::string g_t = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB")); + return g_t; + } }; - template<typename T> - const std::string usertype_traits<T>::name = detail::short_demangle<T>(); - - template<typename T> - const std::string usertype_traits<T>::qualified_name = detail::demangle<T>(); - - template<typename T> - const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>()); - - template<typename T> - const std::string usertype_traits<T>::user_gc_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB"); - - template<typename T> - const std::string usertype_traits<T>::gc_table = std::string("sol.").append(detail::demangle<T>().append(".\xE2\x99\xBB")); - } #endif // SOL_USERTYPE_TRAITS_HPP |