// The MIT License (MIT) // Copyright (c) 2013-2015 Danny Y., Rapptz // 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_STATE_HPP #define SOL_STATE_HPP #include "error.hpp" #include "table.hpp" #include namespace sol { namespace detail { inline int atpanic(lua_State* L) { 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); } } // detail enum class lib : char { base, package, coroutine, string, os, math, table, debug, bit32, io, count }; class state { private: std::unique_ptr L; table reg; global_table globals; public: state(lua_CFunction panic = detail::atpanic): L(luaL_newstate(), lua_close), reg(L.get(), LUA_REGISTRYINDEX), globals(detail::global_overload, reg) { set_panic(panic); } lua_State* lua_state() const { return L.get(); } template void open_libraries(Args&&... args) { static_assert(are_same::value, "all types must be libraries"); if(sizeof...(args) == 0) { luaL_openlibs(L.get()); return; } lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; for(auto&& library : libraries) { switch(library) { #if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) case lib::coroutine: #endif // luajit opens coroutine base stuff case lib::base: luaL_requiref(L.get(), "base", luaopen_base, 1); lua_pop(L.get(), 1); break; case lib::package: luaL_requiref(L.get(), "package", luaopen_package, 1); lua_pop(L.get(), 1); break; #if SOL_LUA_VERSION > 501 case lib::coroutine: luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1); lua_pop(L.get(), 1); break; #endif // Lua 5.2+ only case lib::string: luaL_requiref(L.get(), "string", luaopen_string, 1); lua_pop(L.get(), 1); break; case lib::table: luaL_requiref(L.get(), "table", luaopen_table, 1); lua_pop(L.get(), 1); break; case lib::math: luaL_requiref(L.get(), "math", luaopen_math, 1); lua_pop(L.get(), 1); break; case lib::bit32: #if SOL_LUA_VERSION > 510 luaL_requiref(L.get(), "bit32", luaopen_bit32, 1); lua_pop(L.get(), 1); #else #endif // Lua 5.2+ only break; case lib::io: luaL_requiref(L.get(), "io", luaopen_io, 1); lua_pop(L.get(), 1); break; case lib::os: luaL_requiref(L.get(), "os", luaopen_os, 1); lua_pop(L.get(), 1); break; case lib::debug: luaL_requiref(L.get(), "debug", luaopen_debug, 1); lua_pop(L.get(), 1); break; case lib::count: break; } } } void script(const std::string& code) { if(luaL_dostring(L.get(), code.c_str())) { lua_error(L.get()); } } void open_file(const std::string& filename) { if(luaL_dofile(L.get(), filename.c_str())) { lua_error(L.get()); } } template auto get(Keys&&... keys) const -> decltype(globals.get(std::forward(keys)...)) { return globals.get(std::forward(keys)...); } template state& set(T&& key, U&& value) { globals.set(std::forward(key), std::forward(value)); return *this; } template SOL_DEPRECATED table& set_userdata(usertype& user) { return set_usertype(user); } template SOL_DEPRECATED table& set_userdata(Key&& key, usertype& user) { return set_usertype(std::forward(key), user); } template SOL_DEPRECATED state& new_userdata(const std::string& name, Args&&... args) { return new_usertype(name, std::forward(args)...); } template SOL_DEPRECATED state& new_userdata(const std::string& name, constructors ctor, Args&&... args) { return new_usertype(name, std::move(ctor), std::forward(args)...); } template state& set_usertype(usertype& user) { return set_usertype(usertype_traits::name, user); } template state& set_usertype(Key&& key, usertype& user) { globals.set_usertype(std::forward(key), user); return *this; } template state& new_usertype(const std::string& name, Args&&... args) { constructors> ctor{}; return new_usertype(name, ctor, std::forward(args)...); } template state& new_usertype(const std::string& name, constructors ctor, Args&&... args) { usertype utype(ctor, std::forward(args)...); set_usertype(name, utype); return *this; } template void for_each(Fx&& fx) { globals.for_each(std::forward(fx)); } template table create_table(T&& key, int narr = 0, int nrec = 0) { lua_createtable(L.get(), narr, nrec); table result(L.get()); lua_pop(L.get(), 1); globals.set(std::forward(key), result); return result; } table create_table(int narr = 0, int nrec = 0) { lua_createtable(L.get(), narr, nrec); table result(L.get()); lua_pop(L.get(), 1); return result; } global_table global() const { return globals; } table registry() const { return reg; } void set_panic(lua_CFunction panic){ lua_atpanic(L.get(), panic); } template proxy operator[](T&& key) { return globals[std::forward(key)]; } template proxy operator[](T&& key) const { return globals[std::forward(key)]; } template state& set_function(Key&& key, R fun_ptr(Args...)){ globals.set_function(std::forward(key), fun_ptr); return *this; } template state& set_function(Key&& key, Sig* fun_ptr){ globals.set_function(std::forward(key), fun_ptr); return *this; } template state& set_function(Key&& key, R (C::*mem_ptr)(Args...), T&& obj) { globals.set_function(std::forward(key), mem_ptr, std::forward(obj)); return *this; } template state& set_function(Key&& key, Sig C::* mem_ptr, T&& obj) { globals.set_function(std::forward(key), mem_ptr, std::forward(obj)); return *this; } template state& set_function(Key&& key, Fx&& fx) { globals.set_function(std::forward(key), std::forward(fx)); return *this; } }; } // sol #endif // SOL_STATE_HPP