Mercurial > code
changeset 207:d859ed8bc815
Luae: add pushIterator
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 28 Feb 2014 16:51:09 +0100 |
parents | b54c83ed71ca |
children | 3b0e276f0866 |
files | C++/Luae.h |
diffstat | 1 files changed, 136 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/Luae.h Sun Feb 23 22:14:43 2014 +0100 +++ b/C++/Luae.h Fri Feb 28 16:51:09 2014 +0100 @@ -76,6 +76,24 @@ }; /** + * @struct Iterator + * @brief Wrap STL containers + */ + template <typename Type> + struct Iterator { + Type begin; + Type end; + Type current; + + Iterator(Type begin, Type end) + : begin(begin) + , end(end) + , current(begin) + { + } + }; + + /** * Preload a library, it will be added to package.preload so the * user can successfully call require "name". In order to work, you need * to open luaopen_package and luaopen_base first. @@ -101,6 +119,39 @@ } /** + * Load all Lua libraries. + * + * @param L the Lua state + */ + static inline void openlibs(lua_State *L) + { + luaL_openlibs(L); + } + + /** + * Set a global. + * + * @param L the Lua state + * @param name the name + */ + static inline void setglobal(lua_State *L, const std::string &name) + { + lua_setglobal(L, name.c_str()); + } + + /** + * Push a function with an optional number of upvalues. + * + * @param L the Lua state + * @param func the function + * @param nup the number of up values + */ + static inline void pushfunction(lua_State *L, lua_CFunction func, int nup = 0) + { + lua_pushcclosure(L, func, nup); + } + + /** * Move the top element at the given index. * * @param L the Lua state @@ -272,6 +323,57 @@ } /** + * Push an iterator function onto the stack. May be used by functions + * calls or directly with __pairs. + * + * The container must at least have: + * value_type, + * const_iterator + * + * The value of the container must also be pushable with Luae::Convert. + * + * @param L the Lua state + * @param container the container + * @return 1 + */ + template <typename Container, + typename Converter = Convert<typename Container::value_type>> + static int pushIterator(lua_State *L, const Container &container) + { + using ValueType = typename Container::value_type; + using IteratorType = typename Container::const_iterator; + + LUAE_STACK_CHECKBEGIN(L); + + auto it = new (L) Iterator<IteratorType>(container.cbegin(), container.cend()); + + lua_createtable(L, 0, 0); + lua_pushcfunction(L, [] (lua_State *L) -> int { + toType<Iterator<IteratorType> *>(L, 1)->~Iterator<IteratorType>(); + + return 0; + }); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + + // Push the iterator function + lua_pushcclosure(L, [] (lua_State *L) -> int { + auto it = toType<Iterator<IteratorType> *>(L, lua_upvalueindex(1)); + + if (it->current == it->end) + return 0; + + Converter::push(L, *(it->current++)); + + return 1; + }, 1); + + LUAE_STACK_CHECKEND(L, -1); + + return 1; + } + + /** * Convert a new placement made object, without testing if its a real * object. * @@ -635,6 +737,30 @@ return *static_cast<Ptr<T> *>(lua_touserdata(L, index)); } + + /** + * Delete the shared pointer at the given index. This function does + * not check if the type is valid for performance reason. And because + * it's usually called in __gc, there is no reason to check. + * + * Also return 0 the __gc method can directly call + * return LuaeClass::deleteShared(...) + * + * @param L the Lua state + * @param index the index + * @return 0 for convenience + */ + template <typename T> + static int deleteShared(lua_State *L, int index) + { + LUAE_STACK_CHECKBEGIN(L); + + Luae::toType<Ptr<T> *>(L, index)->~shared_ptr<T>(); + + LUAE_STACK_CHECKEQUALS(L); + + return 0; + } }; /* }}} */ @@ -758,8 +884,12 @@ const std::string &meta, LuaeClass::Ptr<T> o) { + LUAE_STACK_CHECKBEGIN(L); + LuaeClass::pushShared(L, o, meta); LuaeTable::setfield(L, (index < 0) ? --index : index, name); + + LUAE_STACK_CHECKEQUALS(L); } /** @@ -773,6 +903,8 @@ template <typename T> static T require(lua_State *L, int idx, const std::string &name) { + LUAE_STACK_CHECKBEGIN(L); + lua_getfield(L, idx, name.c_str()); if (lua_type(L, -1) == LUA_TNIL) @@ -780,8 +912,11 @@ // NOT REACHED lua_pop(L, 1); + auto v = get<T>(L, idx, name); - return get<T>(L, idx, name); + LUAE_STACK_CHECKEQUALS(L); + + return v; } /**