|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: ltable.c,v 1.103 2002/04/05 18:54:31 roberto Exp roberto $
|
|
|
+** $Id: ltable.c,v 1.104 2002/04/22 14:40:23 roberto Exp roberto $
|
|
|
** Lua tables (hash)
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -52,13 +52,13 @@
|
|
|
#define hashnum(t,n) \
|
|
|
(node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t))))
|
|
|
#define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t))))
|
|
|
-#define hashboolean(t,p) (node(t, p)) /* `p' in [0,1] < minimum table size */
|
|
|
+#define hashboolean(t,p) (node(t, lmod(p, sizenode(t))))
|
|
|
|
|
|
/*
|
|
|
** for pointers, avoid modulus by power of 2, as they tend to have many
|
|
|
** 2 factors.
|
|
|
*/
|
|
|
-#define hashpointer(t,p) (node(t, (IntPoint(p) % (sizenode(t)-1))))
|
|
|
+#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1))))
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -200,12 +200,6 @@ static void numuse (const Table *t, int *narray, int *nhash) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-/*
|
|
|
-** (log2 of) minimum size for hash part of a table
|
|
|
-*/
|
|
|
-#define MINHASHSIZE 1
|
|
|
-
|
|
|
-
|
|
|
static void setarrayvector (lua_State *L, Table *t, int size) {
|
|
|
int i;
|
|
|
luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
|
|
@@ -217,16 +211,22 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
|
|
|
|
|
|
static void setnodevector (lua_State *L, Table *t, int lsize) {
|
|
|
int i;
|
|
|
- int size;
|
|
|
- if (lsize < MINHASHSIZE) lsize = MINHASHSIZE;
|
|
|
- else if (lsize > MAXBITS)
|
|
|
+ int size = twoto(lsize);
|
|
|
+ if (lsize > MAXBITS)
|
|
|
luaD_runerror(L, "table overflow");
|
|
|
- size = twoto(lsize);
|
|
|
- t->node = luaM_newvector(L, size, Node);
|
|
|
- for (i=0; i<size; i++) {
|
|
|
- t->node[i].next = NULL;
|
|
|
- setnilvalue(key(node(t, i)));
|
|
|
- setnilvalue(val(node(t, i)));
|
|
|
+ if (lsize == 0) { /* no elements to hash part? */
|
|
|
+ t->node = G(L)->dummynode; /* use common `dummynode' */
|
|
|
+ lua_assert(ttype(key(t->node)) == LUA_TNIL); /* assert invariants: */
|
|
|
+ lua_assert(ttype(val(t->node)) == LUA_TNIL);
|
|
|
+ lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ t->node = luaM_newvector(L, size, Node);
|
|
|
+ for (i=0; i<size; i++) {
|
|
|
+ t->node[i].next = NULL;
|
|
|
+ setnilvalue(key(node(t, i)));
|
|
|
+ setnilvalue(val(node(t, i)));
|
|
|
+ }
|
|
|
}
|
|
|
t->lsizenode = cast(lu_byte, lsize);
|
|
|
t->firstfree = node(t, size-1); /* first free position to be used */
|
|
@@ -235,14 +235,22 @@ static void setnodevector (lua_State *L, Table *t, int lsize) {
|
|
|
|
|
|
static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
|
|
|
int i;
|
|
|
- int oldasize, oldhsize;
|
|
|
+ int oldasize = t->sizearray;
|
|
|
+ int oldhsize = t->lsizenode;
|
|
|
Node *nold;
|
|
|
- oldasize = t->sizearray;
|
|
|
+ Node temp[1];
|
|
|
+ if (oldhsize)
|
|
|
+ nold = t->node; /* save old hash ... */
|
|
|
+ else { /* old hash is `dummynode' */
|
|
|
+ lua_assert(t->node == G(L)->dummynode);
|
|
|
+ temp[0] = t->node[0]; /* copy it to `temp' (in case of errors) */
|
|
|
+ nold = temp;
|
|
|
+ setnilvalue(key(G(L)->dummynode)); /* restate invariant */
|
|
|
+ setnilvalue(val(G(L)->dummynode));
|
|
|
+ }
|
|
|
if (nasize > oldasize) /* should grow array part? */
|
|
|
setarrayvector(L, t, nasize);
|
|
|
/* create new hash part with appropriate size */
|
|
|
- nold = t->node; /* save old hash ... */
|
|
|
- oldhsize = t->lsizenode; /* ... and (log of) old size */
|
|
|
setnodevector(L, t, nhsize);
|
|
|
/* re-insert elements */
|
|
|
if (nasize < oldasize) { /* array part must shrink? */
|
|
@@ -262,7 +270,8 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
|
|
|
if (ttype(val(old)) != LUA_TNIL)
|
|
|
luaH_set(L, t, key(old), val(old));
|
|
|
}
|
|
|
- luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
|
|
|
+ if (oldhsize)
|
|
|
+ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -299,8 +308,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
|
|
|
|
|
|
|
|
|
void luaH_free (lua_State *L, Table *t) {
|
|
|
- lua_assert(t->lsizenode > 0 || t->node == NULL);
|
|
|
- if (t->lsizenode > 0)
|
|
|
+ if (t->lsizenode)
|
|
|
luaM_freearray(L, t->node, sizenode(t), Node);
|
|
|
luaM_freearray(L, t->array, t->sizearray, TObject);
|
|
|
luaM_freelem(L, t);
|