** 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. */
| 652 | ** position), new key goes to an empty position. |
| 653 | */ |
| 654 | void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { |
| 655 | Node *mp; |
| 656 | TValue aux; |
| 657 | if (l_unlikely(ttisnil(key))) |
| 658 | luaG_runerror(L, "table index is nil"); |
| 659 | else if (ttisfloat(key)) { |
| 660 | lua_Number f = fltvalue(key); |
| 661 | lua_Integer k; |
| 662 | if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */ |
| 663 | setivalue(&aux, k); |
| 664 | key = &aux; /* insert it as an integer */ |
| 665 | } |
| 666 | else if (l_unlikely(luai_numisnan(f))) |
| 667 | luaG_runerror(L, "table index is NaN"); |
| 668 | } |
| 669 | if (ttisnil(value)) |
| 670 | return; /* do not insert nil values */ |
| 671 | mp = mainpositionTV(t, key); |
| 672 | if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
| 673 | Node *othern; |
| 674 | Node *f = getfreepos(t); /* get a free place */ |
| 675 | if (f == NULL) { /* cannot find a free place? */ |
| 676 | rehash(L, t, key); /* grow table */ |
| 677 | /* whatever called 'newkey' takes care of TM cache */ |
| 678 | luaH_set(L, t, key, value); /* insert key into grown table */ |
| 679 | return; |
| 680 | } |
| 681 | lua_assert(!isdummy(t)); |
| 682 | othern = mainposition(t, keytt(mp), &keyval(mp)); |
| 683 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 684 | /* yes; move colliding node into free position */ |
| 685 | while (othern + gnext(othern) != mp) /* find previous */ |
| 686 | othern += gnext(othern); |
| 687 | gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ |
| 688 | *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
| 689 | if (gnext(mp) != 0) { |
| 690 | gnext(f) += cast_int(mp - f); /* correct 'next' */ |
| 691 | gnext(mp) = 0; /* now 'mp' is free */ |
| 692 | } |
| 693 | setempty(gval(mp)); |
| 694 | } |
| 695 | else { /* colliding node is in its own main position */ |
| 696 | /* new node will go into free position */ |
| 697 | if (gnext(mp) != 0) |
| 698 | gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ |
| 699 | else lua_assert(gnext(f) == 0); |
| 700 | gnext(mp) = cast_int(f - mp); |
| 701 | mp = f; |
| 702 | } |
| 703 | } |
| 704 | setnodekey(L, mp, key); |
| 705 | luaC_barrierback(L, obj2gco(t), key); |
| 706 | lua_assert(isempty(gval(mp))); |
| 707 | setobj2t(L, gval(mp), value); |
| 708 | } |
| 709 | |
| 710 | |
| 711 | /* |
no test coverage detected