diff options
| -rw-r--r-- | hash.c | 118 |
1 files changed, 46 insertions, 72 deletions
| @@ -3,7 +3,7 @@ | |||
| 3 | ** hash manager for lua | 3 | ** hash manager for lua |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | char *rcs_hash="$Id: hash.c,v 2.6 1994/08/17 17:41:23 celes Exp celes $"; | 6 | char *rcs_hash="$Id: hash.c,v 2.7 1994/09/08 15:27:10 celes Exp celes $"; |
| 7 | 7 | ||
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <stdlib.h> | 9 | #include <stdlib.h> |
| @@ -33,19 +33,14 @@ char *rcs_hash="$Id: hash.c,v 2.6 1994/08/17 17:41:23 celes Exp celes $"; | |||
| 33 | #define REHASH_LIMIT 0.70 /* avoid more than this % full */ | 33 | #define REHASH_LIMIT 0.70 /* avoid more than this % full */ |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | typedef struct ArrayList | 36 | static Hash *listhead = NULL; |
| 37 | { | ||
| 38 | Hash *array; | ||
| 39 | struct ArrayList *next; | ||
| 40 | } ArrayList; | ||
| 41 | |||
| 42 | static ArrayList *listhead = NULL; | ||
| 43 | 37 | ||
| 44 | 38 | ||
| 45 | 39 | ||
| 46 | /* hash dimensions values */ | 40 | /* hash dimensions values */ |
| 47 | static int dimensions[] = | 41 | static int dimensions[] = |
| 48 | {7, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, 12853, 25717, 51437, 0}; | 42 | {3, 5, 7, 11, 23, 47, 97, 197, 397, 797, 1597, 3203, 6421, |
| 43 | 12853, 25717, 51437, 0}; | ||
| 49 | static int redimension (int nhash) | 44 | static int redimension (int nhash) |
| 50 | { | 45 | { |
| 51 | int i; | 46 | int i; |
| @@ -89,23 +84,27 @@ static int index (Hash *t, Object *ref) /* hash function */ | |||
| 89 | } | 84 | } |
| 90 | } | 85 | } |
| 91 | 86 | ||
| 87 | static int equalObj (Object *t1, Object *t2) | ||
| 88 | { | ||
| 89 | if (tag(t1) != tag(t2)) return 0; | ||
| 90 | switch (tag(t1)) | ||
| 91 | { | ||
| 92 | case T_NUMBER: return nvalue(t1) == nvalue(t2); | ||
| 93 | case T_STRING: return streq(svalue(t1), svalue(t2)); | ||
| 94 | default: return uvalue(t1) == uvalue(t2); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 92 | static int present (Hash *t, Object *ref) | 98 | static int present (Hash *t, Object *ref) |
| 93 | { | 99 | { |
| 94 | int h = index(t, ref); | 100 | int h = index(t, ref); |
| 95 | if (h < 0) return h; | 101 | if (h < 0) return h; |
| 96 | while (tag(ref(node(t, h))) != T_NIL) | 102 | while (tag(ref(node(t, h))) != T_NIL) |
| 97 | { | 103 | { |
| 98 | if (tag(ref) == T_NUMBER && tag(ref(node(t, h))) == T_NUMBER && | 104 | if (equalObj(ref, ref(node(t, h)))) |
| 99 | nvalue(ref) == nvalue(ref(node(t, h))) | 105 | return h; |
| 100 | ) return h; | ||
| 101 | if (tag(ref) == T_STRING && tag(ref(node(t, h))) == T_STRING && | ||
| 102 | streq(svalue(ref),svalue(ref(node(t, h)))) | ||
| 103 | ) return h; | ||
| 104 | if (tag(ref) == tag(ref(node(t, h))) && | ||
| 105 | uvalue(ref) == uvalue(ref(node(t, h))) /* all others are pointers */ | ||
| 106 | ) return h; | ||
| 107 | h = (h+1) % nhash(t); | 106 | h = (h+1) % nhash(t); |
| 108 | } | 107 | } |
| 109 | return h; | 108 | return h; |
| 110 | } | 109 | } |
| 111 | 110 | ||
| @@ -138,7 +137,7 @@ static Hash *hashcreate (int nhash) | |||
| 138 | lua_error ("not enough memory"); | 137 | lua_error ("not enough memory"); |
| 139 | return NULL; | 138 | return NULL; |
| 140 | } | 139 | } |
| 141 | nhash = redimension(nhash); | 140 | nhash = redimension((int)((float)nhash/REHASH_LIMIT)); |
| 142 | 141 | ||
| 143 | nodevector(t) = hashnodecreate(nhash); | 142 | nodevector(t) = hashnodecreate(nhash); |
| 144 | if (nodevector(t) == NULL) | 143 | if (nodevector(t) == NULL) |
| @@ -187,43 +186,36 @@ void lua_hashmark (Hash *h) | |||
| 187 | */ | 186 | */ |
| 188 | void lua_hashcollector (void) | 187 | void lua_hashcollector (void) |
| 189 | { | 188 | { |
| 190 | ArrayList *curr = listhead, *prev = NULL; | 189 | Hash *curr_array = listhead, *prev = NULL; |
| 191 | while (curr != NULL) | 190 | while (curr_array != NULL) |
| 192 | { | 191 | { |
| 193 | ArrayList *next = curr->next; | 192 | Hash *next = curr_array->next; |
| 194 | if (markarray(curr->array) != 1) | 193 | if (markarray(curr_array) != 1) |
| 195 | { | 194 | { |
| 196 | if (prev == NULL) listhead = next; | 195 | if (prev == NULL) listhead = next; |
| 197 | else prev->next = next; | 196 | else prev->next = next; |
| 198 | hashdelete(curr->array); | 197 | hashdelete(curr_array); |
| 199 | free(curr); | ||
| 200 | } | 198 | } |
| 201 | else | 199 | else |
| 202 | { | 200 | { |
| 203 | markarray(curr->array) = 0; | 201 | markarray(curr_array) = 0; |
| 204 | prev = curr; | 202 | prev = curr_array; |
| 205 | } | 203 | } |
| 206 | curr = next; | 204 | curr_array = next; |
| 207 | } | 205 | } |
| 208 | } | 206 | } |
| 209 | 207 | ||
| 210 | 208 | ||
| 211 | /* | 209 | /* |
| 212 | ** Create a new array | 210 | ** Create a new array |
| 213 | ** This function insert the new array at array list. It also | 211 | ** This function inserts the new array in the array list. It also |
| 214 | ** execute garbage collection if the number of array created | 212 | ** executes garbage collection if the number of arrays created |
| 215 | ** exceed a pre-defined range. | 213 | ** exceed a pre-defined range. |
| 216 | */ | 214 | */ |
| 217 | Hash *lua_createarray (int nhash) | 215 | Hash *lua_createarray (int nhash) |
| 218 | { | 216 | { |
| 219 | ArrayList *new = new(ArrayList); | 217 | Hash *array = hashcreate(nhash); |
| 220 | if (new == NULL) | 218 | if (array == NULL) |
| 221 | { | ||
| 222 | lua_error ("not enough memory"); | ||
| 223 | return NULL; | ||
| 224 | } | ||
| 225 | new->array = hashcreate(nhash); | ||
| 226 | if (new->array == NULL) | ||
| 227 | { | 219 | { |
| 228 | lua_error ("not enough memory"); | 220 | lua_error ("not enough memory"); |
| 229 | return NULL; | 221 | return NULL; |
| @@ -233,9 +225,9 @@ Hash *lua_createarray (int nhash) | |||
| 233 | lua_pack(); | 225 | lua_pack(); |
| 234 | 226 | ||
| 235 | lua_nentity++; | 227 | lua_nentity++; |
| 236 | new->next = listhead; | 228 | array->next = listhead; |
| 237 | listhead = new; | 229 | listhead = array; |
| 238 | return new->array; | 230 | return array; |
| 239 | } | 231 | } |
| 240 | 232 | ||
| 241 | 233 | ||
| @@ -268,7 +260,7 @@ Object *lua_hashget (Hash *t, Object *ref) | |||
| 268 | static int count = 1000; | 260 | static int count = 1000; |
| 269 | static Object nil_obj = {T_NIL, {NULL}}; | 261 | static Object nil_obj = {T_NIL, {NULL}}; |
| 270 | int h = present(t, ref); | 262 | int h = present(t, ref); |
| 271 | if (h < 0) return NULL; | 263 | if (h < 0) return &nil_obj; |
| 272 | if (tag(ref(node(t, h))) != T_NIL) return val(node(t, h)); | 264 | if (tag(ref(node(t, h))) != T_NIL) return val(node(t, h)); |
| 273 | if (--count == 0) | 265 | if (--count == 0) |
| 274 | { | 266 | { |
| @@ -276,11 +268,13 @@ Object *lua_hashget (Hash *t, Object *ref) | |||
| 276 | return &nil_obj; | 268 | return &nil_obj; |
| 277 | } | 269 | } |
| 278 | 270 | ||
| 279 | { /* check "parent" field */ | 271 | { /* check "parent" or "godparent" field */ |
| 280 | Hash *p; | 272 | Hash *p; |
| 281 | Object parent; | 273 | Object parent; |
| 282 | tag(&parent) = T_STRING; | 274 | Object godparent; |
| 283 | svalue(&parent) = "parent"; | 275 | tag(&parent) = T_STRING; svalue(&parent) = "parent"; |
| 276 | tag(&godparent) = T_STRING; svalue(&godparent) = "godparent"; | ||
| 277 | |||
| 284 | h = present(t, &parent); /* assert(h >= 0); */ | 278 | h = present(t, &parent); /* assert(h >= 0); */ |
| 285 | p = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? | 279 | p = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? |
| 286 | avalue(val(node(t, h))) : NULL; | 280 | avalue(val(node(t, h))) : NULL; |
| @@ -289,34 +283,14 @@ Object *lua_hashget (Hash *t, Object *ref) | |||
| 289 | Object *r = lua_hashget(p, ref); | 283 | Object *r = lua_hashget(p, ref); |
| 290 | if (tag(r) != T_NIL) { count++; return r; } | 284 | if (tag(r) != T_NIL) { count++; return r; } |
| 291 | } | 285 | } |
| 292 | } | ||
| 293 | 286 | ||
| 294 | { /* check "parents" field */ | 287 | h = present(t, &godparent); /* assert(h >= 0); */ |
| 295 | Hash *ps; | 288 | p = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? |
| 296 | Object parents; | ||
| 297 | tag(&parents) = T_STRING; | ||
| 298 | svalue(&parents) = "parents"; | ||
| 299 | h = present(t, &parents); /* assert(h >= 0); */ | ||
| 300 | ps = tag(ref(node(t, h))) != T_NIL && tag(val(node(t, h))) == T_ARRAY ? | ||
| 301 | avalue(val(node(t, h))) : NULL; | 289 | avalue(val(node(t, h))) : NULL; |
| 302 | if (ps != NULL) | 290 | if (p != NULL) |
| 303 | { | 291 | { |
| 304 | Hash *p; | 292 | Object *r = lua_hashget(p, ref); |
| 305 | Object index; | 293 | if (tag(r) != T_NIL) { count++; return r; } |
| 306 | tag(&index) = T_NUMBER; | ||
| 307 | nvalue(&index) = 1; | ||
| 308 | h = present(ps, &index); | ||
| 309 | p = tag(ref(node(ps, h))) != T_NIL && tag(val(node(ps, h))) == T_ARRAY ? | ||
| 310 | avalue(val(node(ps, h))) : NULL; | ||
| 311 | while (p != NULL) | ||
| 312 | { | ||
| 313 | Object *r = lua_hashget(p, ref); | ||
| 314 | if (tag(r) != T_NIL) { count++; return r; } | ||
| 315 | nvalue(&index)++; | ||
| 316 | h = present(ps, &index); | ||
| 317 | p = tag(ref(node(ps, h))) != T_NIL && tag(val(node(ps, h))) == T_ARRAY ? | ||
| 318 | avalue(val(node(ps, h))) : NULL; | ||
| 319 | } | ||
| 320 | } | 294 | } |
| 321 | } | 295 | } |
| 322 | count++; | 296 | count++; |
| @@ -338,7 +312,7 @@ Object *lua_hashdefine (Hash *t, Object *ref) | |||
| 338 | if (tag(ref(n)) == T_NIL) | 312 | if (tag(ref(n)) == T_NIL) |
| 339 | { | 313 | { |
| 340 | nuse(t)++; | 314 | nuse(t)++; |
| 341 | if (nuse(t) > nhash(t)*REHASH_LIMIT) | 315 | if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT) |
| 342 | { | 316 | { |
| 343 | rehash(t); | 317 | rehash(t); |
| 344 | h = present(t, ref); | 318 | h = present(t, ref); |
