// The MIT License (MIT) // Copyright (c) 2013-2017 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_TYPES_HPP #define SOL_TYPES_HPP #include "error.hpp" #include "optional.hpp" #include "compatibility.hpp" #include "forward.hpp" #include "forward_detail.hpp" #include "traits.hpp" #include "string_view.hpp" #include "raii.hpp" #include "filters.hpp" #include #include #include #ifdef SOL_CXX17_FEATURES #include #include #endif // C++17 namespace sol { namespace detail { #ifdef SOL_NOEXCEPT_FUNCTION_TYPE typedef int (*lua_CFunction_noexcept)(lua_State* L) noexcept; #else typedef int(*lua_CFunction_noexcept)(lua_State* L); #endif // noexcept function type for lua_CFunction #ifdef SOL_NO_EXCEPTIONS template int static_trampoline(lua_State* L) noexcept { return f(L); } #ifdef SOL_NOEXCEPT_FUNCTION_TYPE template int static_trampoline_noexcept(lua_State* L) noexcept { return f(L); } #else template int static_trampoline_noexcept(lua_State* L) noexcept { return f(L); } #endif template int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept { return f(L, std::forward(args)...); } inline int c_trampoline(lua_State* L, lua_CFunction f) noexcept { return trampoline(L, f); } #else template int static_trampoline(lua_State* L) { #if defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) && !defined(SOL_LUAJIT) return f(L); #else try { return f(L); } catch (const char* cs) { lua_pushstring(L, cs); } catch (const std::string& s) { lua_pushlstring(L, s.c_str(), s.size()); } catch (const std::exception& e) { lua_pushstring(L, e.what()); } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) // LuaJIT cannot have the catchall when the safe propagation is on // but LuaJIT will swallow all C++ errors // if we don't at least catch std::exception ones catch (...) { lua_pushstring(L, "caught (...) exception"); } #endif // LuaJIT cannot have the catchall, but we must catch std::exceps for it return lua_error(L); #endif // Safe exceptions } #ifdef SOL_NOEXCEPT_FUNCTION_TYPE #if 0 // impossible: g++/clang++ choke as they think this function is ambiguous: // to fix, wait for template and then switch on no-exceptness of the function template int static_trampoline(lua_State* L) noexcept { return f(L); } #else template int static_trampoline_noexcept(lua_State* L) noexcept { return f(L); } #endif // impossible #else template int static_trampoline_noexcept(lua_State* L) noexcept { return f(L); } #endif // noexcept lua_CFunction type template int trampoline(lua_State* L, Fx&& f, Args&&... args) { if (meta::bind_traits>::is_noexcept) { return f(L, std::forward(args)...); } #if defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) && !defined(SOL_LUAJIT) return f(L, std::forward(args)...); #else try { return f(L, std::forward(args)...); } catch (const char* s) { lua_pushstring(L, s); } catch (const std::exception& e) { lua_pushstring(L, e.what()); } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) // LuaJIT cannot have the catchall when the safe propagation is on // but LuaJIT will swallow all C++ errors // if we don't at least catch std::exception ones catch (...) { lua_pushstring(L, "caught (...) exception"); } #endif return lua_error(L); #endif } inline int c_trampoline(lua_State* L, lua_CFunction f) { return trampoline(L, f); } #endif // Exceptions vs. No Exceptions template inline int typed_static_trampoline_raw(std::true_type, lua_State* L) { return static_trampoline_noexcept(L); } template inline int typed_static_trampoline_raw(std::false_type, lua_State* L) { return static_trampoline(L); } template inline int typed_static_trampoline(lua_State* L) { return typed_static_trampoline_raw(std::integral_constant::is_noexcept>(), L); } template struct unique_usertype {}; template struct implicit_wrapper { T& item; implicit_wrapper(T* item) : item(*item) { } implicit_wrapper(T& item) : item(item) { } operator T&() { return item; } operator T*() { return std::addressof(item); } }; struct unchecked_t {}; const unchecked_t unchecked = unchecked_t{}; } // namespace detail struct lua_nil_t {}; const lua_nil_t lua_nil{}; inline bool operator==(lua_nil_t, lua_nil_t) { return true; } inline bool operator!=(lua_nil_t, lua_nil_t) { return false; } typedef lua_nil_t nil_t; #if !defined(SOL_NO_NIL) const nil_t nil{}; #endif struct metatable_t {}; const metatable_t metatable_key = {}; struct env_t {}; const env_t env_key = {}; struct no_metatable_t {}; const no_metatable_t no_metatable = {}; typedef std::remove_pointer_t lua_CFunction_ref; template struct unique_usertype_traits { typedef T type; typedef T actual_type; static const bool value = false; template static bool is_null(U&&) { return false; } template static auto get(U&& value) { return std::addressof(detail::deref(value)); } }; template struct unique_usertype_traits> { typedef T type; typedef std::shared_ptr actual_type; static const bool value = true; static bool is_null(const actual_type& p) { return p == nullptr; } static type* get(const actual_type& p) { return p.get(); } }; template struct unique_usertype_traits> { typedef T type; typedef std::unique_ptr actual_type; static const bool value = true; static bool is_null(const actual_type& p) { return p == nullptr; } static type* get(const actual_type& p) { return p.get(); } }; template struct non_null {}; template struct function_sig {}; struct upvalue_index { int index; upvalue_index(int idx) : index(lua_upvalueindex(idx)) { } operator int() const { return index; } }; struct raw_index { int index; raw_index(int i) : index(i) { } operator int() const { return index; } }; struct absolute_index { int index; absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) { } operator int() const { return index; } }; struct ref_index { int index; ref_index(int idx) : index(idx) { } operator int() const { return index; } }; struct stack_count { int count; stack_count(int cnt) : count(cnt) { } }; struct lightuserdata_value { void* value; lightuserdata_value(void* data) : value(data) { } operator void*() const { return value; } }; struct userdata_value { void* value; userdata_value(void* data) : value(data) { } operator void*() const { return value; } }; template struct light { L* value; light(L& x) : value(std::addressof(x)) { } light(L* x) : value(x) { } light(void* x) : value(static_cast(x)) { } operator L*() const { return value; } operator L&() const { return *value; } }; template auto make_light(T& l) { typedef meta::unwrapped_t>> L; return light(l); } template struct user { U value; user(U x) : value(std::forward(x)) { } operator std::add_pointer_t>() { return std::addressof(value); } operator std::add_lvalue_reference_t() { return value; } operator std::add_const_t>&() const { return value; } }; template auto make_user(T&& u) { typedef meta::unwrapped_t> U; return user(std::forward(u)); } template struct metatable_registry_key { T key; metatable_registry_key(T key) : key(std::forward(key)) { } }; template auto meta_registry_key(T&& key) { typedef meta::unqualified_t K; return metatable_registry_key(std::forward(key)); } template struct closure { lua_CFunction c_function; std::tuple upvalues; closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward(targetupvalues)...) { } }; template <> struct closure<> { lua_CFunction c_function; int upvalues; closure(lua_CFunction f, int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) { } }; typedef closure<> c_closure; template closure make_closure(lua_CFunction f, Args&&... args) { return closure(f, std::forward(args)...); } template struct function_arguments { std::tuple arguments; template , function_arguments>> = meta::enabler> function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward(arg), std::forward(args)...) { } }; template , typename... Args> auto as_function(Args&&... args) { return function_arguments...>(std::forward(args)...); } template , typename... Args> auto as_function_reference(Args&&... args) { return function_arguments(std::forward(args)...); } template struct as_table_t { T source; as_table_t() = default; as_table_t(const as_table_t&) = default; as_table_t(as_table_t&&) = default; as_table_t& operator=(const as_table_t&) = default; as_table_t& operator=(as_table_t&&) = default; template , as_table_t>>, meta::neg>>> = meta::enabler> as_table_t(Arg&& arg) : source(std::forward(arg)) { } template as_table_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : source(std::forward(arg0), std::forward(arg1), std::forward(args)...) { } operator std::add_lvalue_reference_t() { return source; } }; template struct nested { T source; nested() = default; nested(const nested&) = default; nested(nested&&) = default; nested& operator=(const nested&) = default; nested& operator=(nested&&) = default; template , nested>>, meta::neg>>> = meta::enabler> nested(Arg&& arg) : source(std::forward(arg)) { } template nested(Arg0&& arg0, Arg1&& arg1, Args&&... args) : source(std::forward(arg0), std::forward(arg1), std::forward(args)...) { } operator std::add_lvalue_reference_t() { return source; } }; template as_table_t as_table(T&& container) { return as_table_t(std::forward(container)); } template nested as_nested(T&& container) { return nested(std::forward(container)); } struct this_state { lua_State* L; this_state(lua_State* Ls) : L(Ls) { } operator lua_State*() const noexcept { return lua_state(); } lua_State* operator->() const noexcept { return lua_state(); } lua_State* lua_state() const noexcept { return L; } }; struct this_main_state { lua_State* L; this_main_state(lua_State* Ls) : L(Ls) { } operator lua_State*() const noexcept { return lua_state(); } lua_State* operator->() const noexcept { return lua_state(); } lua_State* lua_state() const noexcept { return L; } }; struct new_table { int sequence_hint = 0; int map_hint = 0; new_table() = default; new_table(const new_table&) = default; new_table(new_table&&) = default; new_table& operator=(const new_table&) = default; new_table& operator=(new_table&&) = default; new_table(int sequence_hint, int map_hint = 0) : sequence_hint(sequence_hint), map_hint(map_hint) { } }; enum class call_syntax { dot = 0, colon = 1 }; enum class load_mode { any = 0, text = 1, binary = 2, }; enum class call_status : int { ok = LUA_OK, yielded = LUA_YIELD, runtime = LUA_ERRRUN, memory = LUA_ERRMEM, handler = LUA_ERRERR, gc = LUA_ERRGCMM, syntax = LUA_ERRSYNTAX, file = LUA_ERRFILE, }; enum class thread_status : int { ok = LUA_OK, yielded = LUA_YIELD, runtime = LUA_ERRRUN, memory = LUA_ERRMEM, gc = LUA_ERRGCMM, handler = LUA_ERRERR, dead = -1, }; enum class load_status : int { ok = LUA_OK, syntax = LUA_ERRSYNTAX, memory = LUA_ERRMEM, gc = LUA_ERRGCMM, file = LUA_ERRFILE, }; enum class type : int { none = LUA_TNONE, lua_nil = LUA_TNIL, #if !defined(SOL_NO_NIL) nil = lua_nil, #endif // Objective C/C++ Keyword that's found in OSX SDK and OBJC -- check for all forms to protect string = LUA_TSTRING, number = LUA_TNUMBER, thread = LUA_TTHREAD, boolean = LUA_TBOOLEAN, function = LUA_TFUNCTION, userdata = LUA_TUSERDATA, lightuserdata = LUA_TLIGHTUSERDATA, table = LUA_TTABLE, poly = -0xFFFF }; inline const std::string& to_string(call_status c) { static const std::array names{ { "ok", "yielded", "runtime", "memory", "handler", "gc", "syntax", "file", } }; switch (c) { case call_status::ok: return names[0]; case call_status::yielded: return names[1]; case call_status::runtime: return names[2]; case call_status::memory: return names[3]; case call_status::handler: return names[4]; case call_status::gc: return names[5]; case call_status::syntax: return names[6]; case call_status::file: return names[7]; } return names[0]; } inline const std::string& to_string(load_status c) { static const std::array names{ { "ok", "memory", "gc", "syntax", "file", } }; switch (c) { case load_status::ok: return names[0]; case load_status::memory: return names[1]; case load_status::gc: return names[2]; case load_status::syntax: return names[3]; case load_status::file: return names[4]; } return names[0]; } inline const std::string& to_string(load_mode c) { static const std::array names{ { "bt", "t", "b", } }; return names[static_cast(c)]; } enum class meta_function { construct, index, new_index, mode, call, call_function = call, metatable, to_string, length, unary_minus, addition, subtraction, multiplication, division, modulus, power_of, involution = power_of, concatenation, equal_to, less_than, less_than_or_equal_to, garbage_collect, floor_division, bitwise_left_shift, bitwise_right_shift, bitwise_not, bitwise_and, bitwise_or, bitwise_xor, pairs, ipairs, next, type, type_info, }; typedef meta_function meta_method; inline const std::array& meta_function_names() { static const std::array names = { { "new", "__index", "__newindex", "__mode", "__call", "__mt", "__tostring", "__len", "__unm", "__add", "__sub", "__mul", "__div", "__mod", "__pow", "__concat", "__eq", "__lt", "__le", "__gc", "__idiv", "__shl", "__shr", "__bnot", "__band", "__bor", "__bxor", "__pairs", "__ipairs", "__next", "__type", "__typeinfo" } }; return names; } inline const std::string& to_string(meta_function mf) { return meta_function_names()[static_cast(mf)]; } inline type type_of(lua_State* L, int index) { return static_cast(lua_type(L, index)); } inline std::string type_name(lua_State* L, type t) { return lua_typename(L, static_cast(t)); } namespace detail { template struct is_initializer_list : std::false_type {}; template struct is_initializer_list> : std::true_type {}; template struct is_container : std::false_type {}; template struct is_container> : std::false_type {}; template <> struct is_container : std::false_type {}; template <> struct is_container : std::false_type {}; template <> struct is_container : std::false_type {}; template <> struct is_container : std::false_type {}; #ifdef SOL_CXX17_FEATURES template <> struct is_container : std::false_type {}; template <> struct is_container : std::false_type {}; template <> struct is_container : std::false_type {}; template <> struct is_container : std::false_type {}; #endif // C++ 17 template struct is_container>::value && !is_initializer_list>::value>> : std::true_type {}; template struct is_container>::value && !meta::any_same>, char, wchar_t, char16_t, char32_t>::value>> : std::true_type {}; } // namespace detail template struct is_container : detail::is_container {}; template struct is_to_stringable : meta::any>, meta::supports_adl_to_string>, meta::supports_ostream_op>> {}; namespace detail { template struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of : std::integral_constant {}; template struct lua_type_of : std::integral_constant {}; template struct lua_type_of : std::integral_constant {}; template struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template struct lua_type_of> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template struct lua_type_of : std::integral_constant {}; template struct lua_type_of::value>> : std::integral_constant {}; template struct lua_type_of::value>> : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; template <> struct lua_type_of : std::integral_constant {}; #ifdef SOL_CXX17_FEATURES template struct lua_type_of> : std::integral_constant {}; #endif // C++ 17 (or not) features template struct lua_type_of, std::enable_if_t<::sol::is_container::value>> : std::integral_constant {}; template struct lua_type_of, std::enable_if_t::value>> : lua_type_of {}; template class V, typename... Args> struct accumulate : std::integral_constant {}; template class V, typename T, typename... Args> struct accumulate : accumulate::value, V, Args...> {}; } // namespace detail template struct is_unique_usertype : std::integral_constant::value> {}; template struct lua_type_of : detail::lua_type_of { typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; }; template struct lua_size : std::integral_constant { typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; }; template struct lua_size> : std::integral_constant::value + lua_size::value> {}; template struct lua_size> : std::integral_constant::value> {}; namespace detail { template struct void_ { typedef void type; }; template struct has_internal_marker_impl : std::false_type {}; template struct has_internal_marker_impl::type> : std::true_type {}; template struct has_internal_marker : has_internal_marker_impl {}; } // namespace detail template struct is_lua_primitive : std::integral_constant>::value || ((type::userdata == lua_type_of>::value) && detail::has_internal_marker>>::value && !detail::has_internal_marker>>::value) || std::is_base_of>::value || std::is_base_of>::value || std::is_base_of>::value || meta::is_specialization_of>::value || meta::is_specialization_of>::value> {}; template struct is_lua_reference : std::integral_constant>::value || std::is_base_of>::value || std::is_base_of>::value> {}; template struct is_lua_reference_or_proxy : std::integral_constant>::value || meta::is_specialization_of>::value> {}; template struct is_main_threaded : std::is_base_of {}; template struct is_stack_based : std::is_base_of {}; template <> struct is_stack_based : std::true_type {}; template <> struct is_stack_based : std::true_type {}; template <> struct is_stack_based : std::true_type {}; template <> struct is_stack_based : std::true_type {}; template <> struct is_stack_based : std::true_type {}; template struct is_lua_primitive : std::true_type {}; template <> struct is_lua_primitive : std::true_type {}; template <> struct is_lua_primitive : std::true_type {}; template struct is_lua_primitive> : std::true_type {}; template struct is_lua_primitive> : std::true_type {}; template struct is_lua_primitive> : is_lua_primitive {}; template struct is_lua_primitive> : std::true_type {}; template struct is_lua_primitive> : std::true_type {}; template struct is_lua_primitive> : std::true_type {}; template <> struct is_lua_primitive : std::true_type {}; template <> struct is_lua_primitive : std::true_type {}; template struct is_lua_primitive> : is_lua_primitive {}; template struct is_proxy_primitive : is_lua_primitive {}; template struct is_transparent_argument : std::false_type {}; template <> struct is_transparent_argument : std::true_type {}; template <> struct is_transparent_argument : std::true_type {}; template <> struct is_transparent_argument : std::true_type {}; template <> struct is_transparent_argument : std::true_type {}; template struct is_variadic_arguments : std::is_same, variadic_args> {}; template struct is_lua_index : std::is_integral {}; template <> struct is_lua_index : std::true_type {}; template <> struct is_lua_index : std::true_type {}; template <> struct is_lua_index : std::true_type {}; template <> struct is_lua_index : std::true_type {}; template struct lua_bind_traits : meta::bind_traits { private: typedef meta::bind_traits base_t; public: typedef std::integral_constant::value != 0> runtime_variadics_t; static const std::size_t true_arity = base_t::arity; static const std::size_t arity = base_t::arity - meta::count_for::value; static const std::size_t true_free_arity = base_t::free_arity; static const std::size_t free_arity = base_t::free_arity - meta::count_for::value; }; template struct is_table : std::false_type {}; template struct is_table> : std::true_type {}; template struct is_function : std::false_type {}; template struct is_function> : std::true_type {}; template struct is_function> : std::true_type {}; template struct is_lightuserdata : std::false_type {}; template struct is_lightuserdata> : std::true_type {}; template struct is_userdata : std::false_type {}; template struct is_userdata> : std::true_type {}; template struct is_environment : std::integral_constant::value || is_table::value> {}; template inline type type_of() { return lua_type_of>::value; } namespace detail { template struct is_non_factory_constructor : std::false_type {}; template struct is_non_factory_constructor> : std::true_type {}; template struct is_non_factory_constructor> : std::true_type {}; template <> struct is_non_factory_constructor : std::true_type {}; template struct is_constructor : is_non_factory_constructor {}; template struct is_constructor> : std::true_type {}; template struct is_constructor> : is_constructor> {}; template struct is_constructor> : is_constructor> {}; template using has_constructor = meta::any>...>; template struct is_destructor : std::false_type {}; template struct is_destructor> : std::true_type {}; template using has_destructor = meta::any>...>; struct add_destructor_tag {}; struct check_destructor_tag {}; struct verified_tag { } const verified{}; } // namespace detail } // namespace sol #endif // SOL_TYPES_HPP