|
|
|
@ -59,8 +59,8 @@
|
|
|
|
|
#define dummynode (&dummynode_)
|
|
|
|
|
|
|
|
|
|
static const Node dummynode_ = {
|
|
|
|
|
{NILCONSTANT}, /* value */
|
|
|
|
|
{{NILCONSTANT, 0}} /* key */
|
|
|
|
|
{{NULL}, LUA_TNIL, /* value's value and type */
|
|
|
|
|
LUA_TNIL, 0, {NULL}} /* key type, next, and key value */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -95,43 +95,98 @@ static int l_hashfloat (lua_Number n) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** returns the 'main' position of an element in a table (that is, the index
|
|
|
|
|
** of its hash value)
|
|
|
|
|
** returns the 'main' position of an element in a table (that is,
|
|
|
|
|
** the index of its hash value). The key comes broken (tag in 'ktt'
|
|
|
|
|
** and value in 'vkl') so that we can call it on keys inserted into
|
|
|
|
|
** nodes.
|
|
|
|
|
*/
|
|
|
|
|
static Node *mainposition (const Table *t, const TValue *key) {
|
|
|
|
|
switch (ttype(key)) {
|
|
|
|
|
static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
|
|
|
|
|
switch (ttyperaw(ktt)) {
|
|
|
|
|
case LUA_TNUMINT:
|
|
|
|
|
return hashint(t, ivalue(key));
|
|
|
|
|
return hashint(t, ivalueraw(*kvl));
|
|
|
|
|
case LUA_TNUMFLT:
|
|
|
|
|
return hashmod(t, l_hashfloat(fltvalue(key)));
|
|
|
|
|
return hashmod(t, l_hashfloat(fltvalueraw(*kvl)));
|
|
|
|
|
case LUA_TSHRSTR:
|
|
|
|
|
return hashstr(t, tsvalue(key));
|
|
|
|
|
return hashstr(t, tsvalueraw(*kvl));
|
|
|
|
|
case LUA_TLNGSTR:
|
|
|
|
|
return hashpow2(t, luaS_hashlongstr(tsvalue(key)));
|
|
|
|
|
return hashpow2(t, luaS_hashlongstr(tsvalueraw(*kvl)));
|
|
|
|
|
case LUA_TBOOLEAN:
|
|
|
|
|
return hashboolean(t, bvalue(key));
|
|
|
|
|
return hashboolean(t, bvalueraw(*kvl));
|
|
|
|
|
case LUA_TLIGHTUSERDATA:
|
|
|
|
|
return hashpointer(t, pvalue(key));
|
|
|
|
|
return hashpointer(t, pvalueraw(*kvl));
|
|
|
|
|
case LUA_TLCF:
|
|
|
|
|
return hashpointer(t, fvalue(key));
|
|
|
|
|
return hashpointer(t, fvalueraw(*kvl));
|
|
|
|
|
default:
|
|
|
|
|
lua_assert(!ttisdeadkey(key));
|
|
|
|
|
return hashpointer(t, gcvalue(key));
|
|
|
|
|
return hashpointer(t, gcvalueraw(*kvl));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Node *mainpositionTV (const Table *t, const TValue *key) {
|
|
|
|
|
return mainposition(t, rttype(key), valraw(key));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** returns the index for 'key' if 'key' is an appropriate key to live in
|
|
|
|
|
** the array part of the table, 0 otherwise.
|
|
|
|
|
** Check whether key 'k1' is equal to the key in node 'n2'.
|
|
|
|
|
** This equality is raw, so there are no metamethods. Floats
|
|
|
|
|
** with integer values have been normalized, so integers cannot
|
|
|
|
|
** be equal to floats. It is assumed that 'eqshrstr' is simply
|
|
|
|
|
** pointer equality, so that short strings are handled in the
|
|
|
|
|
** default case.
|
|
|
|
|
*/
|
|
|
|
|
static unsigned int arrayindex (const TValue *key) {
|
|
|
|
|
if (ttisinteger(key)) {
|
|
|
|
|
lua_Integer k = ivalue(key);
|
|
|
|
|
if (0 < k && (lua_Unsigned)k <= MAXASIZE)
|
|
|
|
|
return cast(unsigned int, k); /* 'key' is an appropriate array index */
|
|
|
|
|
static int equalkey (const TValue *k1, const Node *n2) {
|
|
|
|
|
if (rttype(k1) != keytt(n2)) /* not the same variants? */
|
|
|
|
|
return 0; /* cannot be same key */
|
|
|
|
|
switch (ttype(k1)) {
|
|
|
|
|
case LUA_TNIL:
|
|
|
|
|
return 1;
|
|
|
|
|
case LUA_TNUMINT:
|
|
|
|
|
return (ivalue(k1) == keyival(n2));
|
|
|
|
|
case LUA_TNUMFLT:
|
|
|
|
|
return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2)));
|
|
|
|
|
case LUA_TBOOLEAN:
|
|
|
|
|
return bvalue(k1) == bvalueraw(keyval(n2));
|
|
|
|
|
case LUA_TLIGHTUSERDATA:
|
|
|
|
|
return pvalue(k1) == pvalueraw(keyval(n2));
|
|
|
|
|
case LUA_TLCF:
|
|
|
|
|
return fvalue(k1) == fvalueraw(keyval(n2));
|
|
|
|
|
case LUA_TLNGSTR:
|
|
|
|
|
return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
|
|
|
|
|
default:
|
|
|
|
|
return gcvalue(k1) == gcvalueraw(keyval(n2));
|
|
|
|
|
}
|
|
|
|
|
return 0; /* 'key' did not match some condition */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** "Generic" get version. (Not that generic: not valid for integers,
|
|
|
|
|
** which may be in array part, nor for floats with integral values.)
|
|
|
|
|
*/
|
|
|
|
|
static const TValue *getgeneric (Table *t, const TValue *key) {
|
|
|
|
|
Node *n = mainpositionTV(t, key);
|
|
|
|
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
|
|
|
|
if (equalkey(key, n))
|
|
|
|
|
return gval(n); /* that's it */
|
|
|
|
|
else {
|
|
|
|
|
int nx = gnext(n);
|
|
|
|
|
if (nx == 0)
|
|
|
|
|
return luaO_nilobject; /* not found */
|
|
|
|
|
n += nx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** returns the index for 'k' if 'k' is an appropriate key to live in
|
|
|
|
|
** the array part of a table, 0 otherwise.
|
|
|
|
|
*/
|
|
|
|
|
static unsigned int arrayindex (lua_Integer k) {
|
|
|
|
|
if (0 < k && l_castS2U(k) <= MAXASIZE)
|
|
|
|
|
return cast(unsigned int, k); /* 'key' is an appropriate array index */
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -140,29 +195,19 @@ static unsigned int arrayindex (const TValue *key) {
|
|
|
|
|
** elements in the array part, then elements in the hash part. The
|
|
|
|
|
** beginning of a traversal is signaled by 0.
|
|
|
|
|
*/
|
|
|
|
|
static unsigned int findindex (lua_State *L, Table *t, StkId key) {
|
|
|
|
|
static unsigned int findindex (lua_State *L, Table *t, TValue *key) {
|
|
|
|
|
unsigned int i;
|
|
|
|
|
if (ttisnil(key)) return 0; /* first iteration */
|
|
|
|
|
i = arrayindex(key);
|
|
|
|
|
i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
|
|
|
|
|
if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */
|
|
|
|
|
return i; /* yes; that's the index */
|
|
|
|
|
else {
|
|
|
|
|
int nx;
|
|
|
|
|
Node *n = mainposition(t, key);
|
|
|
|
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
|
|
|
|
/* key may be dead already, but it is ok to use it in 'next' */
|
|
|
|
|
if (luaV_rawequalobj(gkey(n), key) ||
|
|
|
|
|
(ttisdeadkey(gkey(n)) && iscollectable(key) &&
|
|
|
|
|
deadvalue(gkey(n)) == gcvalue(key))) {
|
|
|
|
|
i = cast_int(n - gnode(t, 0)); /* key index in hash table */
|
|
|
|
|
/* hash elements are numbered after array ones */
|
|
|
|
|
return (i + 1) + t->sizearray;
|
|
|
|
|
}
|
|
|
|
|
nx = gnext(n);
|
|
|
|
|
if (nx == 0)
|
|
|
|
|
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
|
|
|
|
|
else n += nx;
|
|
|
|
|
}
|
|
|
|
|
const TValue *n = getgeneric(t, key);
|
|
|
|
|
if (n == luaO_nilobject)
|
|
|
|
|
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
|
|
|
|
|
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
|
|
|
|
|
/* hash elements are numbered after array ones */
|
|
|
|
|
return (i + 1) + t->sizearray;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -212,8 +257,9 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
|
|
|
|
|
}
|
|
|
|
|
for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */
|
|
|
|
|
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
|
|
|
|
|
setobj2s(L, key, gkey(gnode(t, i)));
|
|
|
|
|
setobj2s(L, key + 1, gval(gnode(t, i)));
|
|
|
|
|
Node *n = gnode(t, i);
|
|
|
|
|
getnodekey(L, key, n);
|
|
|
|
|
setobj2s(L, key + 1, gval(n));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -232,7 +278,8 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
|
|
|
|
|
** "count array" where 'nums[i]' is the number of integers in the table
|
|
|
|
|
** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of
|
|
|
|
|
** integer keys in the table and leaves with the number of keys that
|
|
|
|
|
** will go to the array part; return the optimal size.
|
|
|
|
|
** will go to the array part; return the optimal size. (The condition
|
|
|
|
|
** 'twotoi > 0' in the for loop stops the loop if 'twotoi' overflows.)
|
|
|
|
|
*/
|
|
|
|
|
static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
|
|
|
|
|
int i;
|
|
|
|
@ -241,13 +288,13 @@ static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
|
|
|
|
|
unsigned int na = 0; /* number of elements to go to array part */
|
|
|
|
|
unsigned int optimal = 0; /* optimal size for array part */
|
|
|
|
|
/* loop while keys can fill more than half of total size */
|
|
|
|
|
for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) {
|
|
|
|
|
if (nums[i] > 0) {
|
|
|
|
|
a += nums[i];
|
|
|
|
|
if (a > twotoi/2) { /* more than half elements present? */
|
|
|
|
|
optimal = twotoi; /* optimal size (till now) */
|
|
|
|
|
na = a; /* all elements up to 'optimal' will go to array part */
|
|
|
|
|
}
|
|
|
|
|
for (i = 0, twotoi = 1;
|
|
|
|
|
twotoi > 0 && *pna > twotoi / 2;
|
|
|
|
|
i++, twotoi *= 2) {
|
|
|
|
|
a += nums[i];
|
|
|
|
|
if (a > twotoi/2) { /* more than half elements present? */
|
|
|
|
|
optimal = twotoi; /* optimal size (till now) */
|
|
|
|
|
na = a; /* all elements up to 'optimal' will go to array part */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal);
|
|
|
|
@ -256,7 +303,7 @@ static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int countint (const TValue *key, unsigned int *nums) {
|
|
|
|
|
static int countint (lua_Integer key, unsigned int *nums) {
|
|
|
|
|
unsigned int k = arrayindex(key);
|
|
|
|
|
if (k != 0) { /* is 'key' an appropriate array index? */
|
|
|
|
|
nums[luaO_ceillog2(k)]++; /* count as such */
|
|
|
|
@ -305,7 +352,8 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
|
|
|
|
|
while (i--) {
|
|
|
|
|
Node *n = &t->node[i];
|
|
|
|
|
if (!ttisnil(gval(n))) {
|
|
|
|
|
ause += countint(gkey(n), nums);
|
|
|
|
|
if (keyisinteger(n))
|
|
|
|
|
ause += countint(keyival(n), nums);
|
|
|
|
|
totaluse++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -342,7 +390,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
|
|
|
|
|
for (i = 0; i < (int)size; i++) {
|
|
|
|
|
Node *n = gnode(t, i);
|
|
|
|
|
gnext(n) = 0;
|
|
|
|
|
setnilvalue(wgkey(n));
|
|
|
|
|
setnilkey(n);
|
|
|
|
|
setnilvalue(gval(n));
|
|
|
|
|
}
|
|
|
|
|
t->lsizenode = cast_byte(lsize);
|
|
|
|
@ -381,7 +429,8 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
|
|
|
|
if (!ttisnil(gval(old))) {
|
|
|
|
|
/* doesn't need barrier/invalidate cache, as entry was
|
|
|
|
|
already present in the table */
|
|
|
|
|
setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old));
|
|
|
|
|
TValue k; getnodekey(L, &k, old);
|
|
|
|
|
setobjt2t(L, luaH_set(L, t, &k), gval(old));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (oldhsize > 0) /* not the dummy node? */
|
|
|
|
@ -408,7 +457,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
|
|
|
|
|
totaluse = na; /* all those keys are integer keys */
|
|
|
|
|
totaluse += numusehash(t, nums, &na); /* count keys in hash part */
|
|
|
|
|
/* count extra key */
|
|
|
|
|
na += countint(ek, nums);
|
|
|
|
|
if (ttisinteger(ek))
|
|
|
|
|
na += countint(ivalue(ek), nums);
|
|
|
|
|
totaluse++;
|
|
|
|
|
/* compute new size for array part */
|
|
|
|
|
asize = computesizes(nums, &na);
|
|
|
|
@ -487,7 +537,7 @@ static Node *getfreepos (Table *t) {
|
|
|
|
|
if (!isdummy(t)) {
|
|
|
|
|
while (t->lastfree > t->node) {
|
|
|
|
|
t->lastfree--;
|
|
|
|
|
if (ttisnil(gkey(t->lastfree)))
|
|
|
|
|
if (keyisnil(t->lastfree))
|
|
|
|
|
return t->lastfree;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -516,7 +566,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|
|
|
|
else if (luai_numisnan(fltvalue(key)))
|
|
|
|
|
luaG_runerror(L, "table index is NaN");
|
|
|
|
|
}
|
|
|
|
|
mp = mainposition(t, key);
|
|
|
|
|
mp = mainpositionTV(t, key);
|
|
|
|
|
if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */
|
|
|
|
|
Node *othern;
|
|
|
|
|
Node *f = getfreepos(t); /* get a free place */
|
|
|
|
@ -526,7 +576,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|
|
|
|
return luaH_set(L, t, key); /* insert key into grown table */
|
|
|
|
|
}
|
|
|
|
|
lua_assert(!isdummy(t));
|
|
|
|
|
othern = mainposition(t, gkey(mp));
|
|
|
|
|
othern = mainposition(t, keytt(mp), &keyval(mp));
|
|
|
|
|
if (othern != mp) { /* is colliding node out of its main position? */
|
|
|
|
|
/* yes; move colliding node into free position */
|
|
|
|
|
while (othern + gnext(othern) != mp) /* find previous */
|
|
|
|
@ -548,7 +598,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|
|
|
|
mp = f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
setnodekey(L, &mp->i_key, key);
|
|
|
|
|
setnodekey(L, mp, key);
|
|
|
|
|
luaC_barrierback(L, t, key);
|
|
|
|
|
lua_assert(ttisnil(gval(mp)));
|
|
|
|
|
return gval(mp);
|
|
|
|
@ -560,12 +610,12 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
|
|
|
|
*/
|
|
|
|
|
const TValue *luaH_getint (Table *t, lua_Integer key) {
|
|
|
|
|
/* (1 <= key && key <= t->sizearray) */
|
|
|
|
|
if (l_castS2U(key) - 1 < t->sizearray)
|
|
|
|
|
if (l_castS2U(key) - 1u < t->sizearray)
|
|
|
|
|
return &t->array[key - 1];
|
|
|
|
|
else {
|
|
|
|
|
Node *n = hashint(t, key);
|
|
|
|
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
|
|
|
|
if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
|
|
|
|
|
if (keyisinteger(n) && keyival(n) == key)
|
|
|
|
|
return gval(n); /* that's it */
|
|
|
|
|
else {
|
|
|
|
|
int nx = gnext(n);
|
|
|
|
@ -577,7 +627,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if !defined(RAVI_ENABLED)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** search function for short strings
|
|
|
|
|
*/
|
|
|
|
@ -585,27 +635,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
|
|
|
|
|
Node *n = hashstr(t, key);
|
|
|
|
|
lua_assert(key->tt == LUA_TSHRSTR);
|
|
|
|
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
|
|
|
|
const TValue *k = gkey(n);
|
|
|
|
|
if (ttisshrstring(k) && eqshrstr(tsvalue(k), key))
|
|
|
|
|
return gval(n); /* that's it */
|
|
|
|
|
else {
|
|
|
|
|
int nx = gnext(n);
|
|
|
|
|
if (nx == 0)
|
|
|
|
|
return luaO_nilobject; /* not found */
|
|
|
|
|
n += nx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** "Generic" get version. (Not that generic: not valid for integers,
|
|
|
|
|
** which may be in array part, nor for floats with integral values.)
|
|
|
|
|
*/
|
|
|
|
|
static const TValue *getgeneric (Table *t, const TValue *key) {
|
|
|
|
|
Node *n = mainposition(t, key);
|
|
|
|
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
|
|
|
|
if (luaV_rawequalobj(gkey(n), key))
|
|
|
|
|
if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
|
|
|
|
|
return gval(n); /* that's it */
|
|
|
|
|
else {
|
|
|
|
|
int nx = gnext(n);
|
|
|
|
@ -631,8 +661,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
|
|
|
|
|
/*
|
|
|
|
|
** main search function
|
|
|
|
|
*/
|
|
|
|
|
const TValue *luaH_get(Table *t, const TValue *key) {
|
|
|
|
|
#if 1
|
|
|
|
|
const TValue *luaH_get (Table *t, const TValue *key) {
|
|
|
|
|
switch (ttype(key)) {
|
|
|
|
|
case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
|
|
|
|
|
case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
|
|
|
|
@ -646,27 +675,9 @@ const TValue *luaH_get(Table *t, const TValue *key) {
|
|
|
|
|
default:
|
|
|
|
|
return getgeneric(t, key);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
int tt = ttype(key);
|
|
|
|
|
if (RAVI_LIKELY(tt == LUA_TNUMINT))
|
|
|
|
|
return luaH_getint(t, ivalue(key));
|
|
|
|
|
else if (tt == LUA_TSHRSTR)
|
|
|
|
|
return luaH_getshortstr(t, tsvalue(key));
|
|
|
|
|
else if (tt == LUA_TNIL)
|
|
|
|
|
return luaO_nilobject;
|
|
|
|
|
else if (tt == LUA_TNUMFLT) {
|
|
|
|
|
lua_Integer k;
|
|
|
|
|
if (luaV_tointeger(key, &k, 0)) /* index is int? */
|
|
|
|
|
return luaH_getint(t, k); /* use specialized version */
|
|
|
|
|
/* else... */
|
|
|
|
|
return getgeneric(t, key);
|
|
|
|
|
} /* FALLTHROUGH */
|
|
|
|
|
else {
|
|
|
|
|
return getgeneric(t, key);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** beware: when using this function you probably need to check a GC
|
|
|
|
|
** barrier and invalidate the TM cache.
|
|
|
|
@ -693,23 +704,37 @@ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int unbound_search (Table *t, unsigned int j) {
|
|
|
|
|
unsigned int i = j; /* i is zero or a present index */
|
|
|
|
|
j++;
|
|
|
|
|
/* find 'i' and 'j' such that i is present and j is not */
|
|
|
|
|
while (!ttisnil(luaH_getint(t, j))) {
|
|
|
|
|
i = j;
|
|
|
|
|
if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */
|
|
|
|
|
/* table was built with bad purposes: resort to linear search */
|
|
|
|
|
i = 1;
|
|
|
|
|
while (!ttisnil(luaH_getint(t, i))) i++;
|
|
|
|
|
return i - 1;
|
|
|
|
|
/*
|
|
|
|
|
** Try to find a boundary in the hash part of table 't'. From the
|
|
|
|
|
** caller, we know that 'j' is zero or present and that 'j + 1' is
|
|
|
|
|
** present. We want to find a larger key that is absent from the
|
|
|
|
|
** table, so that we can do a binary search between the two keys to
|
|
|
|
|
** find a boundary. We keep doubling 'j' until we get an absent index.
|
|
|
|
|
** If the doubling would overflow, we try LUA_MAXINTEGER. If it is
|
|
|
|
|
** absent, we are ready for the binary search. ('j', being max integer,
|
|
|
|
|
** is larger or equal to 'i', but it cannot be equal because it is
|
|
|
|
|
** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a
|
|
|
|
|
** boundary. ('j + 1' cannot be a present integer key because it is
|
|
|
|
|
** not a valid integer in Lua.)
|
|
|
|
|
*/
|
|
|
|
|
static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
|
|
|
|
|
lua_Unsigned i;
|
|
|
|
|
if (j == 0) j++; /* the caller ensures 'j + 1' is present */
|
|
|
|
|
do {
|
|
|
|
|
i = j; /* 'i' is a present index */
|
|
|
|
|
if (j <= l_castS2U(LUA_MAXINTEGER) / 2)
|
|
|
|
|
j *= 2;
|
|
|
|
|
else {
|
|
|
|
|
j = LUA_MAXINTEGER;
|
|
|
|
|
if (ttisnil(luaH_getint(t, j))) /* t[j] == nil? */
|
|
|
|
|
break; /* 'j' now is an absent index */
|
|
|
|
|
else /* weird case */
|
|
|
|
|
return j; /* well, max integer is a boundary... */
|
|
|
|
|
}
|
|
|
|
|
j *= 2;
|
|
|
|
|
}
|
|
|
|
|
/* now do a binary search between them */
|
|
|
|
|
while (j - i > 1) {
|
|
|
|
|
unsigned int m = (i+j)/2;
|
|
|
|
|
} while (!ttisnil(luaH_getint(t, j))); /* repeat until t[j] == nil */
|
|
|
|
|
/* i < j && t[i] !? nil && t[j] == nil */
|
|
|
|
|
while (j - i > 1u) { /* do a binary search between them */
|
|
|
|
|
lua_Unsigned m = (i + j) / 2;
|
|
|
|
|
if (ttisnil(luaH_getint(t, m))) j = m;
|
|
|
|
|
else i = m;
|
|
|
|
|
}
|
|
|
|
@ -718,32 +743,32 @@ static int unbound_search (Table *t, unsigned int j) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
** Try to find a boundary in table 't'. A 'boundary' is an integer index
|
|
|
|
|
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
|
|
|
|
|
** Try to find a boundary in table 't'. (A 'boundary' is an integer index
|
|
|
|
|
** such that t[i] is non-nil and t[i+1] is nil, plus 0 if t[1] is nil
|
|
|
|
|
** and 'maxinteger' if t[maxinteger] is not nil.)
|
|
|
|
|
** First, try the array part: if there is an array part and its last
|
|
|
|
|
** element is nil, there must be a boundary there; a binary search
|
|
|
|
|
** finds that boundary. Otherwise, if the hash part is empty or does not
|
|
|
|
|
** contain 'j + 1', 'j' is a boundary. Othersize, call 'hash_search'
|
|
|
|
|
** to find a boundary in the hash part.
|
|
|
|
|
*/
|
|
|
|
|
int luaH_getn (Table *t) {
|
|
|
|
|
unsigned int j;
|
|
|
|
|
/* if this is a RAVI array then use specialized function */
|
|
|
|
|
if (t->ravi_array.array_type != RAVI_TTABLE) {
|
|
|
|
|
lua_assert(t->ravi_array.array_type == RAVI_TARRAYFLT ||
|
|
|
|
|
t->ravi_array.array_type == RAVI_TARRAYINT);
|
|
|
|
|
return t->ravi_array.len;
|
|
|
|
|
}
|
|
|
|
|
j = t->sizearray;
|
|
|
|
|
lua_Unsigned luaH_getn (Table *t) {
|
|
|
|
|
unsigned int j = t->sizearray;
|
|
|
|
|
if (j > 0 && ttisnil(&t->array[j - 1])) {
|
|
|
|
|
/* there is a boundary in the array part: (binary) search for it */
|
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
while (j - i > 1) {
|
|
|
|
|
unsigned int m = (i+j)/2;
|
|
|
|
|
while (j - i > 1u) { /* binary search */
|
|
|
|
|
unsigned int m = (i + j) / 2;
|
|
|
|
|
if (ttisnil(&t->array[m - 1])) j = m;
|
|
|
|
|
else i = m;
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
/* else must find a boundary in hash part */
|
|
|
|
|
else if (isdummy(t)) /* hash part is empty? */
|
|
|
|
|
return j; /* that is easy... */
|
|
|
|
|
else return unbound_search(t, j);
|
|
|
|
|
else { /* 'j' is zero or present in table */
|
|
|
|
|
if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1))))
|
|
|
|
|
return j; /* 'j + 1' is absent... */
|
|
|
|
|
else /* 'j + 1' is also present */
|
|
|
|
|
return hash_search(t, j);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* RAVI array specialization */
|
|
|
|
@ -935,7 +960,7 @@ const TValue *raviH_slice_parent(lua_State *L, TValue *slice) {
|
|
|
|
|
#if defined(LUA_DEBUG)
|
|
|
|
|
|
|
|
|
|
Node *luaH_mainposition (const Table *t, const TValue *key) {
|
|
|
|
|
return mainposition(t, key);
|
|
|
|
|
return mainpositionTV(t, key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int luaH_isdummy (const Table *t) { return isdummy(t); }
|
|
|
|
|