** 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. */
| 459 | ** position), new key goes to an empty position. |
| 460 | */ |
| 461 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { |
| 462 | Node *mp; |
| 463 | TValue aux; |
| 464 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
| 465 | else if (ttisfloat(key)) { |
| 466 | lua_Integer k; |
| 467 | if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */ |
| 468 | setivalue(&aux, k); |
| 469 | key = &aux; /* insert it as an integer */ |
| 470 | } |
| 471 | else if (luai_numisnan(fltvalue(key))) |
| 472 | luaG_runerror(L, "table index is NaN"); |
| 473 | } |
| 474 | mp = mainposition(t, key); |
| 475 | if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
| 476 | Node *othern; |
| 477 | Node *f = getfreepos(t); /* get a free place */ |
| 478 | if (f == NULL) { /* cannot find a free place? */ |
| 479 | rehash(L, t, key); /* grow table */ |
| 480 | /* whatever called 'newkey' takes care of TM cache */ |
| 481 | return luaH_set(L, t, key); /* insert key into grown table */ |
| 482 | } |
| 483 | lua_assert(!isdummy(t)); |
| 484 | othern = mainposition(t, gkey(mp)); |
| 485 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 486 | /* yes; move colliding node into free position */ |
| 487 | while (othern + gnext(othern) != mp) /* find previous */ |
| 488 | othern += gnext(othern); |
| 489 | gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ |
| 490 | *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ |
| 491 | if (gnext(mp) != 0) { |
| 492 | gnext(f) += cast_int(mp - f); /* correct 'next' */ |
| 493 | gnext(mp) = 0; /* now 'mp' is free */ |
| 494 | } |
| 495 | setnilvalue(gval(mp)); |
| 496 | } |
| 497 | else { /* colliding node is in its own main position */ |
| 498 | /* new node will go into free position */ |
| 499 | if (gnext(mp) != 0) |
| 500 | gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ |
| 501 | else lua_assert(gnext(f) == 0); |
| 502 | gnext(mp) = cast_int(f - mp); |
| 503 | mp = f; |
| 504 | } |
| 505 | } |
| 506 | setnodekey(L, &mp->i_key, key); |
| 507 | luaC_barrierback(L, t, key); |
| 508 | lua_assert(ttisnil(gval(mp))); |
| 509 | return gval(mp); |
| 510 | } |
| 511 | |
| 512 | |
| 513 | /* |
no test coverage detected