style
[RRG-proxmark3.git] / client / deps / liblua / ltable.c
blob5bcb93b47fe71714dfb653ff6157c12c9eb486b6
1 /*
2 ** $Id: ltable.c,v 2.72 2012/09/11 19:37:16 roberto Exp $
3 ** Lua tables (hash)
4 ** See Copyright Notice in lua.h
5 */
8 /*
9 ** Implementation of tables (aka arrays, objects, or hash tables).
10 ** Tables keep its elements in two parts: an array part and a hash part.
11 ** Non-negative integer keys are all candidates to be kept in the array
12 ** part. The actual size of the array is the largest `n' such that at
13 ** least half the slots between 0 and n are in use.
14 ** Hash uses a mix of chained scatter table with Brent's variation.
15 ** A main invariant of these tables is that, if an element is not
16 ** in its main position (i.e. the `original' position that its hash gives
17 ** to it), then the colliding element is in its own main position.
18 ** Hence even when the load factor reaches 100%, performance remains good.
21 #include <string.h>
23 #define ltable_c
24 #define LUA_CORE
26 #include "lua.h"
28 #include "ldebug.h"
29 #include "ldo.h"
30 #include "lgc.h"
31 #include "lmem.h"
32 #include "lobject.h"
33 #include "lstate.h"
34 #include "lstring.h"
35 #include "ltable.h"
36 #include "lvm.h"
40 ** max size of array part is 2^MAXBITS
42 #if LUAI_BITSINT >= 32
43 #define MAXBITS 30
44 #else
45 #define MAXBITS (LUAI_BITSINT-2)
46 #endif
48 #define MAXASIZE (1 << MAXBITS)
51 #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
53 #define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
54 #define hashboolean(t,p) hashpow2(t, p)
58 ** for some types, it is better to avoid modulus by power of 2, as
59 ** they tend to have many 2 factors.
61 #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
64 #define hashpointer(t,p) hashmod(t, IntPoint(p))
67 #define dummynode (&dummynode_)
69 #define isdummy(n) ((n) == dummynode)
71 static const Node dummynode_ = {
72 {NILCONSTANT}, /* value */
73 {{NILCONSTANT, NULL}} /* key */
78 ** hash for lua_Numbers
80 static Node *hashnum(const Table *t, lua_Number n) {
81 int i;
82 luai_hashnum(i, n);
83 if (i < 0) {
84 if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
85 i = 0; /* handle INT_MIN */
86 i = -i; /* must be a positive value */
88 return hashmod(t, i);
94 ** returns the `main' position of an element in a table (that is, the index
95 ** of its hash value)
97 static Node *mainposition(const Table *t, const TValue *key) {
98 switch (ttype(key)) {
99 case LUA_TNUMBER:
100 return hashnum(t, nvalue(key));
101 case LUA_TLNGSTR: {
102 TString *s = rawtsvalue(key);
103 if (s->tsv.extra == 0) { /* no hash? */
104 s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash);
105 s->tsv.extra = 1; /* now it has its hash */
107 return hashstr(t, rawtsvalue(key));
109 case LUA_TSHRSTR:
110 return hashstr(t, rawtsvalue(key));
111 case LUA_TBOOLEAN:
112 return hashboolean(t, bvalue(key));
113 case LUA_TLIGHTUSERDATA:
114 return hashpointer(t, pvalue(key));
115 case LUA_TLCF:
116 return hashpointer(t, fvalue(key));
117 default:
118 return hashpointer(t, gcvalue(key));
124 ** returns the index for `key' if `key' is an appropriate key to live in
125 ** the array part of the table, -1 otherwise.
127 static int arrayindex(const TValue *key) {
128 if (ttisnumber(key)) {
129 lua_Number n = nvalue(key);
130 int k;
131 lua_number2int(k, n);
132 if (luai_numeq(cast_num(k), n))
133 return k;
135 return -1; /* `key' did not match some condition */
140 ** returns the index of a `key' for table traversals. First goes all
141 ** elements in the array part, then elements in the hash part. The
142 ** beginning of a traversal is signaled by -1.
144 static int findindex(lua_State *L, Table *t, StkId key) {
145 int i;
146 if (ttisnil(key)) return -1; /* first iteration */
147 i = arrayindex(key);
148 if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
149 return i - 1; /* yes; that's the index (corrected to C) */
150 else {
151 Node *n = mainposition(t, key);
152 for (;;) { /* check whether `key' is somewhere in the chain */
153 /* key may be dead already, but it is ok to use it in `next' */
154 if (luaV_rawequalobj(gkey(n), key) ||
155 (ttisdeadkey(gkey(n)) && iscollectable(key) &&
156 deadvalue(gkey(n)) == gcvalue(key))) {
157 i = cast_int(n - gnode(t, 0)); /* key index in hash table */
158 /* hash elements are numbered after array ones */
159 return i + t->sizearray;
160 } else n = gnext(n);
161 if (n == NULL)
162 luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
168 int luaH_next(lua_State *L, Table *t, StkId key) {
169 int i = findindex(L, t, key); /* find original element */
170 for (i++; i < t->sizearray; i++) { /* try first array part */
171 if (!ttisnil(&t->array[i])) { /* a non-nil value? */
172 setnvalue(key, cast_num(i + 1));
173 setobj2s(L, key + 1, &t->array[i]);
174 return 1;
177 for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
178 if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
179 setobj2s(L, key, gkey(gnode(t, i)));
180 setobj2s(L, key + 1, gval(gnode(t, i)));
181 return 1;
184 return 0; /* no more elements */
189 ** {=============================================================
190 ** Rehash
191 ** ==============================================================
195 static int computesizes(int nums[], int *narray) {
196 int i;
197 int twotoi; /* 2^i */
198 int a = 0; /* number of elements smaller than 2^i */
199 int na = 0; /* number of elements to go to array part */
200 int n = 0; /* optimal size for array part */
201 for (i = 0, twotoi = 1; twotoi / 2 < *narray; i++, twotoi *= 2) {
202 if (nums[i] > 0) {
203 a += nums[i];
204 if (a > twotoi / 2) { /* more than half elements present? */
205 n = twotoi; /* optimal size (till now) */
206 na = a; /* all elements smaller than n will go to array part */
209 if (a == *narray) break; /* all elements already counted */
211 *narray = n;
212 lua_assert(*narray / 2 <= na && na <= *narray);
213 return na;
217 static int countint(const TValue *key, int *nums) {
218 int k = arrayindex(key);
219 if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
220 nums[luaO_ceillog2(k)]++; /* count as such */
221 return 1;
222 } else
223 return 0;
227 static int numusearray(const Table *t, int *nums) {
228 int lg;
229 int ttlg; /* 2^lg */
230 int ause = 0; /* summation of `nums' */
231 int i = 1; /* count to traverse all array keys */
232 for (lg = 0, ttlg = 1; lg <= MAXBITS; lg++, ttlg *= 2) { /* for each slice */
233 int lc = 0; /* counter */
234 int lim = ttlg;
235 if (lim > t->sizearray) {
236 lim = t->sizearray; /* adjust upper limit */
237 if (i > lim)
238 break; /* no more elements to count */
240 /* count elements in range (2^(lg-1), 2^lg] */
241 for (; i <= lim; i++) {
242 if (!ttisnil(&t->array[i - 1]))
243 lc++;
245 nums[lg] += lc;
246 ause += lc;
248 return ause;
252 static int numusehash(const Table *t, int *nums, int *pnasize) {
253 int totaluse = 0; /* total number of elements */
254 int ause = 0; /* summation of `nums' */
255 int i = sizenode(t);
256 while (i--) {
257 Node *n = &t->node[i];
258 if (!ttisnil(gval(n))) {
259 ause += countint(gkey(n), nums);
260 totaluse++;
263 *pnasize += ause;
264 return totaluse;
268 static void setarrayvector(lua_State *L, Table *t, int size) {
269 int i;
270 luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
271 for (i = t->sizearray; i < size; i++)
272 setnilvalue(&t->array[i]);
273 t->sizearray = size;
277 static void setnodevector(lua_State *L, Table *t, int size) {
278 int lsize;
279 if (size == 0) { /* no elements to hash part? */
280 t->node = cast(Node *, dummynode); /* use common `dummynode' */
281 lsize = 0;
282 } else {
283 int i;
284 lsize = luaO_ceillog2(size);
285 if (lsize > MAXBITS)
286 luaG_runerror(L, "table overflow");
287 size = twoto(lsize);
288 t->node = luaM_newvector(L, size, Node);
289 for (i = 0; i < size; i++) {
290 Node *n = gnode(t, i);
291 gnext(n) = NULL;
292 setnilvalue(gkey(n));
293 setnilvalue(gval(n));
296 t->lsizenode = cast_byte(lsize);
297 t->lastfree = gnode(t, size); /* all positions are free */
301 void luaH_resize(lua_State *L, Table *t, int nasize, int nhsize) {
302 int i;
303 int oldasize = t->sizearray;
304 int oldhsize = t->lsizenode;
305 Node *nold = t->node; /* save old hash ... */
306 if (nasize > oldasize) /* array part must grow? */
307 setarrayvector(L, t, nasize);
308 /* create new hash part with appropriate size */
309 setnodevector(L, t, nhsize);
310 if (nasize < oldasize) { /* array part must shrink? */
311 t->sizearray = nasize;
312 /* re-insert elements from vanishing slice */
313 for (i = nasize; i < oldasize; i++) {
314 if (!ttisnil(&t->array[i]))
315 luaH_setint(L, t, i + 1, &t->array[i]);
317 /* shrink array */
318 luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
320 /* re-insert elements from hash part */
321 for (i = twoto(oldhsize) - 1; i >= 0; i--) {
322 Node *old = nold + i;
323 if (!ttisnil(gval(old))) {
324 /* doesn't need barrier/invalidate cache, as entry was
325 already present in the table */
326 setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old));
329 if (!isdummy(nold))
330 luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */
334 void luaH_resizearray(lua_State *L, Table *t, int nasize) {
335 int nsize = isdummy(t->node) ? 0 : sizenode(t);
336 luaH_resize(L, t, nasize, nsize);
340 static void rehash(lua_State *L, Table *t, const TValue *ek) {
341 int nasize, na;
342 int nums[MAXBITS + 1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */
343 int i;
344 int totaluse;
345 for (i = 0; i <= MAXBITS; i++) nums[i] = 0; /* reset counts */
346 nasize = numusearray(t, nums); /* count keys in array part */
347 totaluse = nasize; /* all those keys are integer keys */
348 totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
349 /* count extra key */
350 nasize += countint(ek, nums);
351 totaluse++;
352 /* compute new size for array part */
353 na = computesizes(nums, &nasize);
354 /* resize the table to new computed sizes */
355 luaH_resize(L, t, nasize, totaluse - na);
361 ** }=============================================================
365 Table *luaH_new(lua_State *L) {
366 Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h;
367 t->metatable = NULL;
368 t->flags = cast_byte(~0);
369 t->array = NULL;
370 t->sizearray = 0;
371 setnodevector(L, t, 0);
372 return t;
376 void luaH_free(lua_State *L, Table *t) {
377 if (!isdummy(t->node))
378 luaM_freearray(L, t->node, cast(size_t, sizenode(t)));
379 luaM_freearray(L, t->array, t->sizearray);
380 luaM_free(L, t);
384 static Node *getfreepos(Table *t) {
385 while (t->lastfree > t->node) {
386 t->lastfree--;
387 if (ttisnil(gkey(t->lastfree)))
388 return t->lastfree;
390 return NULL; /* could not find a free place */
396 ** inserts a new key into a hash table; first, check whether key's main
397 ** position is free. If not, check whether colliding node is in its main
398 ** position or not: if it is not, move colliding node to an empty place and
399 ** put new key in its main position; otherwise (colliding node is in its main
400 ** position), new key goes to an empty position.
402 TValue *luaH_newkey(lua_State *L, Table *t, const TValue *key) {
403 Node *mp;
404 if (ttisnil(key)) luaG_runerror(L, "table index is nil");
405 else if (ttisnumber(key) && luai_numisnan(L, nvalue(key)))
406 luaG_runerror(L, "table index is NaN");
407 mp = mainposition(t, key);
408 if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
409 Node *othern;
410 Node *n = getfreepos(t); /* get a free place */
411 if (n == NULL) { /* cannot find a free place? */
412 rehash(L, t, key); /* grow table */
413 /* whatever called 'newkey' take care of TM cache and GC barrier */
414 return luaH_set(L, t, key); /* insert key into grown table */
416 lua_assert(!isdummy(n));
417 othern = mainposition(t, gkey(mp));
418 if (othern != mp) { /* is colliding node out of its main position? */
419 /* yes; move colliding node into free position */
420 while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
421 gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
422 *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
423 gnext(mp) = NULL; /* now `mp' is free */
424 setnilvalue(gval(mp));
425 } else { /* colliding node is in its own main position */
426 /* new node will go into free position */
427 gnext(n) = gnext(mp); /* chain new position */
428 gnext(mp) = n;
429 mp = n;
432 setobj2t(L, gkey(mp), key);
433 luaC_barrierback(L, obj2gco(t), key);
434 lua_assert(ttisnil(gval(mp)));
435 return gval(mp);
440 ** search function for integers
442 const TValue *luaH_getint(Table *t, int key) {
443 /* (1 <= key && key <= t->sizearray) */
444 if (cast(unsigned int, key - 1) < cast(unsigned int, t->sizearray))
445 return &t->array[key - 1];
446 else {
447 lua_Number nk = cast_num(key);
448 Node *n = hashnum(t, nk);
449 do { /* check whether `key' is somewhere in the chain */
450 if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
451 return gval(n); /* that's it */
452 else n = gnext(n);
453 } while (n);
454 return luaO_nilobject;
460 ** search function for short strings
462 const TValue *luaH_getstr(Table *t, TString *key) {
463 Node *n = hashstr(t, key);
464 lua_assert(key->tsv.tt == LUA_TSHRSTR);
465 do { /* check whether `key' is somewhere in the chain */
466 if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key))
467 return gval(n); /* that's it */
468 else n = gnext(n);
469 } while (n);
470 return luaO_nilobject;
475 ** main search function
477 const TValue *luaH_get(Table *t, const TValue *key) {
478 switch (ttype(key)) {
479 case LUA_TSHRSTR:
480 return luaH_getstr(t, rawtsvalue(key));
481 case LUA_TNIL:
482 return luaO_nilobject;
483 case LUA_TNUMBER: {
484 int k;
485 lua_Number n = nvalue(key);
486 lua_number2int(k, n);
487 if (luai_numeq(cast_num(k), n)) /* index is int? */
488 return luaH_getint(t, k); /* use specialized version */
489 /* else go through */
491 default: {
492 Node *n = mainposition(t, key);
493 do { /* check whether `key' is somewhere in the chain */
494 if (luaV_rawequalobj(gkey(n), key))
495 return gval(n); /* that's it */
496 else n = gnext(n);
497 } while (n);
498 return luaO_nilobject;
505 ** beware: when using this function you probably need to check a GC
506 ** barrier and invalidate the TM cache.
508 TValue *luaH_set(lua_State *L, Table *t, const TValue *key) {
509 const TValue *p = luaH_get(t, key);
510 if (p != luaO_nilobject)
511 return cast(TValue *, p);
512 else return luaH_newkey(L, t, key);
516 void luaH_setint(lua_State *L, Table *t, int key, TValue *value) {
517 const TValue *p = luaH_getint(t, key);
518 TValue *cell;
519 if (p != luaO_nilobject)
520 cell = cast(TValue *, p);
521 else {
522 TValue k;
523 setnvalue(&k, cast_num(key));
524 cell = luaH_newkey(L, t, &k);
526 setobj2t(L, cell, value);
530 static int unbound_search(Table *t, unsigned int j) {
531 unsigned int i = j; /* i is zero or a present index */
532 j++;
533 /* find `i' and `j' such that i is present and j is not */
534 while (!ttisnil(luaH_getint(t, j))) {
535 i = j;
536 j *= 2;
537 if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
538 /* table was built with bad purposes: resort to linear search */
539 i = 1;
540 while (!ttisnil(luaH_getint(t, i))) i++;
541 return i - 1;
544 /* now do a binary search between them */
545 while (j - i > 1) {
546 unsigned int m = (i + j) / 2;
547 if (ttisnil(luaH_getint(t, m))) j = m;
548 else i = m;
550 return i;
555 ** Try to find a boundary in table `t'. A `boundary' is an integer index
556 ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
558 int luaH_getn(Table *t) {
559 unsigned int j = t->sizearray;
560 if (j > 0 && ttisnil(&t->array[j - 1])) {
561 /* there is a boundary in the array part: (binary) search for it */
562 unsigned int i = 0;
563 while (j - i > 1) {
564 unsigned int m = (i + j) / 2;
565 if (ttisnil(&t->array[m - 1])) j = m;
566 else i = m;
568 return i;
570 /* else must find a boundary in hash part */
571 else if (isdummy(t->node)) /* hash part is empty? */
572 return j; /* that is easy... */
573 else return unbound_search(t, j);
578 #if defined(LUA_DEBUG)
580 Node *luaH_mainposition(const Table *t, const TValue *key) {
581 return mainposition(t, key);
584 int luaH_isdummy(Node *n) { return isdummy(n); }
586 #endif