** 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. */
| 574 | ** position), new key goes to an empty position. |
| 575 | */ |
| 576 | TValue *luaH_newkey(lua_State *L, Table *t, const TValue *key) { |
| 577 | Node *mp; |
| 578 | TValue aux; |
| 579 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
| 580 | else if (ttisfloat(key)) { |
| 581 | lua_Integer k; |
| 582 | if (luaV_tointeger(key, &k, 0)) { /* index is int? */ |
| 583 | setivalue(&aux, k); |
| 584 | key = &aux; /* insert it as an integer */ |
| 585 | } |
| 586 | else if (luai_numisnan(fltvalue(key))) |
| 587 | luaG_runerror(L, "table index is NaN"); |
| 588 | } |
| 589 | mp = mainposition(t, key); |
| 590 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ |
| 591 | Node *othern; |
| 592 | Node *f = getfreepos(t); /* get a free place */ |
| 593 | if (f == nullptr) { /* cannot find a free place? */ |
| 594 | rehash(L, t, key); /* grow table */ |
| 595 | /* whatever called 'newkey' takes care of TM cache */ |
| 596 | return luaH_set(L, t, key); /* insert key into grown table */ |
| 597 | } |
| 598 | lua_assert(!isdummy(f)); |
| 599 | othern = mainposition(t, gkey(mp)); |
| 600 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 601 | /* yes; move colliding node into free position */ |
| 602 | while (othern + gnext(othern) != mp) /* find previous */ |
| 603 | othern += gnext(othern); |
| 604 | gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ |
| 605 | *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
| 606 | if (gnext(mp) != 0) { |
| 607 | gnext(f) += cast_int(mp - f); /* correct 'next' */ |
| 608 | gnext(mp) = 0; /* now 'mp' is free */ |
| 609 | } |
| 610 | setnilvalue(gval(mp)); |
| 611 | } |
| 612 | else { /* colliding node is in its own main position */ |
| 613 | /* new node will go into free position */ |
| 614 | if (gnext(mp) != 0) |
| 615 | gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ |
| 616 | else lua_assert(gnext(f) == 0); |
| 617 | gnext(mp) = cast_int(f - mp); |
| 618 | mp = f; |
| 619 | } |
| 620 | } |
| 621 | setnodekey(L, &mp->i_key, key); |
| 622 | luaC_barrierback(L, t, key); |
| 623 | lua_assert(ttisnil(gval(mp))); |
| 624 | return gval(mp); |
| 625 | } |
| 626 | |
| 627 | |
| 628 | /* |
no test coverage detected