diff --git a/hash.c b/hash.c index 6ccdc932..916a0d43 100644 --- a/hash.c +++ b/hash.c @@ -3,7 +3,7 @@ ** hash manager for lua */ -char *rcs_hash="$Id: hash.c,v 2.6 1994/08/17 17:41:23 celes Exp celes $"; +char *rcs_hash="$Id: hash.c,v 2.7 1994/09/08 15:27:10 celes Exp celes $"; #include #include @@ -33,19 +33,14 @@ char *rcs_hash="$Id: hash.c,v 2.6 1994/08/17 17:41:23 celes Exp celes $"; #define REHASH_LIMIT 0.70 /* avoid more than this % full */ -typedef struct ArrayList -{ - Hash *array; - struct ArrayList *next; -} ArrayList; - -static ArrayList *listhead = NULL; +static Hash *listhead = NULL; /* hash dimensions values */ static int dimensions[] = - {7, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, 12853, 25717, 51437, 0}; + {3, 5, 7, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, + 12853, 25717, 51437, 0}; static int redimension (int nhash) { int i; @@ -89,23 +84,27 @@ static int index (Hash *t, Object *ref) /* hash function */ } } +static int equalObj (Object *t1, Object *t2) +{ + if (tag(t1) != tag(t2)) return 0; + switch (tag(t1)) + { + case T_NUMBER: return nvalue(t1) == nvalue(t2); + case T_STRING: return streq(svalue(t1), svalue(t2)); + default: return uvalue(t1) == uvalue(t2); + } +} + static int present (Hash *t, Object *ref) { int h = index(t, ref); if (h < 0) return h; while (tag(ref(node(t, h))) != T_NIL) { - if (tag(ref) == T_NUMBER && tag(ref(node(t, h))) == T_NUMBER && - nvalue(ref) == nvalue(ref(node(t, h))) - ) return h; - if (tag(ref) == T_STRING && tag(ref(node(t, h))) == T_STRING && - streq(svalue(ref),svalue(ref(node(t, h)))) - ) return h; - if (tag(ref) == tag(ref(node(t, h))) && - uvalue(ref) == uvalue(ref(node(t, h))) /* all others are pointers */ - ) return h; + if (equalObj(ref, ref(node(t, h)))) + return h; h = (h+1) % nhash(t); - } + } return h; } @@ -138,7 +137,7 @@ static Hash *hashcreate (int nhash) lua_error ("not enough memory"); return NULL; } - nhash = redimension(nhash); + nhash = redimension((int)((float)nhash/REHASH_LIMIT)); nodevector(t) = hashnodecreate(nhash); if (nodevector(t) == NULL) @@ -187,43 +186,36 @@ void lua_hashmark (Hash *h) */ void lua_hashcollector (void) { - ArrayList *curr = listhead, *prev = NULL; - while (curr != NULL) + Hash *curr_array = listhead, *prev = NULL; + while (curr_array != NULL) { - ArrayList *next = curr->next; - if (markarray(curr->array) != 1) + Hash *next = curr_array->next; + if (markarray(curr_array) != 1) { if (prev == NULL) listhead = next; else prev->next = next; - hashdelete(curr->array); - free(curr); + hashdelete(curr_array); } else { - markarray(curr->array) = 0; - prev = curr; + markarray(curr_array) = 0; + prev = curr_array; } - curr = next; + curr_array = next; } } /* ** Create a new array -** This function insert the new array at array list. It also -** execute garbage collection if the number of array created +** This function inserts the new array in the array list. It also +** executes garbage collection if the number of arrays created ** exceed a pre-defined range. */ Hash *lua_createarray (int nhash) { - ArrayList *new = new(ArrayList); - if (new == NULL) - { - lua_error ("not enough memory"); - return NULL; - } - new->array = hashcreate(nhash); - if (new->array == NULL) + Hash *array = hashcreate(nhash); + if (array == NULL) { lua_error ("not enough memory"); return NULL; @@ -233,9 +225,9 @@ Hash *lua_createarray (int nhash) lua_pack(); lua_nentity++; - new->next = listhead; - listhead = new; - return new->array; + array->next = listhead; + listhead = array; + return array; } @@ -268,7 +260,7 @@ Object *lua_hashget (Hash *t, Object *ref) static int count = 1000; static Object nil_obj = {T_NIL, {NULL}}; int h = present(t, ref); - if (h < 0) return NULL; + if (h < 0) return &nil_obj; if (tag(ref(node(t, h))) != T_NIL) return val(node(t, h)); if (--count == 0) { @@ -276,11 +268,13 @@ Object *lua_hashget (Hash *t, Object *ref) return &nil_obj; } - { /* check "parent" field */ + { /* check "parent" or "godparent" field */ Hash *p; Object parent; - tag(&parent) = T_STRING; - svalue(&parent) = "parent"; + Object godparent; + tag(&parent) = T_STRING; svalue(&parent) = "parent"; + tag(&godparent) = T_STRING; svalue(&godparent) = "godparent"; + h = present(t, &parent); /* assert(h >= 0); */ p = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? avalue(val(node(t, h))) : NULL; @@ -289,34 +283,14 @@ Object *lua_hashget (Hash *t, Object *ref) Object *r = lua_hashget(p, ref); if (tag(r) != T_NIL) { count++; return r; } } - } - { /* check "parents" field */ - Hash *ps; - Object parents; - tag(&parents) = T_STRING; - svalue(&parents) = "parents"; - h = present(t, &parents); /* assert(h >= 0); */ - ps = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? + h = present(t, &godparent); /* assert(h >= 0); */ + p = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? avalue(val(node(t, h))) : NULL; - if (ps != NULL) + if (p != NULL) { - Hash *p; - Object index; - tag(&index) = T_NUMBER; - nvalue(&index) = 1; - h = present(ps, &index); - p = tag(ref(node(ps, h))) != T_NIL && tag(val(node(ps, h))) == T_ARRAY ? - avalue(val(node(ps, h))) : NULL; - while (p != NULL) - { - Object *r = lua_hashget(p, ref); - if (tag(r) != T_NIL) { count++; return r; } - nvalue(&index)++; - h = present(ps, &index); - p = tag(ref(node(ps, h))) != T_NIL && tag(val(node(ps, h))) == T_ARRAY ? - avalue(val(node(ps, h))) : NULL; - } + Object *r = lua_hashget(p, ref); + if (tag(r) != T_NIL) { count++; return r; } } } count++; @@ -338,7 +312,7 @@ Object *lua_hashdefine (Hash *t, Object *ref) if (tag(ref(n)) == T_NIL) { nuse(t)++; - if (nuse(t) > nhash(t)*REHASH_LIMIT) + if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT) { rehash(t); h = present(t, ref);