#include "l52util.h" #include #include #if LUA_VERSION_NUM >= 502 int luaL_typerror (lua_State *L, int narg, const char *tname) { const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, narg)); return luaL_argerror(L, narg, msg); } void luaL_register (lua_State *L, const char *libname, const luaL_Reg *l){ if(libname) lua_newtable(L); luaL_setfuncs(L, l, 0); } #else void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup){ luaL_checkstack(L, nup, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; for (i = 0; i < nup; i++) /* copy upvalues to the top */ lua_pushvalue(L, -nup); lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ lua_setfield(L, -(nup + 2), l->name); } lua_pop(L, nup); /* remove upvalues */ } void lua_rawgetp(lua_State *L, int index, const void *p){ index = lua_absindex(L, index); lua_pushlightuserdata(L, (void *)p); lua_rawget(L, index); } void lua_rawsetp (lua_State *L, int index, const void *p){ index = lua_absindex(L, index); lua_pushlightuserdata(L, (void *)p); lua_insert(L, -2); lua_rawset(L, index); } #endif int lutil_newmetatablep (lua_State *L, const void *p) { lua_rawgetp(L, LUA_REGISTRYINDEX, p); if (!lua_isnil(L, -1)) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ lua_pop(L, 1); lua_newtable(L); /* create metatable */ lua_pushvalue(L, -1); /* duplicate metatable to set*/ lua_rawsetp(L, LUA_REGISTRYINDEX, p); return 1; } void lutil_getmetatablep (lua_State *L, const void *p) { lua_rawgetp(L, LUA_REGISTRYINDEX, p); } void lutil_setmetatablep (lua_State *L, const void *p) { lutil_getmetatablep(L, p); assert(lua_istable(L,-1)); lua_setmetatable (L, -2); } int lutil_isudatap (lua_State *L, int ud, const void *p) { if (lua_isuserdata(L, ud)){ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ int res; lutil_getmetatablep(L,p); /* get correct metatable */ res = lua_rawequal(L, -1, -2); /* does it have the correct mt? */ lua_pop(L, 2); /* remove both metatables */ return res; } } return 0; } void *lutil_checkudatap (lua_State *L, int ud, const void *p) { void *up = lua_touserdata(L, ud); if (up != NULL) { /* value is a userdata? */ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ lutil_getmetatablep(L,p); /* get correct metatable */ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ lua_pop(L, 2); /* remove both metatables */ return up; } } } luaL_typerror(L, ud, p); /* else error */ return NULL; /* to avoid warnings */ } int lutil_createmetap (lua_State *L, const void *p, const luaL_Reg *methods) { if (!lutil_newmetatablep(L, p)) return 0; /* define methods */ luaL_setfuncs (L, methods, 0); /* define metamethods */ lua_pushliteral (L, "__index"); lua_pushvalue (L, -2); lua_settable (L, -3); return 1; } void *lutil_newudatap_impl(lua_State *L, size_t size, const void *p){ void *obj = lua_newuserdata (L, size); memset(obj, 0, size); lutil_setmetatablep(L, p); return obj; }