// The MIT License (MIT) // Copyright (c) 2013-2016 Rapptz 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_TABLE_CORE_HPP #define SOL_TABLE_CORE_HPP #include "proxy.hpp" #include "stack.hpp" #include "function_types.hpp" #include "usertype.hpp" namespace sol { namespace detail { struct global_overload_tag { } const global_overload; } // detail template class table_core : public reference { friend class state; friend class state_view; template, is_c_str> = 0> decltype(auto) single_get( Key&& key ) const { lua_getglobal(lua_state( ), &key[0]); return stack::pop(lua_state()); } template>, is_c_str> = 0> decltype(auto) single_get( Key&& key ) const { auto pp = stack::push_popper(*this); lua_getfield( lua_state( ), -1, &key[0] ); return stack::pop( lua_state( ) ); } template>> = 0> decltype(auto) single_get( Key&& key ) const { auto pp = stack::push_popper(*this); stack::push( lua_state( ), std::forward( key ) ); lua_gettable( lua_state( ), -2 ); return stack::pop( lua_state( ) ); } template, is_c_str> = 0> void single_set( Key&& key, Value&& value ) { stack::push( lua_state( ), std::forward( value ) ); lua_setglobal( lua_state( ), &key[0] ); } template>, is_c_str> = 0> void single_set(Key&& key, Value&& value) { push(); stack::push(lua_state(), std::forward(value)); lua_setfield(lua_state(), -2, &key[0]); pop(); } template>> = 0> void single_set(Key&& key, Value&& value) { push(); stack::push(lua_state(), std::forward(key)); stack::push(lua_state(), std::forward(value)); lua_settable(lua_state(), -3); pop(); } template stack::get_return tuple_get( types, indices, Keys&& keys ) const { return stack::get_return( single_get( std::get( keys ) )... ); } template decltype(auto) tuple_get( types, indices, Keys&& keys ) const { return single_get( std::get( keys ) ); } template void tuple_set( indices, Pairs&& pairs ) { using swallow = int[]; swallow{ 0, ( single_set(std::get(pairs), std::get(pairs)) , 0)..., 0 }; } #if SOL_LUA_VERSION < 502 table_core( detail::global_overload_tag, const table_core& reg ) noexcept : reference( reg.lua_state(), LUA_GLOBALSINDEX ) { } #else table_core( detail::global_overload_tag, const table& reg ) noexcept : reference( reg.get( LUA_RIDX_GLOBALS ) ) { } #endif public: table_core( ) noexcept : reference( ) { } table_core( const table_core& global ) : reference( global ) { } table_core( lua_State* L, int index = -1 ) : reference( L, index ) { type_assert( L, index, type::table ); } template decltype(auto) get( Keys&&... keys ) const { return tuple_get( types( ), build_indices( ), std::forward_as_tuple(std::forward(keys)...)); } template table_core& set( Tn&&... argn ) { tuple_set(build_indices(), std::forward_as_tuple(std::forward(argn)...)); return *this; } template SOL_DEPRECATED table_core& set_userdata( usertype& user ) { return set_usertype( user ); } template SOL_DEPRECATED table_core& set_userdata( Key&& key, usertype& user ) { return set_usertype(std::forward(key), user); } template table_core& set_usertype( usertype& user ) { return set_usertype(usertype_traits::name, user); } template table_core& set_usertype( Key&& key, usertype& user ) { return set(std::forward(key), user); } template void for_each( Fx&& fx ) const { auto pp = stack::push_popper( *this ); stack::push( lua_state( ), nil ); while ( lua_next( this->lua_state( ), -2 ) ) { sol::object key( lua_state( ), -2 ); sol::object value( lua_state( ), -1 ); fx( key, value ); lua_pop( lua_state( ), 1 ); } } size_t size( ) const { auto pp = stack::push_popper( *this ); return lua_rawlen(lua_state(), -1); } template proxy operator[]( T&& key ) & { return proxy( *this, std::forward( key ) ); } template proxy operator[]( T&& key ) const & { return proxy( *this, std::forward( key ) ); } template proxy operator[]( T&& key ) && { return proxy( *this, std::forward( key ) ); } void pop( int n = 1 ) const noexcept { lua_pop( lua_state( ), n ); } template table_core& set_function( Key&& key, R fun_ptr( Args... ) ) { set_resolved_function( std::forward( key ), fun_ptr ); return *this; } template table_core& set_function( Key&& key, Sig* fun_ptr ) { set_resolved_function( std::forward( key ), fun_ptr ); return *this; } template table_core& set_function( Key&& key, R( C::*mem_ptr )( Args... ), T&& obj ) { set_resolved_function( std::forward( key ), mem_ptr, std::forward( obj ) ); return *this; } template table_core& set_function( Key&& key, Sig C::* mem_ptr, T&& obj ) { set_resolved_function( std::forward( key ), mem_ptr, std::forward( obj ) ); return *this; } template table_core& set_function( Key&& key, Fx&& fx ) { set_fx( types( ), std::forward( key ), std::forward( fx ) ); return *this; } private: template> void set_fx( types, Key&& key, Fx&& fx ) { set_resolved_function( std::forward( key ), std::forward( fx ) ); } template void set_fx( types<>, Key&& key, Fx&& fx ) { typedef Unqualified> fx_t; typedef decltype( &fx_t::operator() ) Sig; set_fx( types>( ), std::forward( key ), std::forward( fx ) ); } template void set_resolved_function( Key&& key, Args&&... args ) { set(std::forward(key), detail::function_pack>(std::forward(args)...)); } }; } // sol #endif // SOL_TABLE_CORE_HPP