commit f775790c2dd3af75630fc3e33ecdd8b50bb8901e Author: Rapptz Date: Mon Nov 25 04:56:27 2013 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..39dc9054 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +obj/* +bin/* +*.ninja* +demacro.txt +Shinobi2 +dev.* +main.cpp diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..3619ff30 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,20 @@ +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. diff --git a/README.md b/README.md new file mode 100644 index 00000000..63a9f844 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +## Sol + +Sol is a C++ library binding to Lua. It currently supports Lua 5.2. Sol aims to be easy to use and easy to add to a project. +At this time, the library is header-only for easy integration with projects. + +## Caveats + +As a change of mechanism to the C API, the Lua Stack is completely abstracted away. Not only that, but all lua errors are +thrown as exceptions instead. This allows you to handle the errors gracefully without being forced to exit. + +It should be noted that the library itself depends on `lua.hpp` to be found by your compiler. It uses angle brackets, e.g. +`#include `. + +## Example + +Here's an example on how to load a basic configuration struct with a Lua script. + +```cpp +#include +#include +#include + +struct test { + int foo; + std::string bar; + double baz; +}; + +test load(const sol::table& t) { + return { t.get("foo"), t.get("bar"), t.get("baz") }; +} + +int main() { + try { + sol::state lua; + lua.script("foo = 1234;\n" + "bar = \"hello world\";\n" + "baz = 1.4;"); + + test c = load(lua.global_table()); + std::cout << '(' << c.foo << ", " << c.bar << ", " << c.baz << ")\n"; + } + catch(const std::exception& e) { + std::cerr << e.what() << '\n'; + } +} +``` + +## License + +Sol is distributed with an MIT License. You can see LICENSE.txt for more info. + +## Supported Compilers + +Sol makes use of C++11 features. The features used are as follows: + +- rvalue references +- move semantics +- variadic templates +- +- +- std::unique_ptr +- enum classes +- auto +- uniform initialisation +- noexcept + +GCC 4.7 and Clang 3.3 or higher should be able to compile without problems. Visual Studio 2013 with the November CTP should +be able to support this as well. \ No newline at end of file diff --git a/sol.hpp b/sol.hpp new file mode 100644 index 00000000..a6fbf563 --- /dev/null +++ b/sol.hpp @@ -0,0 +1,27 @@ +// 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_HPP +#define SOL_HPP + +#include "sol/state.hpp" + +#endif // SOL_HPP \ No newline at end of file diff --git a/sol/error.hpp b/sol/error.hpp new file mode 100644 index 00000000..d183b18a --- /dev/null +++ b/sol/error.hpp @@ -0,0 +1,35 @@ +// 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_ERROR_HPP +#define SOL_ERROR_HPP + +#include +#include + +namespace sol { +class sol_error : public std::runtime_error { +public: + sol_error(const std::string& str) noexcept: std::runtime_error("sol: error: " + str) {} +}; +} // sol + +#endif // SOL_ERROR_HPP \ No newline at end of file diff --git a/sol/reference.hpp b/sol/reference.hpp new file mode 100644 index 00000000..bcab8a05 --- /dev/null +++ b/sol/reference.hpp @@ -0,0 +1,96 @@ +// 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_REFERENCE_HPP +#define SOL_REFERENCE_HPP + +#include "types.hpp" + +namespace sol { +class reference { +private: + lua_State* L = nullptr; // non-owning + int ref = LUA_NOREF; + + int copy() const { + push(); + return luaL_ref(L, LUA_REGISTRYINDEX); + } +public: + constexpr reference() noexcept = default; + + reference(lua_State* L, int index): L(L) { + lua_pushvalue(L, index); + ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + virtual ~reference() { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + } + + + void push() const noexcept { + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + } + + reference(reference&& o) noexcept { + L = o.L; + ref = o.ref; + + o.L = nullptr; + o.ref = LUA_NOREF; + } + + reference& operator=(reference&& o) noexcept { + L = o.L; + ref = o.ref; + + o.L = nullptr; + o.ref = LUA_NOREF; + + return *this; + } + + reference(const reference& o) noexcept { + L = o.L; + ref = o.copy(); + } + + reference& operator=(const reference& o) noexcept { + L = o.L; + ref = o.copy(); + return *this; + } + + type get_type() { + push(); + int result = lua_type(L, -1); + lua_pop(L, 1); + return static_cast(result); + } + + lua_State* state() const noexcept { + return L; + } +}; +} // sol + +#endif // SOL_REFERENCE_HPP \ No newline at end of file diff --git a/sol/stack.hpp b/sol/stack.hpp new file mode 100644 index 00000000..36e7a8ea --- /dev/null +++ b/sol/stack.hpp @@ -0,0 +1,146 @@ +// 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_STACK_HPP +#define SOL_STACK_HPP + +#include "reference.hpp" +#include +#include + +namespace sol { +namespace stack { +namespace detail { +template +inline T pop_unsigned(lua_State* L, std::true_type) { + return lua_tounsigned(L, -1); +} + +template +inline T pop_unsigned(lua_State* L, std::false_type) { + return lua_tointeger(L, -1); +} + +template +inline T pop_arithmetic(lua_State* L, std::false_type) { + // T is a floating point + return lua_tonumber(L, -1); +} + +template +inline T pop_arithmetic(lua_State* L, std::true_type) { + // T is an integral + return pop_unsigned(L, std::is_unsigned{}); +} + +template +inline T pop_helper(lua_State* L, std::true_type) { + // T is a class type + return T(L, -1); +} + +template +inline T pop_helper(lua_State* L, std::false_type) { + // T is a fundamental type + return pop_arithmetic(L, std::is_integral{}); +} + +template +inline void push_unsigned(lua_State* L, T x, std::true_type) { + lua_pushunsigned(L, x); +} + +template +inline void push_unsigned(lua_State* L, T x, std::false_type) { + lua_pushinteger(L, x); +} + +template +inline void push_arithmetic(lua_State* L, T x, std::true_type) { + // T is an integral type + push_unsigned(L, x, std::is_unsigned{}); +} + +template +inline void push_arithmetic(lua_State* L, T x, std::false_type) { + // T is an floating point type + lua_pushnumber(L, x); +} +} // detail + +template +inline T pop(lua_State* L) { + auto result = detail::pop_helper(L, std::is_class{}); + lua_pop(L, 1); + return result; +} + +template<> +inline bool pop(lua_State* L) { + auto result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; +} + +template<> +inline std::string pop(lua_State* L) { + std::string::size_type len; + auto str = lua_tolstring(L, -1, &len); + lua_pop(L, 1); + return { str, len }; +} + +template<> +inline const char* pop(lua_State* L) { + auto result = lua_tostring(L, -1); + lua_pop(L, 1); + return result; +} + +template +inline void push(lua_State* L, T arithmetic) { + detail::push_arithmetic(L, arithmetic, std::is_integral{}); +} + +inline void push(lua_State* L, bool boolean) { + lua_pushboolean(L, boolean); +} + +inline void push(lua_State* L, const nil_t&) { + lua_pushnil(L); +} + +inline void push(lua_State* L, lua_CFunction func) { + lua_pushcfunction(L, func); +} + +template +inline void push(lua_State* L, const char (&str)[N]) { + lua_pushlstring(L, str, N - 1); +} + +inline void push(lua_State* L, const std::string& str) { + lua_pushlstring(L, str.c_str(), str.size()); +} +} // stack +} // sol + +#endif // SOL_STACK_HPP \ No newline at end of file diff --git a/sol/state.hpp b/sol/state.hpp new file mode 100644 index 00000000..86322ff4 --- /dev/null +++ b/sol/state.hpp @@ -0,0 +1,91 @@ +// 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 { +int atpanic(lua_State* L) { + throw sol_error(lua_tostring(L, -1)); +} + +class state { +private: + std::unique_ptr L; + table reg; + table global; +public: + state(): + L(luaL_newstate(), lua_close), + reg(L.get(), LUA_REGISTRYINDEX), + global(reg.get(LUA_RIDX_GLOBALS)) { + lua_atpanic(L.get(), 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(), atpanic); + open_file(filename); + } + + void open_libraries() { + luaL_openlibs(L.get()); + } + + 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) { + return global.set(std::forward(key), std::forward(value)); + } + + table global_table() const { + return global; + } + + table registry() const { + return reg; + } +}; +} // sol + +#endif // SOL_STATE_HPP \ No newline at end of file diff --git a/sol/table.hpp b/sol/table.hpp new file mode 100644 index 00000000..96f64c8c --- /dev/null +++ b/sol/table.hpp @@ -0,0 +1,58 @@ +// 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_TABLE_HPP +#define SOL_TABLE_HPP + +#include "stack.hpp" + +namespace sol { +class table : virtual public reference { +public: + table() noexcept: reference{} {} + table(lua_State* L, int index = -1): reference(L, index) { + type_assert(L, index, type::table); + } + + template + T get(U&& key) const { + push(); + stack::push(state(), std::forward(key)); + lua_gettable(state(), -2); + type_assert(state(), -1, type_of()); + auto result = stack::pop(state()); + lua_pop(state(), 1); + return result; + } + + template + table& set(T&& key, U&& value) { + push(); + stack::push(state(), std::forward(key)); + stack::push(state(), std::forward(value)); + lua_settable(state(), -3); + lua_pop(state(), 1); + return *this; + } +}; +} // sol + +#endif // SOL_TABLE_HPP \ No newline at end of file diff --git a/sol/types.hpp b/sol/types.hpp new file mode 100644 index 00000000..31956544 --- /dev/null +++ b/sol/types.hpp @@ -0,0 +1,108 @@ +// 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_TYPES_HPP +#define SOL_TYPES_HPP + +#include +#include +#include + +namespace sol { +struct nil_t {}; +constexpr nil_t nil{}; + +enum class type : int { + none = LUA_TNONE, + nil = LUA_TNIL, + string = LUA_TSTRING, + number = LUA_TNUMBER, + thread = LUA_TTHREAD, + boolean = LUA_TBOOLEAN, + function = LUA_TFUNCTION, + userdata = LUA_TUSERDATA, + lightuserdata = LUA_TLIGHTUSERDATA, + table = LUA_TTABLE +}; + +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_assert(lua_State* L, int index, type expected) { + int actual = lua_type(L, index); + if(static_cast(expected) != actual) { + type_error(L, static_cast(expected), actual); + } +} + +class table; +class function; + +namespace detail { +template +inline type arithmetic(std::true_type) { + return type::number; +} + +template +inline type arithmetic(std::false_type) { + return type::none; +} +} // detail + +template +inline type type_of() { + return detail::arithmetic(std::is_arithmetic{}); +} + +template<> +inline type type_of
() { + return type::table; +} + +template<> +inline type type_of() { + return type::function; +} + +template<> +inline type type_of() { + return type::string; +} + +template<> +inline type type_of() { + return type::string; +} + +template<> +inline type type_of() { + return type::nil; +} + +template<> +inline type type_of() { + return type::boolean; +} +} // sol + +#endif // SOL_TYPES_HPP \ No newline at end of file