1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
#include "lua_ref_helper.h"
#define FREELIST_REF 0
#if LUA_VERSION_NUM >= 502
#define lua_objlen(L, INDEX) lua_rawlen(L, INDEX)
#endif
/* convert a stack index to positive */
/* stolen from lauxlib.c, converted to a function */
static int abs_index(lua_State *L, int i) {
return i > 0 || i <= LUA_REGISTRYINDEX ? i : lua_gettop(L) + i + 1;
}
LUALIB_API int luaX_ref(lua_State *L, int t, int l) {
int ref;
t = abs_index(L, t);
l = abs_index(L, l);
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* remove from stack */
return LUA_REFNIL; /* 'nil' has a unique fixed reference */
}
lua_rawgeti(L, l, FREELIST_REF); /* get first free element */
ref = (int)lua_tointeger(L, -1); /* ref = l[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, l, ref); /* remove it from list */
lua_rawseti(L, l, FREELIST_REF); /* (l[FREELIST_REF] = l[ref]) */
} else { /* no free elements */
ref = (int)lua_objlen(L, l);
ref++; /* create new reference */
}
lua_pushboolean(L, 1);
lua_rawseti(L, l, ref); /* l[ref] = true */
lua_rawseti(L, t, ref); /* t[ref] = value */
return ref;
}
LUALIB_API void luaX_unref(lua_State *L, int t, int l, int ref) {
if (ref >= 0) {
t = abs_index(L, t);
l = abs_index(L, l);
lua_rawgeti(L, l, FREELIST_REF);
lua_rawseti(L, l, ref); /* l[ref] = l[FREELIST_REF] */
lua_pushinteger(L, ref);
lua_rawseti(L, l, FREELIST_REF); /* l[FREELIST_REF] = ref */
lua_pushnil(L);
lua_rawseti(L, t, ref); /* t[ref] = nil */
}
}
|