// 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_TYPES_HPP #define SOL_TYPES_HPP #include "optional.hpp" #include "compatibility.hpp" #include "traits.hpp" #include "string_shim.hpp" #include #include namespace sol { namespace detail { #ifdef SOL_NO_EXCEPTIONS template int static_trampoline(lua_State* L) { return f(L); } template int trampoline(lua_State* L, Fx&& f, Args&&... args) { return f(L, std::forward(args)...); } inline int c_trampoline(lua_State* L, lua_CFunction f) { return trampoline(L, f); } #else template int static_trampoline(lua_State* L) { try { return f(L); } catch (const char *s) { lua_pushstring(L, s); } catch (const std::exception& e) { lua_pushstring(L, e.what()); } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) catch (...) { lua_pushstring(L, "caught (...) exception"); } #endif return lua_error(L); } template int trampoline(lua_State* L, Fx&& f, Args&&... args) { 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) catch (...) { lua_pushstring(L, "caught (...) exception"); } #endif return lua_error(L); } inline int c_trampoline(lua_State* L, lua_CFunction f) { return trampoline(L, f); } #endif // Exceptions vs. No Exceptions 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{}; } // 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; } #ifndef __OBJC__ typedef lua_nil_t nil_t; const nil_t nil{}; #endif struct metatable_key_t {}; const metatable_key_t metatable_key = {}; struct no_metatable_t {}; const no_metatable_t no_metatable = {}; typedef std::remove_pointer_t lua_r_CFunction; 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 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::move(x)) {} operator U* () { return std::addressof(value); } operator U& () { return value; } operator const U& () 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; template as_table_t(Args&&... args) : source(std::forward(args)...) {} operator std::add_lvalue_reference_t () { return source; } }; template struct nested { T source; template nested(Args&&... args) : source(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)); } struct this_state { lua_State* L; operator lua_State* () const { return L; } lua_State* operator-> () const { 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 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, #ifndef __OBJC__ nil = lua_nil, #endif // Objective C++ Keyword 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 = none | lua_nil | string | number | thread | table | boolean | function | userdata | lightuserdata }; 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]; } 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, next }; typedef meta_function meta_method; const std::array meta_variable_names = { { "__index", "__newindex", } }; const std::array meta_function_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", "__next" } }; inline const std::string& name_of(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 int type_panic(lua_State* L, int index, type expected, type actual) { return luaL_error(L, "stack index %d, expected %s, received %s", index, expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), expected == type::poly ? "anything" : lua_typename(L, static_cast(actual)) ); } // Specify this function as the handler for lua::check if you know there's nothing wrong inline int no_panic(lua_State*, int, type, type) noexcept { return 0; } inline void type_error(lua_State* L, int expected, int actual) { luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); } inline void type_error(lua_State* L, type expected, type actual) { type_error(L, static_cast(expected), static_cast(actual)); } inline void type_assert(lua_State* L, int index, type expected, type actual) { if (expected != type::poly && expected != actual) { type_panic(L, index, expected, actual); } } inline void type_assert(lua_State* L, int index, type expected) { type actual = type_of(L, index); type_assert(L, index, expected, actual); } inline std::string type_name(lua_State* L, type t) { return lua_typename(L, static_cast(t)); } class reference; class stack_reference; template struct proxy; template class usertype; template class basic_table_core; template using table_core = basic_table_core; template using stack_table_core = basic_table_core; template using basic_table = basic_table_core; typedef table_core table; typedef table_core global_table; typedef stack_table_core stack_table; typedef stack_table_core stack_global_table; template struct basic_environment; using environment = basic_environment; using stack_environment = basic_environment; template class basic_function; template class basic_protected_function; using protected_function = basic_protected_function; using stack_protected_function = basic_protected_function; using unsafe_function = basic_function; using safe_function = basic_protected_function; using stack_unsafe_function = basic_function; using stack_safe_function = basic_protected_function; #ifdef SOL_SAFE_FUNCTIONS using function = protected_function; using stack_function = stack_protected_function; #else using function = unsafe_function; using stack_function = stack_unsafe_function; #endif template class basic_object; template class basic_userdata; template class basic_lightuserdata; struct variadic_args; using object = basic_object; using stack_object = basic_object; using userdata = basic_userdata; using stack_userdata = basic_userdata; using lightuserdata = basic_lightuserdata; using stack_lightuserdata = basic_lightuserdata; class coroutine; class thread; struct variadic_args; struct this_state; 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::value>> : std::integral_constant {}; template struct lua_type_of::value>> : std::integral_constant {}; 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>::value>> : std::true_type {}; template <> struct lua_type_of : std::integral_constant {}; template class V, typename... Args> struct accumulate : std::integral_constant {}; template class V, typename T, typename... Args> struct accumulate : accumulate::value, V, Args...> {}; } // 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 {}; } 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 || meta::is_specialization_of>::value || meta::is_specialization_of>::value > { }; template struct is_lua_reference : std::integral_constant>::value || std::is_base_of>::value || meta::is_specialization_of>::value > { }; 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> : 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_variadic_arguments : std::is_same {}; 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_container : detail::is_container{}; template inline type type_of() { return lua_type_of>::value; } namespace detail { 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 {}; } // detail } // sol #endif // SOL_TYPES_HPP