Mercurial > code
changeset 263:fb91d4dc046b
Removal of Luae
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 14 Oct 2014 09:14:33 +0200 |
parents | a9946b5ca0cb |
children | 02aea4deed32 |
files | C++/Lua/LuaSocket.cpp C++/Lua/LuaSocket.h C++/Luae.cpp C++/Luae.h C++/LuaeClass.cpp C++/LuaeClass.h C++/LuaeEnum.cpp C++/LuaeEnum.h C++/LuaeState.cpp C++/LuaeState.h C++/LuaeTable.cpp C++/LuaeTable.h C++/LuaeVariant.cpp C++/LuaeVariant.h |
diffstat | 14 files changed, 0 insertions(+), 3624 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/Lua/LuaSocket.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,829 +0,0 @@ -/* - * LuaSocket.cpp -- Lua bindings for Sockets - * - * Copyright (c) 2013 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <cerrno> -#include <cstdlib> -#include <cstring> -#include <stdexcept> -#include <unordered_map> - -#include <Socket.h> -#include <SocketAddress.h> -#include <SocketListener.h> - -#include "Luae.h" -#include "LuaSocket.h" - -#define SOCKET_TYPE "Socket" -#define ADDRESS_TYPE "SocketAddress" -#define LISTENER_TYPE "SocketListener" - -namespace { - -/* --------------------------------------------------------- - * Enumerations - * --------------------------------------------------------- */ - -using EnumMap = std::unordered_map<std::string, int>; - -EnumMap createSockFamilies() -{ - EnumMap map; - - map["Inet"] = AF_INET; - map["Inet6"] = AF_INET6; - -#if !defined(_WIN32) - map["Unix"] = AF_UNIX; -#endif - - return map; -} - -EnumMap createSockTypes() -{ - EnumMap map; - - map["Stream"] = SOCK_STREAM; - map["Datagram"] = SOCK_DGRAM; - - return map; -} - -EnumMap createSockProtocols() -{ - EnumMap map; - - map["Tcp"] = IPPROTO_TCP; - map["Udp"] = IPPROTO_UDP; - map["IPv4"] = IPPROTO_IP; - map["IPv6"] = IPPROTO_IPV6; - - return map; -} - -EnumMap sockFamilies = createSockFamilies(); -EnumMap sockTypes = createSockTypes(); -EnumMap sockProtocols = createSockProtocols(); - -/* --------------------------------------------------------- - * Socket options - * --------------------------------------------------------- */ - -/* - * Windows setsockopt() says that options which takes a bool may use - * the bool type. On some Unix systems (including FreeBSD), passing - * a bool to SO_REUSEADDR for example, will result in a EINVAL. - */ -#if defined(_WIN32) - -using OptionBool = bool; -using OptionInteger = int; - -#else - -using OptionBool = int; -using OptionInteger = int; - -#endif - -enum class ArgType { - Invalid, - Boolean, - Integer -}; - -struct Option { - int m_level; - int m_optname; - ArgType m_argtype; - - Option() - : m_level(0) - , m_optname(0) - , m_argtype(ArgType::Invalid) - { - } - - Option(int level, int optname, ArgType type) - : m_level(level) - , m_optname(optname) - , m_argtype(type) - { - } -}; - -using OptionMap = std::unordered_map<std::string, - std::unordered_map<std::string, Option> - >; - -/* - * Map here the socket options from the C side to Lua. It's very - * close to the standard API. - * - * This map is used to retrieve which argument we must pass to the - * Socket::set function. It also setup the enumerations to be bound - * as tables. - */ -OptionMap mapOfOptions() -{ - OptionMap map; - - /* - * Standard sockets options SOL_SOCKET - */ - -#if defined(SO_REUSEADDR) - map["socket"]["reuse-address"] = Option(SOL_SOCKET, - SO_REUSEADDR, - ArgType::Boolean); -#endif -#if defined(SO_BROADCAST) - map["socket"]["broadcast"] = Option(SOL_SOCKET, - SO_BROADCAST, - ArgType::Boolean); -#endif -#if defined(SO_DEBUG) - map["socket"]["debug"] = Option(SOL_SOCKET, - SO_DEBUG, - ArgType::Boolean); -#endif -#if defined(SO_KEEPALIVE) - map["socket"]["keep-alive"] = Option(SOL_SOCKET, - SO_KEEPALIVE, - ArgType::Boolean); -#endif -#if defined(SO_RCVBUF) - map["socket"]["receive-buffer"] = Option(SOL_SOCKET, - SO_RCVBUF, - ArgType::Integer); -#endif - - /* - * TCP socket options - */ - -#if defined(TCP_NODELAY) - map["tcp"]["no-delay"] = Option(IPPROTO_TCP, - TCP_NODELAY, - ArgType::Boolean); -#endif - - /* - * IPv6 options - */ - -#if defined(IPV6_V6ONLY) - map["ipv6"]["v6only"] = Option(IPPROTO_IPV6, - IPV6_V6ONLY, - ArgType::Boolean); -#endif - - return map; -} - -OptionMap options = mapOfOptions(); - -/* --------------------------------------------------------- - * Socket functions - * --------------------------------------------------------- */ - -void mapToTable(lua_State *L, - const EnumMap &map, - int index, - const std::string &name) -{ - lua_createtable(L, 0, 0); - - for (auto p : map) { - lua_pushinteger(L, p.second); - lua_setfield(L, -2, p.first.c_str()); - } - - if (index < 0) - -- index; - - lua_setfield(L, index, name.c_str()); -} - -int genericReceive(lua_State *L, bool udp) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - int requested = luaL_checkinteger(L, 2); - SocketAddress *sa; - int nret; - char *data; - size_t nbread; - - /* - * This parameter only needed for UDP sockets - */ - if (udp) - sa = Luae::toType<SocketAddress *>(L, 2, ADDRESS_TYPE); - - /* - * Allocate a temporarly buffer for receiveing the data. - */ - data = static_cast<char *>(std::malloc(requested)); - if (data == nullptr) { - lua_pushnil(L); - lua_pushstring(L, std::strerror(errno)); - - return 2; - } - - try { - if (!udp) - nbread = s->recv(data, requested); - else - nbread = s->recvfrom(data, requested, *sa); - - lua_pushlstring(L, data, nbread); - - nret = 1; - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - nret = 2; - } - - std::free(data); - - return nret; -} - -int genericSend(lua_State *L, bool udp) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - const char *msg = luaL_checkstring(L, 2); - SocketAddress *sa; - long nbsent; - - /* - * This parameter only needed for UDP sockets - */ - if (udp) - sa = Luae::toType<SocketAddress *>(L, 3, ADDRESS_TYPE); - - try { - if (!udp) - nbsent = s->send(msg, strlen(msg)); - else - nbsent = s->sendto(msg, strlen(msg), *sa); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - lua_pushnumber(L, nbsent); - - return 1; -} - -int socketNew(lua_State *L) -{ - int domain; - int type = SOCK_STREAM; - int protocol = 0; - - // Domain is the only one mandatory - domain = luaL_checkinteger(L, 1); - - if (lua_gettop(L) >= 2) - type = luaL_checkinteger(L, 2); - if (lua_gettop(L) >= 3) - protocol = luaL_checkinteger(L, 3); - - try { - new (L, SOCKET_TYPE) Socket(domain, type, protocol); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - return 1; -} - -int socketBlockMode(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - bool mode = lua_toboolean(L, 2); - - try { - s->blockMode(mode); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - lua_pushboolean(L, true); - - return 1; -} - -int socketBind(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - SocketAddress *a = Luae::toType<SocketAddress *>(L, 2, ADDRESS_TYPE); - - /* - * Get nil + error message for chained expression like: - * s:bind(address.bindInet { port = 80, family = 1 }) - */ - if (lua_type(L, 1) == LUA_TNIL && lua_type(L, 2) == LUA_TSTRING) { - lua_pushnil(L); - lua_pushvalue(L, 2); - - return 2; - } - - try { - s->bind(*a); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - lua_pushboolean(L, true); - - return 1; -} - -int socketClose(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - - s->close(); - - return 0; -} - -int socketConnect(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - SocketAddress *a = Luae::toType<SocketAddress *>(L, 2, ADDRESS_TYPE); - - /* - * Get nil + error message for chained expression like: - * s:bind(address.bindInet { port = 80, family = 1 }) - */ - if (lua_type(L, 1) == LUA_TNIL && lua_type(L, 2) == LUA_TSTRING) { - lua_pushnil(L); - lua_pushvalue(L, 2); - - return 2; - } - - try { - s->connect(*a); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - lua_pushboolean(L, true); - - return 1; -} - -int socketAccept(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - Socket client; - SocketAddress info; - - try { - client = s->accept(info); - new (L, SOCKET_TYPE) Socket(client); - new (L, ADDRESS_TYPE) SocketAddress(info); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 3; - } - - return 2; -} - -int socketListen(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - int max = 64; - - if (lua_gettop(L) >= 2) - max = luaL_checkinteger(L, 2); - - try { - s->listen(max); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - lua_pushboolean(L, true); - - return 1; -} - -int socketReceive(lua_State *L) -{ - return genericReceive(L, false); -} - -int socketReceiveFrom(lua_State *L) -{ - return genericReceive(L, true); -} - -int socketSend(lua_State *L) -{ - return genericSend(L, false); -} - -int socketSendTo(lua_State *L) -{ - return genericSend(L, true); -} - -int socketSet(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - const char *lvl = luaL_checkstring(L, 2); - const char *nm = luaL_checkstring(L, 3); - int nret; - - try { - OptionBool bvalue; - OptionInteger ivalue; - void *ptr = nullptr; - size_t size; - - auto o = options.at(lvl).at(nm); - - switch (o.m_argtype) { - case ArgType::Boolean: - bvalue = lua_toboolean(L, 4); - ptr = static_cast<void *>(&bvalue); - size = sizeof (OptionBool); - break; - case ArgType::Integer: - ivalue = luaL_checkinteger(L, 4); - ptr = static_cast<void *>(&ivalue); - size = sizeof (OptionInteger); - break; - default: - break; - } - - if (ptr != nullptr) - s->set(o.m_level, o.m_optname, ptr, size); - lua_pushboolean(L, true); - - nret = 1; - } catch (std::out_of_range) { - lua_pushnil(L); - lua_pushstring(L, "invalid level or option name"); - - nret = 2; - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - nret = 2; - } - - return nret; -} - -int sockEq(lua_State *L) -{ - Socket *s1 = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - Socket *s2 = Luae::toType<Socket *>(L, 2, SOCKET_TYPE); - - lua_pushboolean(L, *s1 == *s2); - - return 1; -} - -int sockToString(lua_State *L) -{ - Socket *s = Luae::toType<Socket *>(L, 1, SOCKET_TYPE); - - lua_pushfstring(L, "socket %d", s->getType()); - - return 1; -} - -int sockGc(lua_State *L) -{ - Luae::toType<Socket *>(L, 1, SOCKET_TYPE)->~Socket(); - - return 0; -} - -const luaL_Reg sockFunctions[] = { - { "new", socketNew }, - { nullptr, nullptr } -}; - -const luaL_Reg sockMethods[] = { - { "blockMode", socketBlockMode }, - { "bind", socketBind }, - { "close", socketClose }, - { "connect", socketConnect }, - { "accept", socketAccept }, - { "listen", socketListen }, - { "receive", socketReceive }, - { "receiveFrom", socketReceiveFrom }, - { "send", socketSend }, - { "sendTo", socketSendTo }, - { "set", socketSet }, - { nullptr, nullptr } -}; - -const luaL_Reg sockMeta[] = { - { "__eq", sockEq }, - { "__tostring", sockToString }, - { "__gc", sockGc }, - { nullptr, nullptr } -}; - -/* --------------------------------------------------------- - * Socket address functions - * --------------------------------------------------------- */ - -int addrConnectInet(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - - std::string host = LuaeTable::require<std::string>(L, 1, "host"); - int port = LuaeTable::require<int>(L, 1, "port"); - int family = LuaeTable::require<int>(L, 1, "family"); - - try { - new (L, ADDRESS_TYPE) ConnectAddressIP(host, port, family); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - return 1; -} - -int addrBindInet(lua_State *L) -{ - std::string address = "*"; - int port, family; - - luaL_checktype(L, 1, LUA_TTABLE); - - // Mandatory fields - port = LuaeTable::require<int>(L, 1, "port"); - family = LuaeTable::require<int>(L, 1, "family"); - - // Optional fields - if (LuaeTable::type(L, 1, "address") == LUA_TSTRING) - address = LuaeTable::require<std::string>(L, 1, "address"); - - try { - new (L, ADDRESS_TYPE) BindAddressIP(address, port, family); - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - return 2; - } - - return 1; -} - -#if !defined(_WIN32) - -int addrUnix(lua_State *L) -{ - const char *path = luaL_checkstring(L, 1); - bool rem = false; - - if (lua_gettop(L) >= 2) - rem = lua_toboolean(L, 2); - - new (L, ADDRESS_TYPE) AddressUnix(path, rem); - - return 1; -} - -#endif - -int addrToString(lua_State *L) -{ - SocketAddress *sa = Luae::toType<SocketAddress *>(L, 1, ADDRESS_TYPE); - - lua_pushfstring(L, "address of length %d", sa->length()); - - return 1; -} - -int addrGc(lua_State *L) -{ - Luae::toType<SocketAddress *>(L, 1, ADDRESS_TYPE)->~SocketAddress(); - - return 0; -} - -const luaL_Reg addrFunctions[] = { - { "connectInet", addrConnectInet }, - { "bindInet", addrBindInet }, -#if !defined(_WIN32) - { "unix", addrUnix }, -#endif - { nullptr, nullptr } -}; - -const luaL_Reg addrMeta[] = { - { "__tostring", addrToString }, - { "__gc", addrGc }, - { nullptr, nullptr } -}; - -/* --------------------------------------------------------- - * Socket listener functions - * --------------------------------------------------------- */ - -int listenerNew(lua_State *L) -{ - new (L, LISTENER_TYPE) SocketListener(); - - return 1; -} - -int listenerAdd(lua_State *L) -{ - SocketListener *l = Luae::toType<SocketListener *>(L, 1, LISTENER_TYPE); - Socket *s = Luae::toType<Socket *>(L, 2, SOCKET_TYPE); - - l->add(*s); - - return 0; -} - -int listenerRemove(lua_State *L) -{ - SocketListener *l = Luae::toType<SocketListener *>(L, 1, LISTENER_TYPE); - Socket *s = Luae::toType<Socket *>(L, 2, SOCKET_TYPE); - - l->remove(*s); - - return 0; -} - -int listenerClear(lua_State *L) -{ - Luae::toType<SocketListener *>(L, 1, LISTENER_TYPE)->clear(); - - return 0; -} - -int listenerSelect(lua_State *L) -{ - SocketListener *l = Luae::toType<SocketListener *>(L, 1, LISTENER_TYPE); - int seconds = 0, ms = 0, nret; - - if (lua_gettop(L) >= 2) - seconds = luaL_checkinteger(L, 2); - if (lua_gettop(L) >= 3) - ms = luaL_checkinteger(L, 3); - - try { - Socket selected = l->select(seconds, ms); - new (L, SOCKET_TYPE) Socket(selected); - - nret = 1; - } catch (SocketError error) { - lua_pushnil(L); - lua_pushstring(L, error.what()); - - nret = 2; - } catch (SocketTimeout timeout) { - lua_pushnil(L); - lua_pushstring(L, timeout.what()); - - nret = 2; - } - - return nret; -} - -int listenerToStr(lua_State *L) -{ - SocketListener *l = Luae::toType<SocketListener *>(L, 1, LISTENER_TYPE); - - lua_pushfstring(L, "listener of %d clients", l->size()); - - return 1; -} - -int listenerGc(lua_State *L) -{ - Luae::toType<SocketListener *>(L, 1, LISTENER_TYPE)->~SocketListener(); - - return 0; -} - -const luaL_Reg listenerFunctions[] = { - { "new", listenerNew }, - { nullptr, nullptr } -}; - -const luaL_Reg listenerMethods[] = { - { "add", listenerAdd }, - { "remove", listenerRemove }, - { "clear", listenerClear }, - { "select", listenerSelect }, - { nullptr, nullptr } -}; - -const luaL_Reg listenerMeta[] = { - { "__tostring", listenerToStr }, - { "__gc", listenerGc }, - { nullptr, nullptr } -}; - -} - -int luaopen_socket(lua_State *L) -{ - // Socket functions - luaL_newlib(L, sockFunctions); - - // Map families, types - mapToTable(L, sockFamilies, -1, "family"); - mapToTable(L, sockTypes, -1, "type"); - mapToTable(L, sockProtocols, -1, "protocol"); - - // Create Socket type - luaL_newmetatable(L, SOCKET_TYPE); - luaL_setfuncs(L, sockMeta, 0); - luaL_newlib(L, sockMethods); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - return 1; -} - -int luaopen_socket_address(lua_State *L) -{ - luaL_newlib(L, addrFunctions); - - // Create SocketAddress type - luaL_newmetatable(L, ADDRESS_TYPE); - luaL_setfuncs(L, addrMeta, 0); - lua_pop(L, 1); - - return 1; -} - -int luaopen_socket_listener(lua_State *L) -{ - luaL_newlib(L, listenerFunctions); - - // Create the SocketListener type - luaL_newmetatable(L, LISTENER_TYPE); - luaL_setfuncs(L, listenerMeta, 0); - luaL_newlib(L, listenerMethods); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - return 1; -}
--- a/C++/Lua/LuaSocket.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * LuaSocket.h -- Lua bindings for sockets - * - * Copyright (c) 2013 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUA_SOCKET_H_ -#define _LUA_SOCKET_H_ - -#include <lua.hpp> - -namespace irccd -{ - -int luaopen_socket(lua_State *L); -int luaopen_socket_address(lua_State *L); -int luaopen_socket_listener(lua_State *L); - -} // !irccd - -#endif // !_LUA_SOCKET_H_
--- a/C++/Luae.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * Luae.cpp -- Lua helpers and such - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "Luae.h" - -void Luae::doexecute(lua_State *L, int status) -{ - if (status != LUA_OK) { - auto error = lua_tostring(L, -1); - lua_pop(L, 1); - - throw std::runtime_error(error); - } -} - -void Luae::assertBegin(lua_State *L) -{ -#if !defined(NDEBUG) - lua_pushinteger(L, lua_gettop(L)); - lua_setfield(L, LUA_REGISTRYINDEX, FieldTop); -#endif -} - -void Luae::assertEnd(lua_State *L, int expected) -{ -#if !defined(NDEBUG) - lua_getfield(L, LUA_REGISTRYINDEX, FieldTop); - if (lua_type(L, -1) == LUA_TNIL) - luaL_error(L, "stack verification without top field, call assertBegin"); - // NOTREACHED - - auto before = lua_tointeger(L, -1); - lua_pop(L, 1); - - if (before != (gettop(L) - expected)) - luaL_error(L, "stack size error: expected %d, got %d", expected, gettop(L) - before); - // NOTREACHED - - lua_pushnil(L); - lua_setfield(L, LUA_REGISTRYINDEX, FieldTop); -#endif -} - -void Luae::preload(lua_State *L, const std::string &name, lua_CFunction func) -{ - assertBegin(L); - - lua_getglobal(L, "package"); - lua_getfield(L, -1, "preload"); - lua_pushcfunction(L, func); - lua_setfield(L, -2, name.c_str()); - lua_pop(L, 2); - - assertEnd(L, 0); -} - -void Luae::require(lua_State *L, const std::string &name, lua_CFunction func) -{ - assertBegin(L); - - luaL_requiref(L, name.c_str(), func, false); - lua_pop(L, 1); - - assertEnd(L, 0); -} - -void *operator new(size_t size, lua_State *L) -{ - return lua_newuserdata(L, size); -} - -void *operator new(size_t size, lua_State *L, const char *metaname) -{ - void *object; - - object = lua_newuserdata(L, size); - luaL_setmetatable(L, metaname); - - return object; -} - -void operator delete(void *, lua_State *) -{ -} - -void operator delete(void *, lua_State *L, const char *) -{ - lua_pushnil(L); - lua_setmetatable(L, -2); -}
--- a/C++/Luae.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1738 +0,0 @@ -/* - * Luae.h -- Lua helpers and such - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUAE_H_ -#define _LUAE_H_ - -/** - * @file Luae.h - * @brief Lua C++ extended API - */ - -#include <memory> -#include <stdexcept> -#include <string> -#include <type_traits> -#include <unordered_map> - -#include <lua.hpp> - -/** - * @class Luae - * @brief Add lot of convenience for Lua - * - * This class adds lot of functions for Lua and C++. - */ -class Luae { -public: - /* - * These fields are stored in the Lua registry. - * - * FieldRefs - this one is used to reference shared_ptr to reuse - * objects and avoid new creation. - * FieldTop - this field store the current stack size and is used - * with assertBegin and assertEnd. - * FieldClasses - this field store the table of created classes. It is used - * to verify type cast of LuaeClass'es. - */ - static constexpr const char *FieldRefs = "__luae_refs"; - static constexpr const char *FieldTop = "__luae_topcheck"; - static constexpr const char *FieldClasses = "__luae_classes"; - - /* - * These fields are stored in the metatable of the object. - * - * FieldName - this is the field stored in the metatable to get the real - * userdata type. - */ - static constexpr const char *FieldName = "__luea_name"; - -private: - /* - * Wrapper for dofile and dostring. - */ - static void doexecute(lua_State *L, int status); - -public: - /** - * Map from string to function. - */ - using Reg = std::unordered_map<const char *, lua_CFunction>; - - /** - * ## Userdata object - * - * Test if the object can be pushed as a userdata. If the object can - * be pushed as a userdata, it must match the following requirements: - * - * - Copy constructible - * - Move constructible (at least) - * - TypeInfo overload must have const char *name and inherit TypeUserdata - * - * The following example code allows the class Object to be pushed - * and get as Lua userdata. - * - * @code - * struct Object { }; - * - * template <> - * struct Luae::TypeInfo<Object> : Luae::TypeUserdata { - * static constexpr const char *name = "Object"; - * }; - * - * int l_push(lua_State *L) - * { - * Luae::push(L, Object()); - * } - * - * int l_get(lua_State *L) - * { - * Object *o = Luae::get<Object>(L, 1); - * } - * @endcode - * - * @note You don't need to add the pointer type to the get template parameter - * - * ## Custom object - * - * This other example can be used to push custom objects but not as - * userdata. You can use this to push and read tables for instance. - * - * For this you must overload TypeInfo to the object and inherit to TypeCustom. - * - * @code - * struct Point { - * int x, y; - * }; - * - * template <> - * struct Luae::TypeInfo<Point> : Luae::TypeCustom { - * static void push(lua_State *L, const Point &p) - * { - * lua_createtable(L, 0, 0); - * lua_pushinteger(L, p.x); - * lua_setfield(L, -2, "x"); - * lua_pushinteger(L, p.y); - * lua_setfield(L, -2, "y"); - * } - * - * static Point get(lua_State *L, int index) - * { - * Point p; - * - * if (lua_type(L, index) == LUA_TTABLE) { - * lua_getfield(L, index, "x"); - * p.x = lua_tonumber(L, -1); - * lua_pop(L, 1); - * lua_getfield(L, index, "y"); - * p.y = lua_tonumber(L, -1); - * lua_pop(L, 1); - * } - * - * return p; - * } - * - * static Point check(lua_State *L, int index) - * { - * // Do your check - * - * return get(L, index); - * } - * - * static Point optional(lua_State *L, int index, const Point &def) - * { - * // Do your check or return def - * } - * }; - * - * int l_push(lua_State *L) - * { - * Luae::push<Point>(L, Point {1, 2}); - * } - * - * int l_get(lua_State *L) - * { - * Point p = Luae::get<Point>(L, 1); - * } - * @endcode - * - * @note Here you get a T and not a T * - */ - template <typename T> - struct TypeInfo { - static const bool isCustom = false; - static const bool isUserdata = false; - }; - - /** - * Helpers for custom types. It is already overloaded for all standard - * types : - * - int - * - bool - * - double - * - std::string - * - std::32string - */ - struct TypeCustom { - static const bool canGet = true; - static const bool canPush = true; - static const bool canCheck = true; - static const bool canOptional = true; - static const bool isCustom = true; - static const bool isUserdata = false; - }; - - /** - * Helper for userdata. It only require to set the name field - * as the metatable name. - */ - struct TypeUserdata { - static const bool isUserdata = true; - static const bool isCustom = false; - }; - -private: - /* Tests */ - template <typename T> - struct IsCustom { - static const bool value = TypeInfo<T>::isCustom; - }; - - template <typename T> - struct IsUserdata { - static const bool value = TypeInfo<T>::isUserdata; - }; - - template <typename T> - struct IsSharedUserdata : std::false_type { }; - - template <typename T> - struct IsSharedUserdata<std::shared_ptr<T>> { - static const bool value = TypeInfo<T>::isUserdata; - }; - - /* Helpers */ - template <bool Cond, typename Type = void> - using EnableIf = typename std::enable_if<Cond, Type>::type; - - template <typename T> - using SharedType = typename T::element_type; - -public: - /* ------------------------------------------------- - * Standard Lua API wrappers - * ------------------------------------------------- */ - - /** - * Calls a Lua function in non-protected mode. - * - * @param L the Lua state - * @param np the number of parameters - * @param nr the number of return values - */ - static inline void call(lua_State *L, int np = 0, int nr = 0) - { - lua_call(L, np, nr); - } - - /** - * Ensure that there are at least extra free stack slots in the stack. - * - * @param L the Lua state - * @param extra the extra data - * @return true if possible - */ - static inline int checkstack(lua_State *L, int extra) - { - return lua_checkstack(L, extra); - } - - /** - * Check the type at the given index. Calls luaL_error on bad - * type. - * - * @param L the Lua state - * @param index the the index - * @param type the type to check - */ - static inline void checktype(lua_State *L, int index, int type) - { - luaL_checktype(L, index, type); - } - - /** - * Compares two Lua values. - * - * Operation is one of: - * - * * LUA_OPEQ, - * * LUA_OPLT, - * * LUA_OPLE - * - * @param L the Lua state - * @param index1 the first value - * @param index2 the second value - * @param op the operation - * @return true if index1 statisfies op compared to index2 - */ - static inline bool compare(lua_State *L, int index1, int index2, int op) - { - return lua_compare(L, index1, index2, op) == 1; - } - - /** - * Concatenate the n values at the top of the stack and pops them. - * Leaves the result at the top of the stack. - * - * @param L the Lua state - * @param n the number to concat - */ - static inline void concat(lua_State *L, int n) - { - lua_concat(L, n); - } - - /** - * Moves the element at the index from into the valid index to. - * - * @param L the Lua state - * @param from the from index - * @param to the destination index - */ - static inline void copy(lua_State *L, int from, int to) - { - lua_copy(L, from, to); - } - - /** - * Create a table. - * - * @param L the Lua state - * @param nr the number of array record - * @param ns the number of sequence - */ - static inline void createtable(lua_State *L, int nr = 0, int ns = 0) - { - lua_createtable(L, nr, ns); - } - - /** - * Load and execute a file. - * - * @param L the Lua state - * @param path the the path - * @throw std::runtime_error on error - */ - static inline void dofile(lua_State *L, const std::string &path) - { - doexecute(L, luaL_dofile(L, path.c_str())); - } - - /** - * Load and execute a string. - * - * @param L the Lua state - * @param data the data - * @throw std::runtime_error on error - */ - static inline void dostring(lua_State *L, const std::string &data) - { - doexecute(L, luaL_dostring(L, data.c_str())); - } - - /** - * Generate an error with the string at the top of the stack. - * - * @param L the Lua state - * @return nothing - */ - static inline int error(lua_State *L) - { - return lua_error(L); - } - - /** - * Raises a Lua error, thus calling longjmp. - * - * @param L the Lua state - * @param fmt the format - * @param args the arguments - * @return nothing - */ - template <typename... Args> - static inline int error(lua_State *L, const char *fmt, Args&&... args) - { - return luaL_error(L, fmt, std::forward<Args>(args)...); - } - - /** - * Controls the garbage collector. - * - * @param L the Lua state - * @param what the action - * @param data optional GC data - */ - static inline int gc(lua_State *L, int what, int data = 0) - { - return lua_gc(L, what, data); - } - - /** - * Get a field at the given index. - * - * @param L the Lua state - * @param idx the table index - * @param name the field name - */ - static inline void getfield(lua_State *L, int idx, const std::string &name) - { - lua_getfield(L, idx, name.c_str()); - } - - /** - * Get a global value from Lua. - * - * @param L the Lua state - * @param name the value name - */ - static inline void getglobal(lua_State *L, const std::string &name) - { - lua_getglobal(L, name.c_str()); - } - - /** - * Check if the object at index idx has a field in its metatable. - * - * @param L the Lua state - * @param idx the object index - * @param name the name - * @return true if has the field - */ - static inline bool getmetafield(lua_State *L, int idx, const std::string &name) - { - return luaL_getmetafield(L, idx, name.c_str()); - } - - /** - * Get the metatable of the value at the given index. Returns false - * if does not have a metatable and pushes nothing. - * - * @param L the Lua state - * @param index the value index - */ - static inline bool getmetatable(lua_State *L, int index) - { - return lua_getmetatable(L, index) == 1; - } - - /** - * Set the value at the given index. Top value is the value to assign - * key is just below the value. - * - * @param L the Lua state - * @param index the value index - */ - static inline void gettable(lua_State *L, int index) - { - lua_gettable(L, index); - } - - /** - * Get the current stack size. - * - * @param L the Lua state - * @return the stack size - */ - static inline int gettop(lua_State *L) - { - return lua_gettop(L); - } - - /** - * Pushes the Lua value associated with the userdata. - * - * @param L the Lua state - * @param index the value index - */ - static inline void getuservalue(lua_State *L, int index) - { - lua_getuservalue(L, index); - } - - /** - * Move the top element at the given index. - * - * @param L the Lua state - * @param index the new index - */ - static inline void insert(lua_State *L, int index) - { - lua_insert(L, index); - } - - /** - * Push the result of the operator '#' from the value at the given - * index. - * - * @param L the Lua state - * @param index the value index - */ - static inline void len(lua_State *L, int index) - { - lua_len(L, index); - } - - /** - * Create or get a metatable in the registry. - * - * @param L the Lua state - * @param name the metatable name - */ - static inline void newmetatable(lua_State *L, const std::string &name) - { - luaL_newmetatable(L, name.c_str()); - } - - /** - * Create a new table and fill it with functions. - * - * @param L the Lua state - * @param functions the functions - */ - static inline void newlib(lua_State *L, const luaL_Reg *functions) - { - lua_createtable(L, 0, 0); - luaL_setfuncs(L, functions, 0); - } - - /** - * Create a new table and fill it with functions. - * - * @param L the Lua state - * @param functions the functions - */ - static inline void newlib(lua_State *L, const Reg &functions) - { - lua_createtable(L, 0, 0); - for (auto &p : functions) { - lua_pushcfunction(L, p.second); - lua_setfield(L, -2, p.first); - } - } - - /** - * Create a new table on the stack. - * - * @param L the Lua state - */ - static inline void newtable(lua_State *L) - { - lua_newtable(L); - } - - /** - * Pops a key from the stack and pushes a key-value pair from the table - * at the given index. - * - * @param L the Lua state - * @param index the table index - * @return true if there are still elements - */ - static inline bool next(lua_State *L, int index) - { - return lua_next(L, index) == 1; - } - - /** - * Load all Lua libraries. - * - * @param L the Lua state - */ - static inline void openlibs(lua_State *L) - { - luaL_openlibs(L); - } - - /** - * Wrapper around pcall, throw instead of returning an error code. - * - * @param L the Lua state - * @param np the number of parameters - * @param nr the number of return value - * @param error the message handler - */ - static inline void pcall(lua_State *L, int np, int nr, int error = 0) - { - if (lua_pcall(L, np, nr, error) != LUA_OK) { - auto error = lua_tostring(L, -1); - lua_pop(L, 1); - - throw std::runtime_error(error); - } - } - - /** - * Pop arguments from the stack. - * - * @param L the Lua state - * @param count the number of values to pop - */ - static inline void pop(lua_State *L, int count = 1) - { - lua_pop(L, count); - } - - /** - * Pushes a copy of the value at the given index. - * - * @param L the Lua state - * @param index the value to copy - */ - static inline void pushvalue(lua_State *L, int index) - { - lua_pushvalue(L, index); - } - - /** - * Returns true if the values are primitively equal. - * - * @param L the Lua state - * @param index1 the first value - * @param index2 the second value - * @return true if they equals - */ - static inline bool rawequal(lua_State *L, int index1, int index2) - { - return lua_rawequal(L, index1, index2) == 1; - } - - /** - * Like gettable but with raw access. - * - * @param L the Lua state - * @param index the value index - */ - static inline void rawget(lua_State *L, int index) - { - lua_rawget(L, index); - } - - /** - * Like gettable but with raw access. - * - * @param L the Lua state - * @param index the value index - * @param n the nt - */ - static inline void rawget(lua_State *L, int index, int n) - { - lua_rawgeti(L, index, n); - } - - /** - * Like rawgeti but with pointer. - * - * @param L the Lua state - * @param index the value index - * @param p the pointer key - */ - static inline void rawget(lua_State *L, int index, const void *p) - { - lua_rawgetp(L, index, p); - } - - /** - * Get the value length. - * - * @param L the Lua state - * @param index the value index - * @return the raw length - */ - static inline int rawlen(lua_State *L, int index) - { - return lua_rawlen(L, index); - } - - /** - * Similar to settable but without raw assignment. - * - * @param L the Lua state - * @param index the value index - */ - static inline void rawset(lua_State *L, int index) - { - lua_rawset(L, index); - } - - /** - * Set the value at the top of stack to the ntn value at the value - * at the given index. - * - * @param L the Lua state - * @param index the value index - * @param n the nth index - */ - static inline void rawset(lua_State *L, int index, int n) - { - lua_rawseti(L, index, n); - } - - /** - * Like rawseti with a void pointer as the key. - * - * @param L the Lua state - * @param index the value index - * @param ptr the pointer key - */ - static inline void rawset(lua_State *L, int index, const void *ptr) - { - lua_rawsetp(L, index, ptr); - } - - /** - * Push a formatted string like lua_pushfstring. Warning, it is not type - * safe and you should for instance not pass std::String to %s. - * - * @param L the Lua state - * @param fmt the format - * @param args the arguments - * @return the formatted string - */ - template <typename... Args> - static inline const char *pushfstring(lua_State *L, const char *fmt, Args&&... args) - { - return lua_pushfstring(L, fmt, std::forward<Args>(args)...); - } - - /** - * 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); - } - - /** - * Create a unique reference to the table at the given index. - * - * @param L the Lua state - * @param index the table index - * @return the reference - */ - static inline int ref(lua_State *L, int index) - { - return luaL_ref(L, index); - } - - /** - * Remove the element at the given index. - * - * @param L the Lua state - * @param index the table index - */ - static inline void remove(lua_State *L, int index) - { - lua_remove(L, index); - } - - /** - * Replace the element at the given index by the one at the top. - * - * @param L the Lua state - * @param index the new index - */ - static inline void replace(lua_State *L, int index) - { - lua_replace(L, index); - } - - /** - * Set a field to the table at the given index. - * - * @param L the Lua state - * @param idx the table index - * @param name the field name - * @see set - */ - static inline void setfield(lua_State *L, int idx, const std::string &name) - { - lua_setfield(L, idx, name.c_str()); - } - - /** - * Set the functions to the table at the top of stack. - * - * @param L the Lua state - * @param functions the functions - * @param nup the number of upvalues - */ - static inline void setfuncs(lua_State *L, const luaL_Reg *functions, int nup = 0) - { - luaL_setfuncs(L, functions, nup); - } - - /** - * Set the functions to the table at the top of stack. - * - * @param L the Lua state - * @param functions the functions - * @param nup the number of upvalues - */ - static inline void setfuncs(lua_State *L, const Reg &functions, int nup = 0) - { - luaL_checkversion(L); - luaL_checkstack(L, nup, "too many upvalues"); - - for (auto &l : functions) { - for (int i = 0; i < nup; i++) - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l.second, nup); - lua_setfield(L, -(nup + 2), l.first); - } - - lua_pop(L, nup); - } - - /** - * 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()); - } - - /** - * Pops the table at the top of the stack and sets it as the metatable - * of the value at the given index. - * - * @param L the Lua state - * @param index the value index - */ - static inline void setmetatable(lua_State *L, int index) - { - lua_setmetatable(L, index); - } - - /** - * Does t[n] where n is the value at the top of the stack and the key - * just below the value. - * - * @param L the Lua state - * @param index the value index - */ - static inline void settable(lua_State *L, int index) - { - lua_settable(L, index); - } - - /** - * Set the stack size. - * - * @param L the Lua state - * @param index the index - */ - static inline void settop(lua_State *L, int index = 0) - { - lua_settop(L, index); - } - - /** - * Pops a table or nil from the top stack and set it as the new - * associated value to the userdata. - * - * @param L the Lua state - * @param index the userdata index - */ - static inline void setuservalue(lua_State *L, int index) - { - lua_setuservalue(L, index); - } - - /** - * Get the type at the given index. - * - * @param L the Lua state - * @param index the value index - * @return the type - */ - static inline int type(lua_State *L, int index) - { - return lua_type(L, index); - } - - /** - * Get the type name. - * - * @param L the Lua state - * @param type the type - * @return the name - * @see type - */ - static inline const char *typeName(lua_State *L, int type) - { - return lua_typename(L, type); - } - - /** - * Get the type name from a index. - * - * @param L the Lua state - * @param index the value index - * @return the name - */ - static inline const char *typeNamei(lua_State *L, int index) - { - return luaL_typename(L, index); - } - - /** - * Unref the value from the table. - * - * @param L the Lua state - * @param index the table index - * @param ref the reference - */ - static inline void unref(lua_State *L, int index, int ref) - { - luaL_unref(L, index, ref); - } - - /** - * Get the up value index. - * - * @param index the index - * @return the real index - */ - static inline int upvalueindex(int index) - { - return lua_upvalueindex(index); - } - - /* ------------------------------------------------- - * Extended API - * ------------------------------------------------- */ - - /** - * Call this prior to assertEnd. - * - * @param L the Lua state - */ - static void assertBegin(lua_State *L); - - /** - * Call this to check the stack size after asserBegin. The stack size - * is automatically adjusted to the last size so the expected argument - * can just be set to the real expected size just like if the stack size - * were 0. - * - * @param L the Lua state - * @param expected the stack size expected - */ - static void assertEnd(lua_State *L, int expected); - - /** - * 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. - * - * @param L the Lua state - * @param name the module name - * @param func the opening library - * @see require - */ - static void preload(lua_State *L, const std::string &name, lua_CFunction func); - - /** - * Load a library just like it was loaded with require. - * - * @param L the Lua state - * @param name the module name - * @param func the function - */ - static void require(lua_State *L, const std::string &name, lua_CFunction func); - - /** - * Push a custom type to Lua. - * - * @param L the Lua state - * @param value the value - * @return 1 - */ - template <typename T> - static int push(lua_State *L, - const T &value, - EnableIf<IsCustom<T>::value, T> * = 0) - { - static_assert(TypeInfo<T>::canPush, "type not supported"); - - TypeInfo<T>::push(L, value); - - return 1; - } - - /** - * Push a userdata to Lua. - * - * @param L the Lua state - * @param value the value - * @return 1 - */ - template <typename T> - static int push(lua_State *L, - const T &value, - EnableIf<IsUserdata<T>::value, T> * = 0) - { - new (L, TypeInfo<T>::name) T(value); - - return 1; - } - - /** - * Push a userdata as a shared pointer. - * - * @param L the Lua state - * @param value the value - */ - template <typename T> - static int push(lua_State *L, - const std::shared_ptr<T> &value, - EnableIf<IsSharedUserdata<std::shared_ptr<T>>::value, T> * = 0) - { - assertBegin(L); - - /* - * If already in the registry use the same shared_ptr to get the same - * pointer address within Lua. This let scripts using the object - * as a table key for instance. - */ - getfield(L, LUA_REGISTRYINDEX, FieldRefs); - if (type(L, -1) == LUA_TNIL) { - pop(L); - createtable(L, 0, 0); - createtable(L, 0, 0); - pushfstring(L, "v"); - setfield(L, -2, "__mode"); - setmetatable(L, -2); - pushvalue(L, -1); - setfield(L, LUA_REGISTRYINDEX, FieldRefs); - } - - /* - * Not already existing? Create and return it. - */ - rawget(L, -1, value.get()); - if (type(L, -1) == LUA_TNIL) { - pop(L); - new (L, TypeInfo<T>::name) std::shared_ptr<T>(value); - pushvalue(L, -1); - rawset(L, -3, value.get()); - } - - // Remove refs table - remove(L, -2); - - return 1; - } - - /** - * Overload for string literals. - * - * @param L the Lua state - * @param s the string - * @return 1 - */ - template <size_t N> - static int push(lua_State *L, const char (&s)[N]) - { - return push<const char *>(L, s); - } - - /** - * Get a custom type without check. - * - * @param L the Lua state - * @param index the index - * @return the type value - */ - template <typename T> - static EnableIf<IsCustom<T>::value, T> - get(lua_State *L, int index) - { - static_assert(TypeInfo<T>::canGet, "type not supported"); - - return TypeInfo<T>::get(L, index); - } - - /** - * Get a userdata without check. Absolute insecure. - * - * @param L the Lua state - * @param index the index - * @return T * - */ - template <typename T> - static EnableIf<IsUserdata<T>::value, T *> - get(lua_State *L, int index) - { - return Luae::toType<T *>(L, index); - } - - /** - * Get a userdata from a shared pointer without check. - * - * @param L the Lua state - * @param index the index - * @return the std::shared_ptr - */ - template <typename T> - static EnableIf<IsSharedUserdata<T>::value, T> - get(lua_State *L, int index) - { - return *Luae::toType<T *>(L, index); - } - - /** - * Get an optional custom type. Returns the value or the - * def argument. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - template <typename T> - static EnableIf<IsCustom<T>::value, T> - optional(lua_State *L, int index, const T &def) - { - static_assert(TypeInfo<T>::canOptional, "type not supported"); - - return TypeInfo<T>::optional(L, index, def); - } - -#if 0 - /** - * Get an optional userdata, returns the userdata pointer - * or a new created one. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - template <typename T> - static EnableIf<IsUserdata<T>::value, T *> - optional(lua_State *L, int index, const T &def) - { - auto ptr = luaL_testudata(L, index, TypeInfo<T>::name); - - if (!ptr) - return new (L, TypeInfo<T>::name) T(def); - - return ptr; - } -#endif - - /** - * Get a custom type with check. - * - * @param L the Lua state - * @param index the index - * @return the type - */ - template <typename T> - static EnableIf<IsCustom<T>::value, T> - check(lua_State *L, int index) - { - static_assert(TypeInfo<T>::canCheck, "type not supported"); - - return TypeInfo<T>::check(L, index); - } - - /** - * Get a userdata with checks - * - * @param L the Lua state - * @param index the index - * @return T * - */ - template <typename T> - static EnableIf<IsUserdata<T>::value, T *> - check(lua_State *L, int index) - { - return Luae::toType<T *>(L, index, TypeInfo<T>::name); - } - - /** - * Get a userdata from a shared pointer with checks. - * - * @param L the Lua state - * @param index the index - * @return the std::shared_ptr - */ - template <typename T> - static EnableIf<IsSharedUserdata<T>::value, T> - check(lua_State *L, int index) - { - return *Luae::toType<T *>(L, index, TypeInfo<SharedType<T>>::name); - } - - /** - * Convert a new placement made object, without testing if its a real - * object. - * - * @param L the Lua state - * @param idx the object index - * @return the converted object - */ - template<class T> - static inline T toType(lua_State *L, int idx) - { - return reinterpret_cast<T>(lua_touserdata(L, idx)); - } - - /** - * - * @param L the Lua state - * @param idx the index - * @param meta the metatable name - * @return the object - */ - template <class T> - static inline T toType(lua_State *L, int idx, const char *meta) - { - assertBegin(L); - - bool isclass(false); - - if (getmetafield(L, idx, FieldName)) { - isclass = true; - auto name = lua_tostring(L, -1); - - lua_pop(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, FieldClasses); - - // No registered class - if (lua_type(L, -1) != LUA_TTABLE) { - lua_pop(L, 1); - luaL_error(L, "%s has not been registered as a class", name); - // NOTREACHED - } - - lua_getfield(L, -1, name); // classes[name] - lua_getfield(L, -1, meta); // t[meta] == true? - auto value = lua_toboolean(L, -1); - lua_pop(L, 3); - - if (!value) - luaL_error(L, "invalid cast from %s to %s", name, meta); - // NOTREACHED - } - - assertEnd(L, 0); - - /* - * If the object is a class, we don't need to check the - * metatable anymore. - */ - if (!isclass) - return reinterpret_cast<T>(luaL_checkudata(L, idx, meta)); - - return reinterpret_cast<T>(lua_touserdata(L, idx)); - } -}; - -/** - * @brief Overload for nil. - */ -template <> -struct Luae::TypeInfo<std::nullptr_t> : Luae::TypeCustom { - static const bool canGet = false; - static const bool canCheck = false; - - /** - * Push nil. - * - * @param L the Lua state - */ - static void push(lua_State *L, const std::nullptr_t &) - { - lua_pushnil(L); - } -}; - -/** - * @brief Overload for booleans. - */ -template <> -struct Luae::TypeInfo<bool> : Luae::TypeCustom { - /** - * Push the boolean value. - * - * @param L the Lua state - * @param value the value - */ - static void push(lua_State *L, const bool &value) - { - lua_pushboolean(L, value); - } - - /** - * Get a boolean. - * - * @param L the Lua state - * @param index the index - * @return a boolean - */ - static bool get(lua_State *L, int index) - { - return lua_toboolean(L, index); - } - - /** - * Check for a bool. - * - * @param L the Lua state - * @param index the index - */ - static bool check(lua_State *L, int index) - { - return lua_toboolean(L, index); - } - - /** - * Get an optional boolean. - * - * @param L the Lua state - * @param index the index - * @param def the default value if not boolean - * @return the value or def - */ - static bool optional(lua_State *L, int index, const bool &def) - { - if (lua_type(L, index) == LUA_TBOOLEAN) - return lua_toboolean(L, index); - - return def; - } -}; - -/** - * @brief Overload for integers. - */ -template <> -struct Luae::TypeInfo<int> : Luae::TypeCustom { - /** - * Push the integer value. - * - * @param L the Lua state - * @param value the value - */ - static void push(lua_State *L, const int &value) - { - lua_pushinteger(L, value); - } - - /** - * Get a integer. - * - * @param L the Lua state - * @param index the index - * @return a boolean - */ - static int get(lua_State *L, int index) - { - return lua_tointeger(L, index); - } - - /** - * Check for an integer. - * - * @param L the Lua state - * @param index the index - */ - static int check(lua_State *L, int index) - { - return luaL_checkinteger(L, index); - } - - /** - * Get an optional integer. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - static int optional(lua_State *L, int index, const int &def) - { - return luaL_optint(L, index, def); - } -}; - -/** - * @brief Overload for longs. - */ -template <> -struct Luae::TypeInfo<long> : Luae::TypeCustom { - /** - * Push the integer value. - * - * @param L the Lua state - * @param value the value - */ - static void push(lua_State *L, const long &value) - { - lua_pushinteger(L, value); - } - - /** - * Get a integer. - * - * @param L the Lua state - * @param index the index - * @return a boolean - */ - static long get(lua_State *L, int index) - { - return lua_tointeger(L, index); - } - - /** - * Check for an integer. - * - * @param L the Lua state - * @param index the index - */ - static long check(lua_State *L, int index) - { - return luaL_checkinteger(L, index); - } - - /** - * Get an optional long. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - static long optional(lua_State *L, int index, const long &def) - { - return luaL_optlong(L, index, def); - } -}; - -/** - * @brief Overload for doubles. - */ -template <> -struct Luae::TypeInfo<double> : Luae::TypeCustom { - /** - * Push the double value. - * - * @param L the Lua state - * @param value the value - */ - static void push(lua_State *L, const double &value) - { - lua_pushnumber(L, value); - } - - /** - * Get a double. - * - * @param L the Lua state - * @param index the index - * @return a boolean - */ - static double get(lua_State *L, int index) - { - return lua_tonumber(L, index); - } - - /** - * Check for a double. - * - * @param L the Lua state - * @param index the index - */ - static double check(lua_State *L, int index) - { - return luaL_checknumber(L, index); - } - - /** - * Get an optional double. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - static double optional(lua_State *L, int index, const double &def) - { - return luaL_optnumber(L, index, def); - } -}; - -/** - * @brief Overload for std::string. - */ -template <> -struct Luae::TypeInfo<std::string> : Luae::TypeCustom { - /** - * Push the string value. - * - * @param L the Lua state - * @param value the value - */ - static void push(lua_State *L, const std::string &value) - { - lua_pushlstring(L, value.c_str(), value.length()); - } - - /** - * Get a string. - * - * @param L the Lua state - * @param index the index - * @return the string or "" - */ - static std::string get(lua_State *L, int index) - { - size_t length; - const char *str = lua_tolstring(L, index, &length); - - if (!str) - return ""; - - return std::string(str, length); - } - - /** - * Check for a string. - * - * @param L the Lua state - * @param index the index - * @return the string - */ - static std::string check(lua_State *L, int index) - { - size_t length; - const char *str = luaL_tolstring(L, index, &length); - - return std::string(str, length); - } - - /** - * Get an optional string. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - static std::string optional(lua_State *L, int index, const std::string &def) - { - size_t length; - const char *str = luaL_optlstring(L, index, def.c_str(), &length); - - return std::string(str, length); - } -}; - -/** - * @brief Overload for std::u32string. - */ -template <> -struct Luae::TypeInfo<std::u32string> : Luae::TypeCustom { - /** - * Push the string value. - * - * @param L the Lua state - * @param str the value - */ - static void push(lua_State *L, const std::u32string &str) - { - lua_createtable(L, str.size(), 0); - for (size_t i = 0; i < str.size(); ++i) { - lua_pushinteger(L, str[i]); - lua_rawseti(L, -2, i + 1); - } - } - - /** - * Get a string. - * - * @param L the Lua state - * @param index the index - * @return a boolean - */ - static std::u32string get(lua_State *L, int index) - { - std::u32string result; - - if (lua_type(L, index) == LUA_TNUMBER) { - result.push_back(lua_tonumber(L, index)); - } else if (lua_type(L, index) == LUA_TTABLE) { - if (index < 0) - -- index; - - lua_pushnil(L); - while (lua_next(L, index)) { - if (lua_type(L, -1) == LUA_TNUMBER) - result.push_back(lua_tonumber(L, -1)); - - lua_pop(L, 1); - } - } - - return result; - } - - /** - * Check for a string. - * - * @param L the Lua state - * @param index the index - */ - static std::u32string check(lua_State *L, int index) - { - if (lua_type(L, index) != LUA_TNUMBER && - lua_type(L, index) != LUA_TTABLE) - luaL_error(L, "expected table or number"); - // NOTREACHED - - return get(L, index); - } - - /** - * Get an optional std::u32string. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - static std::u32string optional(lua_State *L, int index, const std::u32string &def) - { - if (lua_type(L, index) != LUA_TNUMBER && - lua_type(L, index) != LUA_TTABLE) - return def; - - return get(L, index); - } -}; - -/** - * @brief Overload for const char * - */ -template <> -struct Luae::TypeInfo<const char *> : Luae::TypeCustom { - /** - * Push the string value. - * - * @param L the Lua state - * @param value the value - */ - static void push(lua_State *L, const char *value) - { - lua_pushstring(L, value); - } - - /** - * Get a string. - * - * @param L the Lua state - * @param index the index - * @return a boolean - */ - static const char *get(lua_State *L, int index) - { - return lua_tostring(L, index); - } - - /** - * Check for a string. - * - * @param L the Lua state - * @param index the index - */ - static const char *check(lua_State *L, int index) - { - return luaL_checkstring(L, index); - } - - /** - * Get an optional C string. - * - * @param L the Lua state - * @param index the index - * @param def the default value - * @return the value or def - */ - static const char *optional(lua_State *L, int index, const char *& def) - { - return luaL_optstring(L, index, def); - } -}; - -/** - * Push a Lua userdata. - * - * @param size the object size - * @param L the Lua state - * @return the allocated data - */ -void *operator new(size_t size, lua_State *L); - -/** - * Push a Lua userdata with a metatable. - * - * @param size the object size - * @param L the Lua state - * @param metaname the metatable name - * @return the allocated data - */ -void *operator new(size_t size, lua_State *L, const char *metaname); - -/** - * Delete the Lua userdata. - * - * @param ptr the data - * @param L the Lua state - */ -void operator delete(void *ptr, lua_State *L); - -/** - * Delete the Lua userdata. - * - * @param ptr the data - * @param L the Lua state - * @param metaname the metatable name - */ -void operator delete(void *ptr, lua_State *L, const char *metaname); - -#endif // !_LUAE_H_
--- a/C++/LuaeClass.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * LuaeClass.cpp -- Lua object management - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "Luae.h" -#include "LuaeClass.h" - -LuaeClass::Def::Def(const std::string &name, - const Methods &methods, - const Methods &metamethods) - : name(name) - , methods(methods) - , metamethods(metamethods) -{ -} - -LuaeClass::Def::Def(const std::string &name, - const Methods &methods, - const Methods &metamethods, - const Def &defparent) - : Def(name, methods, metamethods) -{ - parent = std::make_shared<Def>(defparent); -} - -void LuaeClass::registerInheritance(lua_State *L, const Def &def) -{ - Luae::getfield(L, LUA_REGISTRYINDEX, Luae::FieldClasses); - - // The table __luae_classes does not exists? - if (Luae::type(L, -1) == LUA_TNIL) { - Luae::pop(L); - Luae::newtable(L); - Luae::pushvalue(L, -1); - Luae::setfield(L, LUA_REGISTRYINDEX, Luae::FieldClasses); - } - - // The description already exists? - Luae::getfield(L, -1, def.name); - - if (Luae::type(L, -1) == LUA_TNIL) { - Luae::pop(L); - Luae::newtable(L); - - for (const auto *parent = def.parent.get(); parent != nullptr; parent = parent->parent.get()) { - Luae::push(L, true); - Luae::setfield(L, -2, parent->name); - } - - // Also allow cast for itself - Luae::push(L, true); - Luae::setfield(L, -2, def.name); - - // Set this map to the registry - Luae::setfield(L, -2, def.name); - } else - Luae::pop(L); - - Luae::pop(L); -} - -void LuaeClass::create(lua_State *L, const Def &def) -{ - Luae::assertBegin(L); - Luae::newmetatable(L, def.name); - - // Set the name to the metatable to get the real userdata type - Luae::push(L, def.name); - Luae::setfield(L, -2, Luae::FieldName); - - // Metamethods - if (def.metamethods.size() > 0) { - for (const auto &m : def.metamethods) { - Luae::pushfunction(L, m.func); - Luae::setfield(L, -2, m.name); - } - } - - // Methods - Luae::newtable(L); - for (const auto &m : def.methods) { - Luae::pushfunction(L, m.func); - Luae::setfield(L, -2, m.name); - } - - /* - * Here is how inheritance works. If we have a parent, we use the - * metatable parent as the metatable of the __index functions table. - * - * So we have the following: - * - * The top square is the metatable name, the square below is the - * functions table set to __index. - * - * +-----------------+ +-----------------+ - * | Base | <-- inherits -- | Child | - * +-----Methods-----+ +-----Methods-----+ - * | apply | | foo | - * +-----------------+ +----Metatable----+ (metatable for methods table) - * <-- points to | <reference> | - * +-----------------+ - */ - if (def.parent) { - Luae::newmetatable(L, def.parent->name); - Luae::setmetatable(L, -2); - } - Luae::setfield(L, -2, "__index"); - Luae::pop(L); - - // Now register the class map for type safe cast in __luae_class - registerInheritance(L, def); - - Luae::assertEnd(L, 0); -} \ No newline at end of file
--- a/C++/LuaeClass.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * LuaeClass.h -- Lua object management - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUAE_CLASS_H_ -#define _LUAE_CLASS_H_ - -#include <memory> -#include <string> -#include <vector> - -#include <lua.hpp> - -/** - * @class LuaeClass - * @brief Support for object oriented programming between C++ and Lua - * - * This class provides functions for passing and retrieving objects from C++ and - * Lua. - */ -class LuaeClass { -public: - /** - * Methods for a class. - */ - using Methods = std::vector<luaL_Reg>; - - /** - * @struct Def - * @brief Definition of a class - */ - struct Def { - std::string name; //!< metatable name - Methods methods; //!< methods - Methods metamethods; //!< metamethods - std::shared_ptr<Def> parent; //!< optional parent class - - /** - * Constructor for base or final classes. No parent. - * - * @param name the class name - * @param methods the methods - * @param metamethods the metamethods - */ - Def(const std::string &name, - const Methods &methods, - const Methods &metamethods); - - /** - * Child class constructor. Use parent as the parent class - * of this one. - * - * @param name the class name - * @param methods the methods - * @param metamethods the metamethods - * @param parent the parent - */ - Def(const std::string &name, - const Methods &methods, - const Methods &metamethods, - const Def &parent); - }; - -private: - static void registerInheritance(lua_State *L, const Def &def); - -public: - /** - * Initialize a new object. - * - * @param L the Lua state - * @param def the definition - */ - static void create(lua_State *L, const Def &def); -}; - -#endif // !_LUAE_CLASS_H_
--- a/C++/LuaeEnum.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ - -#include "LuaeEnum.h" - -void LuaeEnum::create(lua_State *L, const Def &def) -{ - LUAE_STACK_CHECKBEGIN(L); - - lua_createtable(L, 0, 0); - - for (auto p : def) { - lua_pushinteger(L, p.second); - lua_setfield(L, -2, p.first); - } - - LUAE_STACK_CHECKEND(L, - 1); -} - -void LuaeEnum::create(lua_State *L, const Def &def, int index) -{ - LUAE_STACK_CHECKBEGIN(L); - - if (index < 0) - -- index; - - for (auto p : def) { - lua_pushinteger(L, p.second); - lua_setfield(L, index, p.first); - } - - LUAE_STACK_CHECKEQUALS(L); -} - -void LuaeEnum::create(lua_State *L, - const Def &def, - int index, - const std::string &name) -{ - LUAE_STACK_CHECKBEGIN(L); - - create(L, def); - - if (index < 0) - -- index; - - lua_setfield(L, index, name.c_str()); - - LUAE_STACK_CHECKEQUALS(L); -} - -void LuaeEnum::push(lua_State *L, const Def &def, int value) -{ - LUAE_STACK_CHECKBEGIN(L); - lua_createtable(L, 0, 0); - - for (auto p : def) { - if (value & p.second) { - lua_pushinteger(L, p.second); - lua_setfield(L, -2, p.first); - } - } - - LUAE_STACK_CHECKEND(L, - 1); -} - -int LuaeEnum::get(lua_State *L, int index) -{ - int value = 0; - - LUAE_STACK_CHECKBEGIN(L); - luaL_checktype(L, index, LUA_TTABLE); - - if (index < 0) - -- index; - - lua_pushnil(L); - while (lua_next(L, index)) { - if (lua_type(L, -1) == LUA_TNUMBER) - value |= lua_tointeger(L, -1); - - lua_pop(L, 1); - } - - LUAE_STACK_CHECKEQUALS(L); - - return value; -}
--- a/C++/LuaeEnum.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * LuaeEnum.h -- Lua enumeration helpers - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUAE_ENUM_H_ -#define _LUAE_ENUM_H_ - -#include <lua.hpp> - -/** - * @class LuaeEnum - * @brief Binds and get enumeration - * - * Bind C/C++ enumeration as tables to Lua in the key-value form. Two - * methods push and get are also available for enumeration flags. - */ -class LuaeEnum { -public: - /** - * The definition of the enumeration - */ - using Def = std::unordered_map<const char *, int>; - - /** - * Bind the enumeration and keep it at the top of the stack. - * - * @param L the Lua state - * @param def the definition - */ - static void create(lua_State *L, const Def &def); - - /** - * Set the enumeration values to an existing table. - * - * @param L the Lua state - * @param def the definition - * @param index the table index - */ - static void create(lua_State *L, const Def &def, int index); - - /** - * Create the enumeration table and set it to a table field. - * - * @param L the Lua state - * @param def the definition - * @param index the table index - * @param name the field name to store the enumeration - */ - static void create(lua_State *L, - const Def &def, - int index, - const std::string &name); - - /** - * Push the value enumeration as a table to Lua. This is used - * as the OR replacement. - * - * @param L the Lua state - * @param def the definition - * @param value the value - */ - static void push(lua_State *L, const Def &def, int value); - - /** - * Get the enumeration from Lua. Raises an error if the - * value at the index is not a table. - * - * This is used as the OR replacement. - * - * @param L the Lua state - * @param index the value index - * @return the value - */ - static int get(lua_State *L, int index); -}; - -#endif // !_LUAE_ENUM_H_
--- a/C++/LuaeState.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#include "LuaeState.h" - -LuaeState::LuaeState() -{ - m_state = Ptr(luaL_newstate()); -} - -LuaeState::LuaeState(lua_State *L) -{ - m_state = Ptr(L); -} - -LuaeState::LuaeState(LuaeState &&state) -{ - m_state = std::move(state.m_state); -} - -LuaeState &LuaeState::operator=(LuaeState &&state) -{ - m_state = std::move(state.m_state); - - return *this; -} - -LuaeState::operator lua_State*() -{ - return m_state.get(); -}
--- a/C++/LuaeState.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * LuaeState.h -- Lua RAII wrapper for lua_State - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUAE_STATE_H_ -#define _LUAE_STATE_H_ - -#include <memory> - -#include <lua.hpp> - -/** - * @class LuaeState - * @brief Wrapper for lua_State - * - * This class automatically create a new Lua state and add implicit - * cast operator plus RAII destruction. - */ -class LuaeState { -private: - struct Deleter { - void operator()(lua_State *L) - { - lua_close(L); - } - }; - - using Ptr = std::unique_ptr<lua_State, Deleter>; - - Ptr m_state; - -public: - /** - * Deleted copy constructor. - */ - LuaeState(const LuaeState &) = delete; - - /** - * Deleted copy assignment. - */ - LuaeState &operator=(const LuaeState &) = delete; - - /** - * Default constructor. Create a new state. - */ - LuaeState(); - - /** - * Use the already created state. - * - * @param L the state to use - */ - LuaeState(lua_State *L); - - /** - * Move constructor. - * - * @param state the Lua state to move - */ - LuaeState(LuaeState &&state); - - /** - * Move assignment operator. - * - * @param state the Lua state to move - */ - LuaeState &operator=(LuaeState &&state); - - /** - * Implicit cast operator for convenient usage to C Lua API. - * - * @return the state as lua_State * - */ - operator lua_State*(); -}; - -#endif // !_LUAE_STATE_H_
--- a/C++/LuaeTable.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * LuaeTable.cpp -- Lua table helpers - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "LuaeTable.h" - -void LuaeTable::create(lua_State *L, int nrec, int narr) -{ - LUAE_STACK_CHECKBEGIN(L); - - lua_createtable(L, nrec, narr); - - LUAE_STACK_CHECKEND(L, - 1); -} - -int LuaeTable::type(lua_State *L, int idx, const std::string &name) -{ - int type; - - LUAE_STACK_CHECKBEGIN(L); - - lua_getfield(L, idx, name.c_str()); - type = lua_type(L, -1); - lua_pop(L, 1); - - LUAE_STACK_CHECKEQUALS(L); - - return type; -} - -void LuaeTable::read(lua_State *L, int idx, ReadFunction func) -{ - LUAE_STACK_CHECKBEGIN(L); - - lua_pushnil(L); - - if (idx < 0) - --idx; - - while (lua_next(L, idx)) { - func(L, lua_type(L, -2), lua_type(L, -1)); - lua_pop(L, 1); - } - - LUAE_STACK_CHECKEQUALS(L); -} - -int LuaeTable::ref(lua_State *L, int idx, int type, const std::string &name) -{ - int ref = LUA_REFNIL; - - lua_getfield(L, idx, name.c_str()); - - if (lua_type(L, -1) == type) { - lua_pushvalue(L, -1); - ref = luaL_ref(L, LUA_REGISTRYINDEX); - } - - lua_pop(L, 1); - - return ref; -}
--- a/C++/LuaeTable.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* - * LuaeTable.h -- Lua table helpers - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUAE_TABLE_H_ -#define _LUAE_TABLE_H_ - -#include <lua.hpp> - -/** - * @class LuaeTable - * @brief Some function for table manipulation - * - * Read, reference and get fields from tables. - */ -class LuaeTable { -public: - /** - * The map function for \ref read - */ - using ReadFunction = std::function<void(lua_State *L, int tkey, int tvalue)>; - - /** - * Push a new table onto the stack. - * - * @param L the Lua state - * @param nrec the optional number of entries as record - * @param narr the optional number of entries as sequence - */ - static void create(lua_State *L, int nrec = 0, int narr = 0); - - /** - * Get a field of a specific type from a table. Specialized for the - * types: int, double, bool and string. - * - * @param L the Lua state - * @param idx the table index - * @param name the field name - * @return the converted type. - */ - template <typename T> - static T get(lua_State *L, int idx, const std::string &name) - { - LUAE_STACK_CHECKBEGIN(L); - - lua_getfield(L, idx, name.c_str()); - auto t = Luae::get<T>(L, -1); - lua_pop(L, 1); - - LUAE_STACK_CHECKEQUALS(L); - - return t; - } - - /** - * Set a table field. Specialized for the same fields as get. - * - * @param L the Lua state - * @param idx the index - * @param name the field name - * @param value the value - * @see get - */ - template <typename T> - static void set(lua_State *L, int idx, const std::string &name, const T &value) - { - LUAE_STACK_CHECKBEGIN(L); - - Luae::push(L, value); - Luae::setfield(L, (idx < 0) ? --idx : idx, name); - - LUAE_STACK_CHECKEQUALS(L); - } - - /** - * Overload for string literals. - * - * @param L the Lua state - * @param idx the index - * @param name the field name - * @param s the string - */ - template <size_t N> - static void set(lua_State *L, int idx, const std::string &name, const char (&s)[N]) - { - set<const char *>(L, idx, name, s); - } - - /** - * Require a field from a table. - * - * @param L the Lua state - * @param idx the table index - * @param name the field name - * @return the value or call luaL_error - */ - 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) - luaL_error(L, "missing field `%s'", name.c_str()); - // NOT REACHED - - lua_pop(L, 1); - auto v = get<T>(L, idx, name); - - LUAE_STACK_CHECKEQUALS(L); - - return v; - } - - /** - * Check a table field. - * - * @param L the Lua state - * @param idx the table index - * @param name the field name - * @return the type - */ - static int type(lua_State *L, int idx, const std::string &name); - - /** - * Read a table, the function func is called for each element in the - * table. Parameter tkey is the Lua type of the key, parameter tvalue is - * the Lua type of the value. The key is available at index -2 and the - * value at index -1. - * - * <strong>Do not pop anything within the function.</strong> - * - * @param L the Lua state - * @param idx the table index - * @param func the function to call - */ - static void read(lua_State *L, int idx, ReadFunction func); - - /** - * Reference a field from a table at the index. The reference is created in - * the registry only if type matches. - * - * @param L the Lua state - * @param idx the table index - * @param type the type requested - * @param name the field name - * @return the reference or LUA_REFNIL on problem - */ - static int ref(lua_State *L, - int idx, - int type, - const std::string &name); -}; - -#endif // !_LUAE_TABLE_H_
--- a/C++/LuaeVariant.cpp Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * LuaeVariant.cpp -- Lua variant helper - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "LuaeVariant.h" - -LuaeVariant LuaeVariant::copy(lua_State *L, int index) -{ - LuaeVariant v; - - v.type = lua_type(L, index); - - switch (v.type) { - case LUA_TBOOLEAN: - v.boolean = lua_toboolean(L, index); - break; - case LUA_TNUMBER: - v.number = lua_tonumber(L, index); - break; - case LUA_TSTRING: - v.str = lua_tostring(L, index); - break; - case LUA_TTABLE: - { - if (index < 0) - -- index; - - lua_pushnil(L); - while (lua_next(L, index)) { - v.table.push_back(std::make_pair(copy(L, -2), copy(L, -1))); - lua_pop(L, 1); - } - - break; - } - default: - v.type = LUA_TNIL; - break; - } - - return v; -} - -void LuaeVariant::push(lua_State *L, const LuaeVariant &value) -{ - switch (value.type) { - case LUA_TBOOLEAN: - lua_pushboolean(L, value.boolean); - break; - case LUA_TSTRING: - lua_pushlstring(L, value.str.c_str(), value.str.size()); - break; - case LUA_TNUMBER: - lua_pushnumber(L, value.number); - break; - case LUA_TTABLE: - { - lua_createtable(L, 0, 0); - - for (auto p : value.table) { - push(L, p.first); - push(L, p.second); - - lua_settable(L, -3); - } - break; - } - default: - lua_pushnil(L); - break; - } -} - -LuaeVariant::LuaeVariant() - : type(LUA_TNIL) -{ -} -
--- a/C++/LuaeVariant.h Mon Oct 13 14:32:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * LuaeVariant.h -- Lua variant helper - * - * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LUAE_VARIANT_H_ -#define _LUAE_VARIANT_H_ - -#include <lua.hpp> - -/** - * @class LuaeVariant - * @brief A fake variant for Lua values - * - * This class is primarly used for copying Lua values without checking - * the types, useful to pass data. - */ -class LuaeVariant { -private: - union { - lua_Number number; - bool boolean; - }; - - int type; - std::string str; - std::vector<std::pair<LuaeVariant, LuaeVariant>> table; - -public: - /** - * Dump a value at the specific index. - * - * @param L the Lua state - * @param index the value - * @return a tree of values - */ - static LuaeVariant copy(lua_State *L, int index); - - /** - * Push a value to a state. - * - * @param L the Lua state - * @param value the value to push - */ - static void push(lua_State *L, const LuaeVariant &value); - - /** - * Default constructor (type nil) - */ - LuaeVariant(); -}; - -#endif // !_LUAE_VARIANT_H_