// The MIT License (MIT) // Copyright (c) 2013 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 { template struct are_same : std::true_type {}; template struct are_same : std::integral_constant::value && are_same::value> {}; int atpanic(lua_State* L) { throw sol_error(lua_tostring(L, -1)); } } // 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; table global; std::unordered_map> funcs; public: state(): L(luaL_newstate(), lua_close), reg(L.get(), LUA_REGISTRYINDEX), global(reg.get(LUA_RIDX_GLOBALS)) { lua_atpanic(L.get(), detail::atpanic); } state(const std::string& filename): L(luaL_newstate(), lua_close), reg(L.get(), LUA_REGISTRYINDEX), global(reg.get
(LUA_RIDX_GLOBALS)) { lua_atpanic(L.get(), detail::atpanic); open_file(filename); } template void open_libraries(Args&&... args) { static_assert(detail::are_same{}, "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) { case lib::base: luaL_requiref(L.get(), "base", luaopen_base, 1); break; case lib::package: luaL_requiref(L.get(), "package", luaopen_package, 1); break; case lib::coroutine: luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1); break; case lib::string: luaL_requiref(L.get(), "string", luaopen_string, 1); break; case lib::table: luaL_requiref(L.get(), "table", luaopen_table, 1); break; case lib::math: luaL_requiref(L.get(), "math", luaopen_math, 1); break; case lib::bit32: luaL_requiref(L.get(), "bit32", luaopen_bit32, 1); break; case lib::io: luaL_requiref(L.get(), "io", luaopen_io, 1); break; case lib::os: luaL_requiref(L.get(), "os", luaopen_os, 1); break; case lib::debug: luaL_requiref(L.get(), "debug", luaopen_debug, 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 T get(U&& key) const { return global.get(std::forward(key)); } template state& set(T&& key, U&& value) { global.set(std::forward(key), std::forward(value)); return *this; } template state& set_function(T&& key, TFx&& fx) { global.set_function(std::forward(key), std::forward(fx)); return *this; } template table create_table(T&& key, int narr = 0, int nrec = 0) { if(narr == 0 && nrec == 0) { lua_newtable(L.get()); } else { lua_createtable(L.get(), narr, nrec); } table result(L.get()); lua_pop(L.get(), 1); global.set(std::forward(key), result); return result; } table create_table(int narr = 0, int nrec = 0) { if(narr == 0 && nrec == 0) { lua_newtable(L.get()); } else { lua_createtable(L.get(), narr, nrec); } table result(L.get()); lua_pop(L.get(), 1); return result; } table global_table() const { return global; } table registry() const { return reg; } }; } // sol #endif // SOL_STATE_HPP