diff options
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 63 |
1 files changed, 39 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -52,6 +52,7 @@ | |||
52 | 52 | ||
53 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) | 53 | #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) |
54 | #define hashboolean(t,p) hashpow2(t, p) | 54 | #define hashboolean(t,p) hashpow2(t, p) |
55 | #define hashint(t,i) hashpow2(t, i) | ||
55 | 56 | ||
56 | 57 | ||
57 | /* | 58 | /* |
@@ -96,8 +97,12 @@ static Node *hashnum (const Table *t, lua_Number n) { | |||
96 | */ | 97 | */ |
97 | static Node *mainposition (const Table *t, const TValue *key) { | 98 | static Node *mainposition (const Table *t, const TValue *key) { |
98 | switch (ttype(key)) { | 99 | switch (ttype(key)) { |
99 | case LUA_TNUMBER: | 100 | case LUA_TNUMINT: |
100 | return hashnum(t, nvalue(key)); | 101 | return hashint(t, ivalue(key)); |
102 | case LUA_TNUMFLT: | ||
103 | return hashnum(t, fltvalue(key)); | ||
104 | case LUA_TSHRSTR: | ||
105 | return hashstr(t, rawtsvalue(key)); | ||
101 | case LUA_TLNGSTR: { | 106 | case LUA_TLNGSTR: { |
102 | TString *s = rawtsvalue(key); | 107 | TString *s = rawtsvalue(key); |
103 | if (s->tsv.extra == 0) { /* no hash? */ | 108 | if (s->tsv.extra == 0) { /* no hash? */ |
@@ -106,8 +111,6 @@ static Node *mainposition (const Table *t, const TValue *key) { | |||
106 | } | 111 | } |
107 | return hashstr(t, rawtsvalue(key)); | 112 | return hashstr(t, rawtsvalue(key)); |
108 | } | 113 | } |
109 | case LUA_TSHRSTR: | ||
110 | return hashstr(t, rawtsvalue(key)); | ||
111 | case LUA_TBOOLEAN: | 114 | case LUA_TBOOLEAN: |
112 | return hashboolean(t, bvalue(key)); | 115 | return hashboolean(t, bvalue(key)); |
113 | case LUA_TLIGHTUSERDATA: | 116 | case LUA_TLIGHTUSERDATA: |
@@ -120,19 +123,24 @@ static Node *mainposition (const Table *t, const TValue *key) { | |||
120 | } | 123 | } |
121 | 124 | ||
122 | 125 | ||
126 | static int numisint (lua_Number n, int *p) { | ||
127 | int k; | ||
128 | lua_number2int(k, n); | ||
129 | if (luai_numeq(cast_num(k), n)) { /* 'k' is int? */ | ||
130 | *p = k; | ||
131 | return 1; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | |||
123 | /* | 137 | /* |
124 | ** returns the index for `key' if `key' is an appropriate key to live in | 138 | ** returns the index for `key' if `key' is an appropriate key to live in |
125 | ** the array part of the table, -1 otherwise. | 139 | ** the array part of the table, -1 otherwise. |
126 | */ | 140 | */ |
127 | static int arrayindex (const TValue *key) { | 141 | static int arrayindex (const TValue *key) { |
128 | if (ttisnumber(key)) { | 142 | if (ttisinteger(key)) return ivalue(key); |
129 | lua_Number n = nvalue(key); | 143 | else return -1; /* `key' did not match some condition */ |
130 | int k; | ||
131 | lua_number2int(k, n); | ||
132 | if (luai_numeq(cast_num(k), n)) | ||
133 | return k; | ||
134 | } | ||
135 | return -1; /* `key' did not match some condition */ | ||
136 | } | 144 | } |
137 | 145 | ||
138 | 146 | ||
@@ -170,7 +178,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { | |||
170 | int i = findindex(L, t, key); /* find original element */ | 178 | int i = findindex(L, t, key); /* find original element */ |
171 | for (i++; i < t->sizearray; i++) { /* try first array part */ | 179 | for (i++; i < t->sizearray; i++) { /* try first array part */ |
172 | if (!ttisnil(&t->array[i])) { /* a non-nil value? */ | 180 | if (!ttisnil(&t->array[i])) { /* a non-nil value? */ |
173 | setnvalue(key, cast_num(i+1)); | 181 | setivalue(key, i + 1); |
174 | setobj2s(L, key+1, &t->array[i]); | 182 | setobj2s(L, key+1, &t->array[i]); |
175 | return 1; | 183 | return 1; |
176 | } | 184 | } |
@@ -404,9 +412,18 @@ static Node *getfreepos (Table *t) { | |||
404 | */ | 412 | */ |
405 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | 413 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { |
406 | Node *mp; | 414 | Node *mp; |
415 | TValue aux; | ||
407 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); | 416 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
408 | else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) | 417 | else if (ttisfloat(key)) { |
409 | luaG_runerror(L, "table index is NaN"); | 418 | lua_Number n = fltvalue(key); |
419 | int k; | ||
420 | if (luai_numisnan(L, n)) | ||
421 | luaG_runerror(L, "table index is NaN"); | ||
422 | if (numisint(n, &k)) { /* index is int? */ | ||
423 | setivalue(&aux, k); | ||
424 | key = &aux; /* insert it as an integer */ | ||
425 | } | ||
426 | } | ||
410 | mp = mainposition(t, key); | 427 | mp = mainposition(t, key); |
411 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ | 428 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ |
412 | Node *othern; | 429 | Node *othern; |
@@ -448,10 +465,9 @@ const TValue *luaH_getint (Table *t, int key) { | |||
448 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) | 465 | if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) |
449 | return &t->array[key-1]; | 466 | return &t->array[key-1]; |
450 | else { | 467 | else { |
451 | lua_Number nk = cast_num(key); | 468 | Node *n = hashint(t, key); |
452 | Node *n = hashnum(t, nk); | ||
453 | do { /* check whether `key' is somewhere in the chain */ | 469 | do { /* check whether `key' is somewhere in the chain */ |
454 | if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) | 470 | if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) |
455 | return gval(n); /* that's it */ | 471 | return gval(n); /* that's it */ |
456 | else n = gnext(n); | 472 | else n = gnext(n); |
457 | } while (n); | 473 | } while (n); |
@@ -481,12 +497,11 @@ const TValue *luaH_getstr (Table *t, TString *key) { | |||
481 | const TValue *luaH_get (Table *t, const TValue *key) { | 497 | const TValue *luaH_get (Table *t, const TValue *key) { |
482 | switch (ttype(key)) { | 498 | switch (ttype(key)) { |
483 | case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); | 499 | case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); |
500 | case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); | ||
484 | case LUA_TNIL: return luaO_nilobject; | 501 | case LUA_TNIL: return luaO_nilobject; |
485 | case LUA_TNUMBER: { | 502 | case LUA_TNUMFLT: { |
486 | int k; | 503 | int k; |
487 | lua_Number n = nvalue(key); | 504 | if (numisint(fltvalue(key), &k)) /* index is int? */ |
488 | lua_number2int(k, n); | ||
489 | if (luai_numeq(cast_num(k), n)) /* index is int? */ | ||
490 | return luaH_getint(t, k); /* use specialized version */ | 505 | return luaH_getint(t, k); /* use specialized version */ |
491 | /* else go through */ | 506 | /* else go through */ |
492 | } | 507 | } |
@@ -522,7 +537,7 @@ void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { | |||
522 | cell = cast(TValue *, p); | 537 | cell = cast(TValue *, p); |
523 | else { | 538 | else { |
524 | TValue k; | 539 | TValue k; |
525 | setnvalue(&k, cast_num(key)); | 540 | setivalue(&k, key); |
526 | cell = luaH_newkey(L, t, &k); | 541 | cell = luaH_newkey(L, t, &k); |
527 | } | 542 | } |
528 | setobj2t(L, cell, value); | 543 | setobj2t(L, cell, value); |