[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Faster checking of userdata
- From: Fabio Mascarenhas <fabiomasc@...>
- Date: Fri, 27 Aug 2004 10:48:43 -0300
Roberto Ierusalimschy wrote:
A safe alternative, that does not use strcmp, is to write versions of
luaL_newmetatable and luaL_checkudata that use pointers as keys, instead
of strings:
LUALIB_API int luaL_newmetatable_pointer (lua_State *L, void *tname) {
lua_pushlightuserdata(L, tname);
lua_rawget(L, LUA_REGISTRYINDEX); /* get registry.name */
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_pushlightuserdata(L, tname);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */
lua_pushvalue(L, -1);
lua_pushstring(L, tname);
lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */
return 1;
}
LUALIB_API void *luaL_checkudata_pointer (lua_State *L, int ud, void
*tname) {
void *tn;
if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */
lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */
tn = lua_touserdata(L, -1);
if (tn && (tn == tname)) {
lua_pop(L, 1);
return lua_touserdata(L, ud);
}
else {
lua_pop(L, 1);
return NULL;
}
}
Always profile first, of course, to see if it's worth the trouble.
--
Fabio Mascarenhas
if( !lua_getmetatable( L, index ) )
return NULL;
lua_pushlightuserdata( L, udkey ); /* ( ... mt udkey )
lua_rawget( L, -2 ); /* ( ... mt mt[ udkey ] )
This technique is not safe. A Lua program may get udkey (traversing the
metatable of a userdata) and then add it as a key in the metatable of a
userdata from a different kind, fooling checkudata.
-- Roberto