Mercurial > code
changeset 201:8ee4a34e166c
* Adds inheritance to Luae
* Use const variables to let user definable
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 04 Jan 2014 16:59:09 +0100 |
parents | 617459270743 |
children | 99d0887395cc |
files | C++/Luae.cpp C++/Luae.h |
diffstat | 2 files changed, 87 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/Luae.cpp Sat Dec 28 11:16:11 2013 +0100 +++ b/C++/Luae.cpp Sat Jan 04 16:59:09 2014 +0100 @@ -18,21 +18,21 @@ #include "Luae.h" -namespace malikania { - /* -------------------------------------------------------- * LuaeState * -------------------------------------------------------- */ +const char *LuaeState::FieldRefs = "__refs"; + void LuaeState::initRegistry() { - if (LuaeTable::type(*this, LUA_REGISTRYINDEX, "refs") == LUA_TNIL) { + if (LuaeTable::type(*this, LUA_REGISTRYINDEX, FieldRefs) == LUA_TNIL) { lua_createtable(*this, 0, 0); lua_createtable(*this, 0, 1); lua_pushstring(*this, "v"); lua_setfield(*this, -2, "__mode"); lua_setmetatable(*this, -2); - lua_setfield(*this, LUA_REGISTRYINDEX, "refs"); + lua_setfield(*this, LUA_REGISTRYINDEX, FieldRefs); } } @@ -257,11 +257,27 @@ * LuaeClass * -------------------------------------------------------- */ +const char *LuaeClass::FieldName = "__name"; +const char *LuaeClass::FieldParents = "__parents"; + void LuaeClass::create(lua_State *L, const Def &def) { LUAE_STACK_CHECKBEGIN(L); + luaL_newmetatable(L, def.name.c_str()); - luaL_newmetatable(L, def.name.c_str()); + // Store the name of the class + lua_pushlstring(L, def.name.c_str(), def.name.length()); + lua_setfield(L, -2, FieldName); + + // Store the parents names + int i = 0; + + lua_createtable(L, 0, 0); + for (auto d(def.parent); d != nullptr; d = d->parent) { + lua_pushlstring(L, d->name.c_str(), d->name.length()); + lua_rawseti(L, -2, ++i); + } + lua_setfield(L, -2, FieldParents); // Metamethods if (def.metamethods.size() > 0) { @@ -272,19 +288,20 @@ } // Methods - if (def.methods.size() > 0) { - lua_createtable(L, 0, 0); - - for (auto m : def.methods) { - lua_pushcfunction(L, m.func); - lua_setfield(L, -2, m.name); - } - - lua_setfield(L, -2, "__index"); + lua_createtable(L, 0, 0); + for (auto m : def.methods) { + lua_pushcfunction(L, m.func); + lua_setfield(L, -2, m.name); } + // Create the inheritance + if (def.parent != nullptr) { + luaL_newmetatable(L, def.parent->name.c_str()); + lua_setmetatable(L, -2); + } + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); - LUAE_STACK_CHECKEQUALS(L); } @@ -378,8 +395,6 @@ LUAE_STACK_CHECKEQUALS(L); } -} // !malikania - void *operator new(size_t size, lua_State *L) { return lua_newuserdata(L, size);
--- a/C++/Luae.h Sat Dec 28 11:16:11 2013 +0100 +++ b/C++/Luae.h Sat Jan 04 16:59:09 2014 +0100 @@ -28,8 +28,6 @@ #include <lua.hpp> -namespace malikania { - /* {{{ LuaeState */ /** @@ -55,6 +53,12 @@ void initRegistry(); public: + /* + * FieldRefs: The field stored into the registry to avoid + * recreation of shared objects. + */ + static const char *FieldRefs; + LuaeState(const LuaeState &) = delete; LuaeState &operator=(const LuaeState &) = delete; @@ -251,10 +255,26 @@ const Def *parent; //! optional parent class }; + /* + * FieldName: The field stored in the object metatable about + * the object metatable name. + * + * FieldParents: The field that holds all parent classes. It is + * used to verify casts. + */ + static const char *FieldName; + static const char *FieldParents; + + /** + * Initialize a new object. + * + * @param L the Lua state + * @param def the definition + */ static void create(lua_State *L, const Def &def); /** - * Push a shared object to Lua, it also push it to the "refs" + * Push a shared object to Lua, it also push it to the "__refs" * table with __mode = "v". That is if we need to push the object * again we use the same reference so Lua get always the same * userdata and gain the following benefits: @@ -269,7 +289,7 @@ template <typename T> static void push(lua_State *L, Ptr<T> o, const std::string &name) { - lua_getfield(L, LUA_REGISTRYINDEX, "refs"); + lua_getfield(L, LUA_REGISTRYINDEX, LuaeState::FieldRefs); assert(lua_type(L, -1) == LUA_TTABLE); lua_rawgetp(L, -1, o.get()); @@ -297,9 +317,38 @@ template <typename T> static Ptr<T> get(lua_State *L, int index, const char *meta) { - Ptr<T> *ptr = static_cast<Ptr<T> *>(luaL_checkudata(L, index, meta)); + luaL_checktype(L, index, LUA_TUSERDATA); + if (!luaL_getmetafield(L, index, FieldName)) + luaL_error(L, "invalid type"); + + // Get the class name + const char *name = lua_tostring(L, -1); + lua_pop(L, 1); + + bool found(false); + + if (std::string(name) == std::string(meta)) { + found = true; + } else { + if (!luaL_getmetafield(L, index, FieldParents)) + luaL_error(L, "invalid type"); + + LuaeTable::read(L, -1, [&] (lua_State *L, int, int tvalue) { + if (tvalue != LUA_TSTRING) + return; + + const char *tn = lua_tostring(L, -1); + if (std::string(tn) == std::string(meta)) + found = true; + }); + + lua_pop(L, 1); + } + + if (!found) + luaL_error(L, "invalid cast from `%s' to `%s'", name, meta); - return *ptr; + return *static_cast<Ptr<T> *>(lua_touserdata(L, index)); } }; @@ -433,8 +482,6 @@ #endif -} // !malikania - void *operator new(size_t size, lua_State *L); void *operator new(size_t size, lua_State *L, const char *metaname);