static Tvalue *table_newkey(ktap_State *ks, Table *t, const Tvalue *key) { Node *mp; mp = mainposition(t, key); if (!isnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; Node *n = getfreepos(t); /* get a free place */ if (n == NULL) { /* cannot find a free place? */ rehash(ks, t, key); /* grow table */ /* whatever called 'newkey' take care of TM cache and GC barrier */ return kp_table_set(ks, t, key); /* insert key into grown table */ } othern = mainposition(t, gkey(mp)); if (othern != mp) { /* is colliding node out of its main position? */ /* yes; move colliding node into free position */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ gnext(mp) = NULL; /* now `mp' is free */ setnilvalue(gval(mp)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ gnext(n) = gnext(mp); /* chain new position */ gnext(mp) = n; mp = n; } } setobj(ks, gkey(mp), key); return gval(mp); }
static int ktap_lib_count(ktap_State *ks) { Table *tbl = hvalue(GetArg(ks, 1)); Tvalue *k = GetArg(ks, 2); int n; Tvalue *v; if (GetArgN(ks) > 2) n = nvalue(GetArg(ks, 3)); else n = 1; v = kp_table_set(ks, tbl, k); if (unlikely(isnil(v))) { setnvalue(v, 1); } else setnvalue(v, nvalue(v) + n); return 0; }
void kp_table_resize(ktap_State *ks, Table *t, int nasize, int nhsize) { int i; int oldasize = t->sizearray; int oldhsize = t->lsizenode; Node *nold = t->node; /* save old hash ... */ if (nasize > oldasize) /* array part must grow? */ setarrayvector(ks, t, nasize); /* create new hash part with appropriate size */ setnodevector(ks, t, nhsize); if (nasize < oldasize) { /* array part must shrink? */ t->sizearray = nasize; /* re-insert elements from vanishing slice */ for (i=nasize; i<oldasize; i++) { if (!ttisnil(&t->array[i])) kp_table_setint(ks, t, i + 1, &t->array[i]); } /* shrink array */ kp_realloc(ks, t->array, oldasize, nasize, Tvalue); } /* re-insert elements from hash part */ for (i = twoto(oldhsize) - 1; i >= 0; i--) { Node *old = nold+i; if (!ttisnil(gval(old))) { /* doesn't need barrier/invalidate cache, as entry was * already present in the table */ setobj(ks, kp_table_set(ks, t, gkey(old)), gval(old)); } } if (!isdummy(nold)) kp_free(ks, nold); /* free old array */ }
void kp_table_setvalue(ktap_State *ks, Table *t, const Tvalue *key, Tvalue *val) { setobj(ks, kp_table_set(ks, t, key), val); }