commit 9ffae705ee8894d68bbc07a1a5f77a112c40efad
parent 6bfef60e77f5eec1057470010b4179ee6f830fe6
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 16 Mar 2005 13:58:19 -0300
new "primitive" getn
Diffstat:
7 files changed, 101 insertions(+), 66 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;