diff options
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 68 |
1 files changed, 44 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.77 2013/05/29 14:05:03 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.78 2013/06/20 15:02:49 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -79,7 +79,7 @@ | |||
79 | 79 | ||
80 | static const Node dummynode_ = { | 80 | static const Node dummynode_ = { |
81 | {NILCONSTANT}, /* value */ | 81 | {NILCONSTANT}, /* value */ |
82 | {{NILCONSTANT, NULL}} /* key */ | 82 | {{NILCONSTANT, 0}} /* key */ |
83 | }; | 83 | }; |
84 | 84 | ||
85 | 85 | ||
@@ -158,6 +158,7 @@ static int findindex (lua_State *L, Table *t, StkId key) { | |||
158 | if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ | 158 | if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ |
159 | return i-1; /* yes; that's the index (corrected to C) */ | 159 | return i-1; /* yes; that's the index (corrected to C) */ |
160 | else { | 160 | else { |
161 | int nx; | ||
161 | Node *n = mainposition(t, key); | 162 | Node *n = mainposition(t, key); |
162 | for (;;) { /* check whether `key' is somewhere in the chain */ | 163 | for (;;) { /* check whether `key' is somewhere in the chain */ |
163 | /* key may be dead already, but it is ok to use it in `next' */ | 164 | /* key may be dead already, but it is ok to use it in `next' */ |
@@ -168,9 +169,10 @@ static int findindex (lua_State *L, Table *t, StkId key) { | |||
168 | /* hash elements are numbered after array ones */ | 169 | /* hash elements are numbered after array ones */ |
169 | return i + t->sizearray; | 170 | return i + t->sizearray; |
170 | } | 171 | } |
171 | else n = gnext(n); | 172 | nx = gnext(n); |
172 | if (n == NULL) | 173 | if (nx == 0) |
173 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ | 174 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ |
175 | else n += nx; | ||
174 | } | 176 | } |
175 | } | 177 | } |
176 | } | 178 | } |
@@ -301,7 +303,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { | |||
301 | t->node = luaM_newvector(L, size, Node); | 303 | t->node = luaM_newvector(L, size, Node); |
302 | for (i=0; i<size; i++) { | 304 | for (i=0; i<size; i++) { |
303 | Node *n = gnode(t, i); | 305 | Node *n = gnode(t, i); |
304 | gnext(n) = NULL; | 306 | gnext(n) = 0; |
305 | setnilvalue(gkey(n)); | 307 | setnilvalue(gkey(n)); |
306 | setnilvalue(gval(n)); | 308 | setnilvalue(gval(n)); |
307 | } | 309 | } |
@@ -429,27 +431,33 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
429 | mp = mainposition(t, key); | 431 | mp = mainposition(t, key); |
430 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ | 432 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ |
431 | Node *othern; | 433 | Node *othern; |
432 | Node *n = getfreepos(t); /* get a free place */ | 434 | Node *f = getfreepos(t); /* get a free place */ |
433 | if (n == NULL) { /* cannot find a free place? */ | 435 | if (f == NULL) { /* cannot find a free place? */ |
434 | rehash(L, t, key); /* grow table */ | 436 | rehash(L, t, key); /* grow table */ |
435 | /* whatever called 'newkey' take care of TM cache and GC barrier */ | 437 | /* whatever called 'newkey' take care of TM cache and GC barrier */ |
436 | return luaH_set(L, t, key); /* insert key into grown table */ | 438 | return luaH_set(L, t, key); /* insert key into grown table */ |
437 | } | 439 | } |
438 | lua_assert(!isdummy(n)); | 440 | lua_assert(!isdummy(f)); |
439 | othern = mainposition(t, gkey(mp)); | 441 | othern = mainposition(t, gkey(mp)); |
440 | if (othern != mp) { /* is colliding node out of its main position? */ | 442 | if (othern != mp) { /* is colliding node out of its main position? */ |
441 | /* yes; move colliding node into free position */ | 443 | /* yes; move colliding node into free position */ |
442 | while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ | 444 | while (othern + gnext(othern) != mp) /* find previous */ |
443 | gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ | 445 | othern += gnext(othern); |
444 | *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ | 446 | gnext(othern) = f - othern; /* re-chain with 'f' in place of 'mp' */ |
445 | gnext(mp) = NULL; /* now `mp' is free */ | 447 | *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
448 | if (gnext(mp) != 0) { | ||
449 | gnext(f) += mp - f; /* correct 'next' */ | ||
450 | gnext(mp) = 0; /* now 'mp' is free */ | ||
451 | } | ||
446 | setnilvalue(gval(mp)); | 452 | setnilvalue(gval(mp)); |
447 | } | 453 | } |
448 | else { /* colliding node is in its own main position */ | 454 | else { /* colliding node is in its own main position */ |
449 | /* new node will go into free position */ | 455 | /* new node will go into free position */ |
450 | gnext(n) = gnext(mp); /* chain new position */ | 456 | if (gnext(mp) != 0) |
451 | gnext(mp) = n; | 457 | gnext(f) = (mp + gnext(mp)) - f; /* chain new position */ |
452 | mp = n; | 458 | else lua_assert(gnext(f) == 0); |
459 | gnext(mp) = f - mp; | ||
460 | mp = f; | ||
453 | } | 461 | } |
454 | } | 462 | } |
455 | setobj2t(L, gkey(mp), key); | 463 | setobj2t(L, gkey(mp), key); |
@@ -468,11 +476,15 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
468 | return &t->array[key - 1]; | 476 | return &t->array[key - 1]; |
469 | else { | 477 | else { |
470 | Node *n = hashint(t, key); | 478 | Node *n = hashint(t, key); |
471 | do { /* check whether `key' is somewhere in the chain */ | 479 | for (;;) { /* check whether `key' is somewhere in the chain */ |
472 | if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) | 480 | if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) |
473 | return gval(n); /* that's it */ | 481 | return gval(n); /* that's it */ |
474 | else n = gnext(n); | 482 | else { |
475 | } while (n); | 483 | int nx = gnext(n); |
484 | if (nx == 0) break; | ||
485 | n += nx; | ||
486 | } | ||
487 | }; | ||
476 | return luaO_nilobject; | 488 | return luaO_nilobject; |
477 | } | 489 | } |
478 | } | 490 | } |
@@ -484,11 +496,15 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
484 | const TValue *luaH_getstr (Table *t, TString *key) { | 496 | const TValue *luaH_getstr (Table *t, TString *key) { |
485 | Node *n = hashstr(t, key); | 497 | Node *n = hashstr(t, key); |
486 | lua_assert(key->tsv.tt == LUA_TSHRSTR); | 498 | lua_assert(key->tsv.tt == LUA_TSHRSTR); |
487 | do { /* check whether `key' is somewhere in the chain */ | 499 | for (;;) { /* check whether `key' is somewhere in the chain */ |
488 | if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) | 500 | if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) |
489 | return gval(n); /* that's it */ | 501 | return gval(n); /* that's it */ |
490 | else n = gnext(n); | 502 | else { |
491 | } while (n); | 503 | int nx = gnext(n); |
504 | if (nx == 0) break; | ||
505 | n += nx; | ||
506 | } | ||
507 | }; | ||
492 | return luaO_nilobject; | 508 | return luaO_nilobject; |
493 | } | 509 | } |
494 | 510 | ||
@@ -509,11 +525,15 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
509 | } | 525 | } |
510 | default: { | 526 | default: { |
511 | Node *n = mainposition(t, key); | 527 | Node *n = mainposition(t, key); |
512 | do { /* check whether `key' is somewhere in the chain */ | 528 | for (;;) { /* check whether `key' is somewhere in the chain */ |
513 | if (luaV_rawequalobj(gkey(n), key)) | 529 | if (luaV_rawequalobj(gkey(n), key)) |
514 | return gval(n); /* that's it */ | 530 | return gval(n); /* that's it */ |
515 | else n = gnext(n); | 531 | else { |
516 | } while (n); | 532 | int nx = gnext(n); |
533 | if (nx == 0) break; | ||
534 | n += nx; | ||
535 | } | ||
536 | }; | ||
517 | return luaO_nilobject; | 537 | return luaO_nilobject; |
518 | } | 538 | } |
519 | } | 539 | } |