diff options
Diffstat (limited to '')
| -rw-r--r-- | ltable.c | 82 |
1 files changed, 50 insertions, 32 deletions
| @@ -234,41 +234,51 @@ l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) { | |||
| 234 | ** Check whether key 'k1' is equal to the key in node 'n2'. This | 234 | ** Check whether key 'k1' is equal to the key in node 'n2'. This |
| 235 | ** equality is raw, so there are no metamethods. Floats with integer | 235 | ** equality is raw, so there are no metamethods. Floats with integer |
| 236 | ** values have been normalized, so integers cannot be equal to | 236 | ** values have been normalized, so integers cannot be equal to |
| 237 | ** floats. It is assumed that 'eqshrstr' is simply pointer equality, so | 237 | ** floats. It is assumed that 'eqshrstr' is simply pointer equality, |
| 238 | ** that short strings are handled in the default case. | 238 | ** so that short strings are handled in the default case. The flag |
| 239 | ** A true 'deadok' means to accept dead keys as equal to their original | 239 | ** 'deadok' means to accept dead keys as equal to their original values. |
| 240 | ** values. All dead keys are compared in the default case, by pointer | 240 | ** (Only collectable objects can produce dead keys.) Note that dead |
| 241 | ** identity. (Only collectable objects can produce dead keys.) Note that | 241 | ** long strings are also compared by identity. Once a key is dead, |
| 242 | ** dead long strings are also compared by identity. | 242 | ** its corresponding value may be collected, and then another value |
| 243 | ** Once a key is dead, its corresponding value may be collected, and | 243 | ** can be created with the same address. If this other value is given |
| 244 | ** then another value can be created with the same address. If this | 244 | ** to 'next', 'equalkey' will signal a false positive. In a regular |
| 245 | ** other value is given to 'next', 'equalkey' will signal a false | 245 | ** traversal, this situation should never happen, as all keys given to |
| 246 | ** positive. In a regular traversal, this situation should never happen, | 246 | ** 'next' came from the table itself, and therefore could not have been |
| 247 | ** as all keys given to 'next' came from the table itself, and therefore | 247 | ** collected. Outside a regular traversal, we have garbage in, garbage |
| 248 | ** could not have been collected. Outside a regular traversal, we | 248 | ** out. What is relevant is that this false positive does not break |
| 249 | ** have garbage in, garbage out. What is relevant is that this false | 249 | ** anything. (In particular, 'next' will return some other valid item |
| 250 | ** positive does not break anything. (In particular, 'next' will return | 250 | ** on the table or nil.) |
| 251 | ** some other valid item on the table or nil.) | ||
| 252 | */ | 251 | */ |
| 253 | static int equalkey (const TValue *k1, const Node *n2, int deadok) { | 252 | static int equalkey (const TValue *k1, const Node *n2, int deadok) { |
| 254 | if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ | 253 | if (rawtt(k1) != keytt(n2)) { /* not the same variants? */ |
| 255 | !(deadok && keyisdead(n2) && iscollectable(k1))) | 254 | if (keyisshrstr(n2) && ttislngstring(k1)) { |
| 256 | return 0; /* cannot be same key */ | 255 | /* an external string can be equal to a short-string key */ |
| 257 | switch (keytt(n2)) { | 256 | return luaS_eqstr(tsvalue(k1), keystrval(n2)); |
| 258 | case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: | 257 | } |
| 259 | return 1; | 258 | else if (deadok && keyisdead(n2) && iscollectable(k1)) { |
| 260 | case LUA_VNUMINT: | 259 | /* a collectable value can be equal to a dead key */ |
| 261 | return (ivalue(k1) == keyival(n2)); | ||
| 262 | case LUA_VNUMFLT: | ||
| 263 | return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); | ||
| 264 | case LUA_VLIGHTUSERDATA: | ||
| 265 | return pvalue(k1) == pvalueraw(keyval(n2)); | ||
| 266 | case LUA_VLCF: | ||
| 267 | return fvalue(k1) == fvalueraw(keyval(n2)); | ||
| 268 | case ctb(LUA_VLNGSTR): | ||
| 269 | return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); | ||
| 270 | default: | ||
| 271 | return gcvalue(k1) == gcvalueraw(keyval(n2)); | 260 | return gcvalue(k1) == gcvalueraw(keyval(n2)); |
| 261 | } | ||
| 262 | else | ||
| 263 | return 0; /* otherwise, different variants cannot be equal */ | ||
| 264 | } | ||
| 265 | else { /* equal variants */ | ||
| 266 | switch (keytt(n2)) { | ||
| 267 | case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: | ||
| 268 | return 1; | ||
| 269 | case LUA_VNUMINT: | ||
| 270 | return (ivalue(k1) == keyival(n2)); | ||
| 271 | case LUA_VNUMFLT: | ||
| 272 | return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); | ||
| 273 | case LUA_VLIGHTUSERDATA: | ||
| 274 | return pvalue(k1) == pvalueraw(keyval(n2)); | ||
| 275 | case LUA_VLCF: | ||
| 276 | return fvalue(k1) == fvalueraw(keyval(n2)); | ||
| 277 | case ctb(LUA_VLNGSTR): | ||
| 278 | return luaS_eqstr(tsvalue(k1), keystrval(n2)); | ||
| 279 | default: | ||
| 280 | return gcvalue(k1) == gcvalueraw(keyval(n2)); | ||
| 281 | } | ||
| 272 | } | 282 | } |
| 273 | } | 283 | } |
| 274 | 284 | ||
| @@ -1158,6 +1168,14 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key, | |||
| 1158 | else if (l_unlikely(luai_numisnan(f))) | 1168 | else if (l_unlikely(luai_numisnan(f))) |
| 1159 | luaG_runerror(L, "table index is NaN"); | 1169 | luaG_runerror(L, "table index is NaN"); |
| 1160 | } | 1170 | } |
| 1171 | else if (isextstr(key)) { /* external string? */ | ||
| 1172 | /* If string is short, must internalize it to be used as table key */ | ||
| 1173 | TString *ts = luaS_normstr(L, tsvalue(key)); | ||
| 1174 | setsvalue2s(L, L->top.p++, ts); /* anchor 'ts' (EXTRA_STACK) */ | ||
| 1175 | luaH_newkey(L, t, s2v(L->top.p - 1), value); | ||
| 1176 | L->top.p--; | ||
| 1177 | return; | ||
| 1178 | } | ||
| 1161 | luaH_newkey(L, t, key, value); | 1179 | luaH_newkey(L, t, key, value); |
| 1162 | } | 1180 | } |
| 1163 | else if (hres > 0) { /* regular Node? */ | 1181 | else if (hres > 0) { /* regular Node? */ |
