From 9ffae705ee8894d68bbc07a1a5f77a112c40efad Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 16 Mar 2005 13:58:41 -0300 Subject: [PATCH] new "primitive" getn --- lapi.c | 24 +++++++++++++----------- lauxlib.c | 49 ++++++++++--------------------------------------- lbaselib.c | 10 +++++++++- ltable.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- ltable.h | 3 ++- ltablib.c | 21 ++++++++++++--------- ltests.c | 10 ++++++---- 7 files changed, 101 insertions(+), 66 deletions(-) diff --git a/lapi.c b/lapi.c index b13aa6c5..d51ac270 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.30 2005/03/08 20:10:05 roberto Exp roberto $ +** $Id: lapi.c,v 2.31 2005/03/09 16:28:07 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -350,16 +350,18 @@ LUA_API const char *lua_tostring (lua_State *L, int idx) { LUA_API size_t lua_objsize (lua_State *L, int idx) { StkId o = index2adr(L, idx); - if (ttisstring(o)) - return tsvalue(o)->len; - else if (ttisuserdata(o)) - return uvalue(o)->len; - else { - size_t l; - lua_lock(L); /* `luaV_tostring' may create a new string */ - l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); - lua_unlock(L); - return l; + switch (ttype(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); + lua_unlock(L); + return l; + } + default: return 0; } } diff --git a/lauxlib.c b/lauxlib.c index cccff91b..835ae5b9 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.128 2005/02/10 17:12:02 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.129 2005/02/23 17:30:22 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -25,12 +25,7 @@ #include "lauxlib.h" -/* number of prereserved references (for internal use) */ -#define RESERVED_REFS 2 - -/* reserved references */ -#define FREELIST_REF 1 /* free list of references */ -#define ARRAYSIZE_REF 2 /* array sizes */ +#define FREELIST_REF 0 /* free list of references */ /* convert a stack index to positive */ @@ -275,6 +270,8 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, ** ======================================================= */ +#ifndef luaL_getn + static int checkint (lua_State *L, int topop) { int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; lua_pop(L, topop); @@ -283,7 +280,7 @@ static int checkint (lua_State *L, int topop) { static void getsizes (lua_State *L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); if (lua_isnil(L, -1)) { /* no `size' table? */ lua_pop(L, 1); /* remove nil */ lua_newtable(L); /* create it */ @@ -292,7 +289,7 @@ static void getsizes (lua_State *L) { lua_pushliteral(L, "kv"); lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ lua_pushvalue(L, -1); - lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ } } @@ -307,31 +304,6 @@ LUALIB_API void luaL_setn (lua_State *L, int t, int n) { } -/* find an `n' such that t[n] ~= nil and t[n+1] == nil */ -static int countn (lua_State *L, int t) { - int i = LUA_FIRSTINDEX - 1; - int j = 2; - /* find `i' such that i <= n < i*2 (= j) */ - for (;;) { - lua_rawgeti(L, t, j); - if (lua_isnil(L, -1)) break; - lua_pop(L, 1); - i = j; - j = i*2; - } - lua_pop(L, 1); - /* i <= n < j; do a binary search */ - while (i < j-1) { - int m = (i+j)/2; - lua_rawgeti(L, t, m); - if (lua_isnil(L, -1)) j = m; - else i = m; - lua_pop(L, 1); - } - return i - LUA_FIRSTINDEX + 1; -} - - LUALIB_API int luaL_getn (lua_State *L, int t) { int n; t = abs_index(L, t); @@ -341,9 +313,11 @@ LUALIB_API int luaL_getn (lua_State *L, int t) { if ((n = checkint(L, 2)) >= 0) return n; lua_getfield(L, t, "n"); /* else try t.n */ if ((n = checkint(L, 1)) >= 0) return n; - return countn(L, t); + return lua_objsize(L, t); } +#endif + /* }====================================================== */ @@ -562,11 +536,8 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ } else { /* no free elements */ - ref = luaL_getn(L, t); - if (ref < RESERVED_REFS) - ref = RESERVED_REFS; /* skip reserved references */ + ref = lua_objsize(L, t); ref++; /* create new reference */ - luaL_setn(L, t, ref); } lua_rawseti(L, t, ref); return ref; diff --git a/lbaselib.c b/lbaselib.c index 442ca621..20dcefe2 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.169 2005/02/28 17:24:41 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.170 2005/03/11 15:51:08 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -332,6 +332,13 @@ static int luaB_assert (lua_State *L) { } +static int luaB_getn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushinteger(L, lua_objsize(L, 1)); + return 1; +} + + static int luaB_unpack (lua_State *L) { int i = luaL_optint(L, 2, LUA_FIRSTINDEX); int e = luaL_optint(L, 3, -1); @@ -448,6 +455,7 @@ static const luaL_reg base_funcs[] = { {"tostring", luaB_tostring}, {"type", luaB_type}, {"assert", luaB_assert}, + {"getn", luaB_getn}, {"unpack", luaB_unpack}, {"select", luaB_select}, {"rawequal", luaB_rawequal}, diff --git a/ltable.c b/ltable.c index d66cc2e5..eaf4ea7d 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.17 2005/03/08 20:10:05 roberto Exp roberto $ +** $Id: ltable.c,v 2.18 2005/03/09 16:28:07 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -524,3 +524,51 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { } } + +static int unbound_search (Table *t, unsigned int j) { + unsigned int i = j; /* i is zero or a present index */ + j = j+1; + /* find `i' and `j' such that i is present and j is not */ + while (!ttisnil(luaH_getnum(t, j))) { + i = j; + j = i*2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getnum(t, i))) i++; + return i - 1; + } + } + /* now do a binary search between them */ + while (i < j-1) { + unsigned int m = (i+j)/2; + if (ttisnil(luaH_getnum(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table `t'. A `boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +int luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 1; + if (ttisnil(&t->array[1 - 1])) return 0; + while (i < j - 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (t->node == &luaH_dummynode) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + diff --git a/ltable.h b/ltable.h index d8ba8c8a..0036198f 100644 --- a/ltable.h +++ b/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.4 2005/01/04 15:55:12 roberto Exp roberto $ +** $Id: ltable.h,v 2.5 2005/01/05 18:20:51 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -30,6 +30,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash); void luaH_resizearray (lua_State *L, Table *t, int nasize); void luaH_free (lua_State *L, Table *t); int luaH_next (lua_State *L, Table *t, StkId key); +int luaH_getn (Table *t); /* exported only for debugging */ Node *luaH_mainposition (const Table *t, const TValue *key); diff --git a/ltablib.c b/ltablib.c index 572730aa..42575685 100644 --- a/ltablib.c +++ b/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.26 2004/06/15 13:37:21 roberto Exp roberto $ +** $Id: ltablib.c,v 1.27 2004/12/07 18:28:47 roberto Exp roberto $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -62,29 +62,32 @@ static int getn (lua_State *L) { static int setn (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); +#ifndef luaL_setn luaL_setn(L, 1, luaL_checkint(L, 2)); +#else + luaL_error(L, "`setn' is obsolete"); +#endif lua_pushvalue(L, 1); return 1; } static int tinsert (lua_State *L) { - int v = lua_gettop(L); /* number of arguments */ int e = aux_getn(L, 1) + LUA_FIRSTINDEX; /* first empty element */ int pos; /* where to insert new element */ - if (v == 2) /* called with only 2 arguments */ + if (lua_isnone(L, 3)) /* called with only 2 arguments */ pos = e; /* insert new element at the end */ else { + int i; pos = luaL_checkint(L, 2); /* 2nd argument is the position */ if (pos > e) e = pos; /* `grow' array if necessary */ - v = 3; /* function may be called with more than 3 args */ + lua_settop(L, 3); /* function may be called with more than 3 args */ + for (i = e; i > pos; i--) { /* move up elements */ + lua_rawgeti(L, 1, i-1); + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + } } luaL_setn(L, 1, e - LUA_FIRSTINDEX + 1); /* new size */ - while (--e >= pos) { /* move up elements */ - lua_rawgeti(L, 1, e); - lua_rawseti(L, 1, e+1); /* t[e+1] = t[e] */ - } - lua_pushvalue(L, v); lua_rawseti(L, 1, pos); /* t[pos] = v */ return 0; } diff --git a/ltests.c b/ltests.c index 620b6a41..717e0c5e 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.19 2005/01/19 15:54:26 roberto Exp roberto $ +** $Id: ltests.c,v 2.20 2005/02/18 12:40:02 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -456,11 +456,11 @@ static int listlocals (lua_State *L) { static int get_limits (lua_State *L) { lua_createtable(L, 0, 5); - setnameval(L, "BITS_INT", LUA_BITSINT); + setnameval(L, "BITS_INT", LUAI_BITSINT); setnameval(L, "LFPF", LFIELDS_PER_FLUSH); - setnameval(L, "MAXVARS", MAXVARS); + setnameval(L, "MAXVARS", LUAI_MAXVARS); setnameval(L, "MAXSTACK", MAXSTACK); - setnameval(L, "MAXUPVALUES", MAXUPVALUES); + setnameval(L, "MAXUPVALUES", LUAI_MAXUPVALUES); setnameval(L, "NUM_OPCODES", NUM_OPCODES); return 1; } @@ -970,12 +970,14 @@ static int testC (lua_State *L) { int i = getindex; lua_pushinteger(L1, luaL_getn(L1, i)); } +#ifndef luaL_setn else if EQ("setn") { int i = getindex; int n = cast(int, lua_tonumber(L1, -1)); luaL_setn(L1, i, n); lua_pop(L1, 1); } +#endif else if EQ("throw") { #ifdef __cplusplus static struct X { int x; } x;