From 41ed3c47719b29dd02dc9fcf07f79dc6f2c4381d Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 27 Jan 2003 11:46:16 -0200 Subject: [PATCH] getn/setn in C moved to lauxlib --- lauxlib.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- lauxlib.h | 5 +++- ltablib.c | 65 +++++------------------------------------- 3 files changed, 94 insertions(+), 61 deletions(-) diff --git a/lauxlib.c b/lauxlib.c index 9ecec884..9f39b46b 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.91 2002/12/04 17:38:31 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.92 2003/01/23 11:34:18 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -23,6 +23,13 @@ #include "lauxlib.h" +/* number of prereserved references (for internal use) */ +#define RESERVED_REFS 1 + +/* reserved reference for array sizes */ +#define ARRAYSIZE_REF 1 + + /* ** {====================================================== ** Error-report functions @@ -195,6 +202,78 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +static int checkint (lua_State *L, int topop) { + int n = (int)lua_tonumber(L, -1); + if (n == 0 && !lua_isnumber(L, -1)) n = -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); + if (lua_isnil(L, -1)) { /* no `size' table? */ + lua_newtable(L); /* create it */ + lua_pushvalue(L, -1); /* `size' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "k"); + lua_rawset(L, -3); /* metatable(N).__mode = "k" */ + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ + } +} + + +void luaL_setn (lua_State *L, int t, int n) { + lua_pushliteral(L, "n"); + lua_rawget(L, t); + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ + lua_pushliteral(L, "n"); /* use it */ + lua_pushnumber(L, n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushnumber(L, n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +int luaL_getn (lua_State *L, int t) { + int n; + lua_pushliteral(L, "n"); /* try t.n */ + lua_rawget(L, t); + if ((n = checkint(L, 1)) >= 0) return n; + getsizes(L); /* else try sizes[t] */ + lua_pushvalue(L, t); + lua_rawget(L, -2); + if ((n = checkint(L, 2)) >= 0) return n; + else { /* must count elements */ + for (n = 1; ; n++) { + lua_rawgeti(L, t, n); + if (lua_isnil(L, -1)) break; + lua_pop(L, 1); + } + lua_pop(L, 1); + luaL_setn(L, t, n - 1); + return n - 1; + } +} + +/* }====================================================== */ + + + /* ** {====================================================== ** Generic Buffer manipulation @@ -308,8 +387,10 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { lua_pushliteral(L, "n"); lua_pushvalue(L, -1); lua_rawget(L, t); /* get t.n */ - ref = (int)lua_tonumber(L, -1) + 1; /* ref = t.n + 1 */ + ref = (int)lua_tonumber(L, -1); /* ref = t.n */ lua_pop(L, 1); /* pop t.n */ + if (ref == 0) ref = RESERVED_REFS; /* skip reserved references */ + ref++; /* create new reference */ lua_pushnumber(L, ref); lua_rawset(L, t); /* t.n = t.n + 1 */ } diff --git a/lauxlib.h b/lauxlib.h index 25d8499c..fb2b0ab6 100644 --- a/lauxlib.h +++ b/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.55 2002/11/14 15:41:38 roberto Exp roberto $ +** $Id: lauxlib.h,v 1.56 2003/01/17 15:28:09 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -51,6 +51,9 @@ LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); LUALIB_API int luaL_ref (lua_State *L, int t); LUALIB_API void luaL_unref (lua_State *L, int t, int ref); +LUALIB_API int luaL_getn (lua_State *L, int t); +LUALIB_API void luaL_setn (lua_State *L, int t, int n); + LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, const char *name); diff --git a/ltablib.c b/ltablib.c index 504081bc..c0e773aa 100644 --- a/ltablib.c +++ b/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.17 2002/12/04 17:38:31 roberto Exp roberto $ +** $Id: ltablib.c,v 1.18 2002/12/20 10:26:33 roberto Exp roberto $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -15,52 +15,7 @@ #include "lualib.h" - -static int checkint (lua_State *L) { - int n = (int)lua_tonumber(L, -1); - if (n == 0 && !lua_isnumber(L, -1)) n = -1; - lua_pop(L, 1); - return n; -} - - -static void aux_setn (lua_State *L, int t, int n) { - lua_pushliteral(L, "n"); - lua_rawget(L, t); - if (checkint(L) >= 0) { - lua_pushliteral(L, "n"); /* use it */ - lua_pushnumber(L, n); - lua_rawset(L, t); - } - else { /* use N */ - lua_pushvalue(L, t); - lua_pushnumber(L, n); - lua_rawset(L, lua_upvalueindex(1)); /* N[t] = n */ - } -} - - -static int aux_getn (lua_State *L, int t) { - int n; - luaL_checktype(L, t, LUA_TTABLE); - lua_pushliteral(L, "n"); /* try t.n */ - lua_rawget(L, t); - if ((n = checkint(L)) >= 0) return n; - lua_pushvalue(L, t); /* try N[t] */ - lua_rawget(L, lua_upvalueindex(1)); - if ((n = checkint(L)) >= 0) return n; - else { /* must count elements */ - n = 0; - for (;;) { - lua_rawgeti(L, t, ++n); - if (lua_isnil(L, -1)) break; - lua_pop(L, 1); - } - lua_pop(L, 1); - aux_setn(L, t, n - 1); - return n - 1; - } -} +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) static int luaB_foreachi (lua_State *L) { @@ -106,7 +61,7 @@ static int luaB_getn (lua_State *L) { static int luaB_setn (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - aux_setn(L, 1, luaL_checkint(L, 2)); + luaL_setn(L, 1, luaL_checkint(L, 2)); return 0; } @@ -122,7 +77,7 @@ static int luaB_tinsert (lua_State *L) { if (pos > n) n = pos; /* `grow' array if necessary */ v = 3; /* function may be called with more than 3 args */ } - aux_setn(L, 1, n); /* new size */ + luaL_setn(L, 1, n); /* new size */ while (--n >= pos) { /* move up elements */ lua_rawgeti(L, 1, n); lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ @@ -137,7 +92,7 @@ static int luaB_tremove (lua_State *L) { int n = aux_getn(L, 1); int pos = luaL_optint(L, 2, n); if (n <= 0) return 0; /* table is `empty' */ - aux_setn(L, 1, n-1); /* t.n = n-1 */ + luaL_setn(L, 1, n-1); /* t.n = n-1 */ lua_rawgeti(L, 1, pos); /* result = t[pos] */ for ( ;pos