Mercurial > code
view C++/Luae.cpp @ 213:1829c4266bee
Hash: hash functions
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 24 Mar 2014 13:54:28 +0100 |
parents | b54c83ed71ca |
children | 8fc177bbc4a6 |
line wrap: on
line source
/* * Luae.cpp -- Lua helpers and such * * 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 "Luae.h" /* -------------------------------------------------------- * LuaeState * -------------------------------------------------------- */ const char *LuaeState::FieldRefs = "__refs"; void LuaeState::initRegistry() { 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, FieldRefs); } } LuaeState::LuaeState() { m_state = Ptr(luaL_newstate()); initRegistry(); } LuaeState::LuaeState(lua_State *L) { m_state = Ptr(L); initRegistry(); } LuaeState::LuaeState(LuaeState &&state) { m_state = std::move(state.m_state); initRegistry(); } LuaeState &LuaeState::operator=(LuaeState &&state) { m_state = std::move(state.m_state); initRegistry(); return *this; } LuaeState::operator lua_State*() { return m_state.get(); } /* -------------------------------------------------------- * LuaeValue * -------------------------------------------------------- */ LuaeValue LuaeValue::copy(lua_State *L, int index) { LuaeValue 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: { LuaeValue k; 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 LuaeValue::push(lua_State *L, const LuaeValue &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; } } LuaeValue::LuaeValue() : type(LUA_TNIL) { } /* -------------------------------------------------------- * LuaeTable * -------------------------------------------------------- */ 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; } /* -------------------------------------------------------- * 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()); // 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) { for (auto m : def.metamethods) { lua_pushcfunction(L, m.func); lua_setfield(L, -2, m.name); } } // Methods 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); } /* -------------------------------------------------------- * LuaeEnum * -------------------------------------------------------- */ void LuaeEnum::create(lua_State *L, const Def &def, int index, const std::string &name) { LUAE_STACK_CHECKBEGIN(L); lua_createtable(L, 0, def.size()); for (auto p : def) { lua_pushinteger(L, p.second); lua_setfield(L, -2, p.first.c_str()); } 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.c_str()); } } 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; } /* -------------------------------------------------------- * Luae * -------------------------------------------------------- */ 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::preload(lua_State *L, const std::string &name, lua_CFunction func) { LUAE_STACK_CHECKBEGIN(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); LUAE_STACK_CHECKEQUALS(L); } void Luae::require(lua_State *L, const std::string &name, lua_CFunction func, bool global) { LUAE_STACK_CHECKBEGIN(L); luaL_requiref(L, name.c_str(), func, global); lua_pop(L, 1); LUAE_STACK_CHECKEQUALS(L); } 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); }