** inserts a new key into a hash table; first, check whether key's main ** position is free. If not, check whether colliding node is in its main ** position or not: if it is not, move colliding node to an empty place and ** put new key in its main position; otherwise (colliding node is in its main ** position), new key goes to an empty position. */
| 439 | ** position), new key goes to an empty position. |
| 440 | */ |
| 441 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { |
| 442 | Node *mp; |
| 443 | TValue aux; |
| 444 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
| 445 | else if (ttisfloat(key)) { |
| 446 | lua_Number n = fltvalue(key); |
| 447 | lua_Integer k; |
| 448 | if (luai_numisnan(n)) |
| 449 | luaG_runerror(L, "table index is NaN"); |
| 450 | if (numisinteger(n, &k)) { /* index is int? */ |
| 451 | setivalue(&aux, k); |
| 452 | key = &aux; /* insert it as an integer */ |
| 453 | } |
| 454 | } |
| 455 | mp = mainposition(t, key); |
| 456 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ |
| 457 | Node *othern; |
| 458 | Node *f = getfreepos(t); /* get a free place */ |
| 459 | if (f == NULL) { /* cannot find a free place? */ |
| 460 | rehash(L, t, key); /* grow table */ |
| 461 | /* whatever called 'newkey' takes care of TM cache and GC barrier */ |
| 462 | return luaH_set(L, t, key); /* insert key into grown table */ |
| 463 | } |
| 464 | lua_assert(!isdummy(f)); |
| 465 | othern = mainposition(t, gkey(mp)); |
| 466 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 467 | /* yes; move colliding node into free position */ |
| 468 | while (othern + gnext(othern) != mp) /* find previous */ |
| 469 | othern += gnext(othern); |
| 470 | gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ |
| 471 | *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
| 472 | if (gnext(mp) != 0) { |
| 473 | gnext(f) += cast_int(mp - f); /* correct 'next' */ |
| 474 | gnext(mp) = 0; /* now 'mp' is free */ |
| 475 | } |
| 476 | setnilvalue(gval(mp)); |
| 477 | } |
| 478 | else { /* colliding node is in its own main position */ |
| 479 | /* new node will go into free position */ |
| 480 | if (gnext(mp) != 0) |
| 481 | gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ |
| 482 | else lua_assert(gnext(f) == 0); |
| 483 | gnext(mp) = cast_int(f - mp); |
| 484 | mp = f; |
| 485 | } |
| 486 | } |
| 487 | setnodekey(L, &mp->i_key, key); |
| 488 | luaC_barrierback(L, t, key); |
| 489 | lua_assert(ttisnil(gval(mp))); |
| 490 | return gval(mp); |
| 491 | } |
| 492 | |
| 493 | |
| 494 | /* |
no test coverage detected