Browse Source

new "primitive" getn

v5-2
Roberto Ierusalimschy 20 years ago
parent
commit
9ffae705ee
  1. 24
      lapi.c
  2. 49
      lauxlib.c
  3. 10
      lbaselib.c
  4. 50
      ltable.c
  5. 3
      ltable.h
  6. 21
      ltablib.c
  7. 10
      ltests.c

24
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;
}
}

49
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;

10
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},

50
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);
}

3
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);

21
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;
}

10
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;

Loading…
Cancel
Save