diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2006-01-10 10:51:53 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2006-01-10 10:51:53 -0200 |
commit | ffb798e1e2deb1fe0f931e1f6c5b6d91f694051c (patch) | |
tree | 325354bd5b01893821ae7aed0bab0409027ef431 | |
parent | fa936f8fa9d391de08901339de044b783011adfa (diff) | |
download | lua-ffb798e1e2deb1fe0f931e1f6c5b6d91f694051c.tar.gz lua-ffb798e1e2deb1fe0f931e1f6c5b6d91f694051c.tar.bz2 lua-ffb798e1e2deb1fe0f931e1f6c5b6d91f694051c.zip |
avoids type punning for table keys
-rw-r--r-- | lobject.h | 14 | ||||
-rw-r--r-- | ltable.c | 49 | ||||
-rw-r--r-- | ltable.h | 14 |
3 files changed, 42 insertions, 35 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 2.17 2005/06/13 14:19:00 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.18 2005/10/24 17:37:33 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -323,9 +323,12 @@ typedef union Closure { | |||
323 | ** Tables | 323 | ** Tables |
324 | */ | 324 | */ |
325 | 325 | ||
326 | typedef struct TKey { | 326 | typedef union TKey { |
327 | TValuefields; | 327 | struct { |
328 | struct Node *next; /* for chaining */ | 328 | TValuefields; |
329 | struct Node *next; /* for chaining */ | ||
330 | } nk; | ||
331 | TValue tvk; | ||
329 | } TKey; | 332 | } TKey; |
330 | 333 | ||
331 | 334 | ||
@@ -360,8 +363,9 @@ typedef struct Table { | |||
360 | #define sizenode(t) (twoto((t)->lsizenode)) | 363 | #define sizenode(t) (twoto((t)->lsizenode)) |
361 | 364 | ||
362 | 365 | ||
366 | #define luaO_nilobject (&luaO_nilobject_) | ||
363 | 367 | ||
364 | LUAI_DATA const TValue luaO_nilobject; | 368 | LUAI_DATA const TValue luaO_nilobject_; |
365 | 369 | ||
366 | #define ceillog2(x) (luaO_log2((x)-1) + 1) | 370 | #define ceillog2(x) (luaO_log2((x)-1) + 1) |
367 | 371 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.28 2005/11/25 13:29:32 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.29 2005/12/22 16:19:56 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 | */ |
@@ -70,9 +70,9 @@ | |||
70 | 70 | ||
71 | 71 | ||
72 | 72 | ||
73 | const Node luaH_dummynode = { | 73 | const Node luaH_dummynode_ = { |
74 | {{NULL}, LUA_TNIL}, /* value */ | 74 | {{NULL}, LUA_TNIL}, /* value */ |
75 | {{NULL}, LUA_TNIL, NULL} /* key */ | 75 | {{{NULL}, LUA_TNIL, NULL}} /* key */ |
76 | }; | 76 | }; |
77 | 77 | ||
78 | 78 | ||
@@ -270,7 +270,7 @@ static void setarrayvector (lua_State *L, Table *t, int size) { | |||
270 | static void setnodevector (lua_State *L, Table *t, int size) { | 270 | static void setnodevector (lua_State *L, Table *t, int size) { |
271 | int lsize; | 271 | int lsize; |
272 | if (size == 0) { /* no elements to hash part? */ | 272 | if (size == 0) { /* no elements to hash part? */ |
273 | t->node = cast(Node *, &luaH_dummynode); /* use common `dummynode' */ | 273 | t->node = cast(Node *, luaH_dummynode); /* use common `dummynode' */ |
274 | lsize = 0; | 274 | lsize = 0; |
275 | } | 275 | } |
276 | else { | 276 | else { |
@@ -281,9 +281,10 @@ static void setnodevector (lua_State *L, Table *t, int size) { | |||
281 | size = twoto(lsize); | 281 | size = twoto(lsize); |
282 | t->node = luaM_newvector(L, size, Node); | 282 | t->node = luaM_newvector(L, size, Node); |
283 | for (i=0; i<size; i++) { | 283 | for (i=0; i<size; i++) { |
284 | gnext(&t->node[i]) = NULL; | 284 | Node *n = gnode(t, i); |
285 | setnilvalue(gkey(gnode(t, i))); | 285 | gnext(n) = NULL; |
286 | setnilvalue(gval(gnode(t, i))); | 286 | setnilvalue(gkey(n)); |
287 | setnilvalue(gval(n)); | ||
287 | } | 288 | } |
288 | } | 289 | } |
289 | t->lsizenode = cast_byte(lsize); | 290 | t->lsizenode = cast_byte(lsize); |
@@ -316,13 +317,13 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { | |||
316 | if (!ttisnil(gval(old))) | 317 | if (!ttisnil(gval(old))) |
317 | setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); | 318 | setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); |
318 | } | 319 | } |
319 | if (nold != &luaH_dummynode) | 320 | if (nold != luaH_dummynode) |
320 | luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ | 321 | luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ |
321 | } | 322 | } |
322 | 323 | ||
323 | 324 | ||
324 | void luaH_resizearray (lua_State *L, Table *t, int nasize) { | 325 | void luaH_resizearray (lua_State *L, Table *t, int nasize) { |
325 | int nsize = (t->node == &luaH_dummynode) ? 0 : sizenode(t); | 326 | int nsize = (t->node == luaH_dummynode) ? 0 : sizenode(t); |
326 | resize(L, t, nasize, nsize); | 327 | resize(L, t, nasize, nsize); |
327 | } | 328 | } |
328 | 329 | ||
@@ -361,7 +362,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) { | |||
361 | t->array = NULL; | 362 | t->array = NULL; |
362 | t->sizearray = 0; | 363 | t->sizearray = 0; |
363 | t->lsizenode = 0; | 364 | t->lsizenode = 0; |
364 | t->node = cast(Node *, &luaH_dummynode); | 365 | t->node = cast(Node *, luaH_dummynode); |
365 | setarrayvector(L, t, narray); | 366 | setarrayvector(L, t, narray); |
366 | setnodevector(L, t, nhash); | 367 | setnodevector(L, t, nhash); |
367 | return t; | 368 | return t; |
@@ -369,7 +370,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) { | |||
369 | 370 | ||
370 | 371 | ||
371 | void luaH_free (lua_State *L, Table *t) { | 372 | void luaH_free (lua_State *L, Table *t) { |
372 | if (t->node != &luaH_dummynode) | 373 | if (t->node != luaH_dummynode) |
373 | luaM_freearray(L, t->node, sizenode(t), Node); | 374 | luaM_freearray(L, t->node, sizenode(t), Node); |
374 | luaM_freearray(L, t->array, t->sizearray, TValue); | 375 | luaM_freearray(L, t->array, t->sizearray, TValue); |
375 | luaM_free(L, t); | 376 | luaM_free(L, t); |
@@ -395,14 +396,14 @@ static Node *getfreepos (Table *t) { | |||
395 | */ | 396 | */ |
396 | static TValue *newkey (lua_State *L, Table *t, const TValue *key) { | 397 | static TValue *newkey (lua_State *L, Table *t, const TValue *key) { |
397 | Node *mp = luaH_mainposition(t, key); | 398 | Node *mp = luaH_mainposition(t, key); |
398 | if (!ttisnil(gval(mp)) || mp == &luaH_dummynode) { | 399 | if (!ttisnil(gval(mp)) || mp == luaH_dummynode) { |
399 | Node *othern; | 400 | Node *othern; |
400 | Node *n = getfreepos(t); /* get a free place */ | 401 | Node *n = getfreepos(t); /* get a free place */ |
401 | if (n == NULL) { /* cannot find a free place? */ | 402 | if (n == NULL) { /* cannot find a free place? */ |
402 | rehash(L, t, key); /* grow table */ | 403 | rehash(L, t, key); /* grow table */ |
403 | return luaH_set(L, t, key); /* re-insert key into grown table */ | 404 | return luaH_set(L, t, key); /* re-insert key into grown table */ |
404 | } | 405 | } |
405 | lua_assert(n != &luaH_dummynode); | 406 | lua_assert(n != luaH_dummynode); |
406 | othern = luaH_mainposition(t, key2tval(mp)); | 407 | othern = luaH_mainposition(t, key2tval(mp)); |
407 | if (othern != mp) { /* is colliding node out of its main position? */ | 408 | if (othern != mp) { /* is colliding node out of its main position? */ |
408 | /* yes; move colliding node into free position */ | 409 | /* yes; move colliding node into free position */ |
@@ -441,7 +442,7 @@ const TValue *luaH_getnum (Table *t, int key) { | |||
441 | return gval(n); /* that's it */ | 442 | return gval(n); /* that's it */ |
442 | else n = gnext(n); | 443 | else n = gnext(n); |
443 | } while (n); | 444 | } while (n); |
444 | return &luaO_nilobject; | 445 | return luaO_nilobject; |
445 | } | 446 | } |
446 | } | 447 | } |
447 | 448 | ||
@@ -456,7 +457,7 @@ const TValue *luaH_getstr (Table *t, TString *key) { | |||
456 | return gval(n); /* that's it */ | 457 | return gval(n); /* that's it */ |
457 | else n = gnext(n); | 458 | else n = gnext(n); |
458 | } while (n); | 459 | } while (n); |
459 | return &luaO_nilobject; | 460 | return luaO_nilobject; |
460 | } | 461 | } |
461 | 462 | ||
462 | 463 | ||
@@ -465,7 +466,7 @@ const TValue *luaH_getstr (Table *t, TString *key) { | |||
465 | */ | 466 | */ |
466 | const TValue *luaH_get (Table *t, const TValue *key) { | 467 | const TValue *luaH_get (Table *t, const TValue *key) { |
467 | switch (ttype(key)) { | 468 | switch (ttype(key)) { |
468 | case LUA_TNIL: return &luaO_nilobject; | 469 | case LUA_TNIL: return luaO_nilobject; |
469 | case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); | 470 | case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); |
470 | case LUA_TNUMBER: { | 471 | case LUA_TNUMBER: { |
471 | int k; | 472 | int k; |
@@ -482,7 +483,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
482 | return gval(n); /* that's it */ | 483 | return gval(n); /* that's it */ |
483 | else n = gnext(n); | 484 | else n = gnext(n); |
484 | } while (n); | 485 | } while (n); |
485 | return &luaO_nilobject; | 486 | return luaO_nilobject; |
486 | } | 487 | } |
487 | } | 488 | } |
488 | } | 489 | } |
@@ -491,7 +492,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
491 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | 492 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { |
492 | const TValue *p = luaH_get(t, key); | 493 | const TValue *p = luaH_get(t, key); |
493 | t->flags = 0; | 494 | t->flags = 0; |
494 | if (p != &luaO_nilobject) | 495 | if (p != luaO_nilobject) |
495 | return cast(TValue *, p); | 496 | return cast(TValue *, p); |
496 | else { | 497 | else { |
497 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); | 498 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
@@ -504,7 +505,7 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | |||
504 | 505 | ||
505 | TValue *luaH_setnum (lua_State *L, Table *t, int key) { | 506 | TValue *luaH_setnum (lua_State *L, Table *t, int key) { |
506 | const TValue *p = luaH_getnum(t, key); | 507 | const TValue *p = luaH_getnum(t, key); |
507 | if (p != &luaO_nilobject) | 508 | if (p != luaO_nilobject) |
508 | return cast(TValue *, p); | 509 | return cast(TValue *, p); |
509 | else { | 510 | else { |
510 | TValue k; | 511 | TValue k; |
@@ -516,7 +517,7 @@ TValue *luaH_setnum (lua_State *L, Table *t, int key) { | |||
516 | 517 | ||
517 | TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { | 518 | TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { |
518 | const TValue *p = luaH_getstr(t, key); | 519 | const TValue *p = luaH_getstr(t, key); |
519 | if (p != &luaO_nilobject) | 520 | if (p != luaO_nilobject) |
520 | return cast(TValue *, p); | 521 | return cast(TValue *, p); |
521 | else { | 522 | else { |
522 | TValue k; | 523 | TValue k; |
@@ -528,11 +529,11 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { | |||
528 | 529 | ||
529 | static int unbound_search (Table *t, unsigned int j) { | 530 | static int unbound_search (Table *t, unsigned int j) { |
530 | unsigned int i = j; /* i is zero or a present index */ | 531 | unsigned int i = j; /* i is zero or a present index */ |
531 | j = j+1; | 532 | j++; |
532 | /* find `i' and `j' such that i is present and j is not */ | 533 | /* find `i' and `j' such that i is present and j is not */ |
533 | while (!ttisnil(luaH_getnum(t, j))) { | 534 | while (!ttisnil(luaH_getnum(t, j))) { |
534 | i = j; | 535 | i = j; |
535 | j = i*2; | 536 | j *= 2; |
536 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ | 537 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ |
537 | /* table was built with bad purposes: resort to linear search */ | 538 | /* table was built with bad purposes: resort to linear search */ |
538 | i = 1; | 539 | i = 1; |
@@ -541,7 +542,7 @@ static int unbound_search (Table *t, unsigned int j) { | |||
541 | } | 542 | } |
542 | } | 543 | } |
543 | /* now do a binary search between them */ | 544 | /* now do a binary search between them */ |
544 | while (i < j-1) { | 545 | while (j - i > 1) { |
545 | unsigned int m = (i+j)/2; | 546 | unsigned int m = (i+j)/2; |
546 | if (ttisnil(luaH_getnum(t, m))) j = m; | 547 | if (ttisnil(luaH_getnum(t, m))) j = m; |
547 | else i = m; | 548 | else i = m; |
@@ -567,7 +568,7 @@ int luaH_getn (Table *t) { | |||
567 | return i; | 568 | return i; |
568 | } | 569 | } |
569 | /* else must find a boundary in hash part */ | 570 | /* else must find a boundary in hash part */ |
570 | else if (t->node == &luaH_dummynode) /* hash part is empty? */ | 571 | else if (t->node == luaH_dummynode) /* hash part is empty? */ |
571 | return j; /* that is easy... */ | 572 | return j; /* that is easy... */ |
572 | else return unbound_search(t, j); | 573 | else return unbound_search(t, j); |
573 | } | 574 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.h,v 2.7 2005/04/25 19:24:10 roberto Exp roberto $ | 2 | ** $Id: ltable.h,v 2.8 2005/06/06 13:30:25 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 | */ |
@@ -11,15 +11,13 @@ | |||
11 | 11 | ||
12 | 12 | ||
13 | #define gnode(t,i) (&(t)->node[i]) | 13 | #define gnode(t,i) (&(t)->node[i]) |
14 | #define gkey(n) (&(n)->i_key) | 14 | #define gkey(n) (&(n)->i_key.nk) |
15 | #define gval(n) (&(n)->i_val) | 15 | #define gval(n) (&(n)->i_val) |
16 | #define gnext(n) ((n)->i_key.next) | 16 | #define gnext(n) ((n)->i_key.nk.next) |
17 | 17 | ||
18 | #define key2tval(n) (cast(const TValue *, gkey(n))) | 18 | #define key2tval(n) (&(n)->i_key.tvk) |
19 | 19 | ||
20 | 20 | ||
21 | LUAI_DATA const Node luaH_dummynode; | ||
22 | |||
23 | LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); | 21 | LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); |
24 | LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); | 22 | LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); |
25 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); | 23 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); |
@@ -35,5 +33,9 @@ LUAI_FUNC int luaH_getn (Table *t); | |||
35 | /* exported only for debugging */ | 33 | /* exported only for debugging */ |
36 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); | 34 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); |
37 | 35 | ||
36 | #define luaH_dummynode (&luaH_dummynode_) | ||
37 | |||
38 | LUAI_DATA const Node luaH_dummynode_; | ||
39 | |||
38 | 40 | ||
39 | #endif | 41 | #endif |