ltable.c
上传用户:jxpjxmjjw
上传日期:2009-12-07
资源大小:5877k
文件大小:14k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. /*
  2. ** $Id: ltable.c,v 1.1 2004/08/20 02:26:56 JH Exp $
  3. ** Lua tables (hash)
  4. ** See Copyright Notice in lua.h
  5. */
  6. /*
  7. ** Implementation of tables (aka arrays, objects, or hash tables).
  8. ** Tables keep its elements in two parts: an array part and a hash part.
  9. ** Non-negative integer keys are all candidates to be kept in the array
  10. ** part. The actual size of the array is the largest `n' such that at
  11. ** least half the slots between 0 and n are in use.
  12. ** Hash uses a mix of chained scatter table with Brent's variation.
  13. ** A main invariant of these tables is that, if an element is not
  14. ** in its main position (i.e. the `original' position that its hash gives
  15. ** to it), then the colliding element is in its own main position.
  16. ** In other words, there are collisions only when two elements have the
  17. ** same main position (i.e. the same hash values for that table size).
  18. ** Because of that, the load factor of these tables can be 100% without
  19. ** performance penalties.
  20. */
  21. #include <string.h>
  22. #define ltable_c
  23. #include "lua.h"
  24. #include "ldebug.h"
  25. #include "ldo.h"
  26. #include "lgc.h"
  27. #include "lmem.h"
  28. #include "lobject.h"
  29. #include "lstate.h"
  30. #include "ltable.h"
  31. /*
  32. ** max size of array part is 2^MAXBITS
  33. */
  34. #if BITS_INT > 26
  35. #define MAXBITS 24
  36. #else
  37. #define MAXBITS (BITS_INT-2)
  38. #endif
  39. /* check whether `x' < 2^MAXBITS */
  40. #define toobig(x) ((((x)-1) >> MAXBITS) != 0)
  41. /* function to convert a lua_Number to int (with any rounding method) */
  42. #ifndef lua_number2int
  43. #define lua_number2int(i,n) ((i)=(int)(n))
  44. #endif
  45. #define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))
  46.   
  47. #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
  48. #define hashboolean(t,p)        hashpow2(t, p)
  49. /*
  50. ** for some types, it is better to avoid modulus by power of 2, as
  51. ** they tend to have many 2 factors.
  52. */
  53. #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
  54. #define hashpointer(t,p) hashmod(t, IntPoint(p))
  55. /*
  56. ** number of ints inside a lua_Number
  57. */
  58. #define numints cast(int, sizeof(lua_Number)/sizeof(int))
  59. /*
  60. ** hash for lua_Numbers
  61. */
  62. static Node *hashnum (const Table *t, lua_Number n) {
  63.   unsigned int a[numints];
  64.   int i;
  65.   n += 1;  /* normalize number (avoid -0) */
  66.   lua_assert(sizeof(a) <= sizeof(n));
  67.   memcpy(a, &n, sizeof(a));
  68.   for (i = 1; i < numints; i++) a[0] += a[i];
  69.   return hashmod(t, cast(lu_hash, a[0]));
  70. }
  71. /*
  72. ** returns the `main' position of an element in a table (that is, the index
  73. ** of its hash value)
  74. */
  75. Node *luaH_mainposition (const Table *t, const TObject *key) {
  76.   switch (ttype(key)) {
  77.     case LUA_TNUMBER:
  78.       return hashnum(t, nvalue(key));
  79.     case LUA_TSTRING:
  80.       return hashstr(t, tsvalue(key));
  81.     case LUA_TBOOLEAN:
  82.       return hashboolean(t, bvalue(key));
  83.     case LUA_TLIGHTUSERDATA:
  84.       return hashpointer(t, pvalue(key));
  85.     default:
  86.       return hashpointer(t, gcvalue(key));
  87.   }
  88. }
  89. /*
  90. ** returns the index for `key' if `key' is an appropriate key to live in
  91. ** the array part of the table, -1 otherwise.
  92. */
  93. static int arrayindex (const TObject *key) {
  94.   if (ttisnumber(key)) {
  95.     int k;
  96.     lua_number2int(k, (nvalue(key)));
  97.     if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k))
  98.       return k;
  99.   }
  100.   return -1;  /* `key' did not match some condition */
  101. }
  102. /*
  103. ** returns the index of a `key' for table traversals. First goes all
  104. ** elements in the array part, then elements in the hash part. The
  105. ** beginning and end of a traversal are signalled by -1.
  106. */
  107. static int luaH_index (lua_State *L, Table *t, StkId key) {
  108.   int i;
  109.   if (ttisnil(key)) return -1;  /* first iteration */
  110.   i = arrayindex(key);
  111.   if (0 <= i && i <= t->sizearray) {  /* is `key' inside array part? */
  112.     return i-1;  /* yes; that's the index (corrected to C) */
  113.   }
  114.   else {
  115.     const TObject *v = luaH_get(t, key);
  116.     if (v == &luaO_nilobject)
  117.       luaG_runerror(L, "invalid key for `next'");
  118.     i = cast(int, (cast(const lu_byte *, v) -
  119.                    cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node));
  120.     return i + t->sizearray;  /* hash elements are numbered after array ones */
  121.   }
  122. }
  123. int luaH_next (lua_State *L, Table *t, StkId key) {
  124.   int i = luaH_index(L, t, key);  /* find original element */
  125.   for (i++; i < t->sizearray; i++) {  /* try first array part */
  126.     if (!ttisnil(&t->array[i])) {  /* a non-nil value? */
  127.       setnvalue(key, cast(lua_Number, i+1));
  128.       setobj2s(key+1, &t->array[i]);
  129.       return 1;
  130.     }
  131.   }
  132.   for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */
  133.     if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */
  134.       setobj2s(key, gkey(gnode(t, i)));
  135.       setobj2s(key+1, gval(gnode(t, i)));
  136.       return 1;
  137.     }
  138.   }
  139.   return 0;  /* no more elements */
  140. }
  141. /*
  142. ** {=============================================================
  143. ** Rehash
  144. ** ==============================================================
  145. */
  146. static void computesizes  (int nums[], int ntotal, int *narray, int *nhash) {
  147.   int i;
  148.   int a = nums[0];  /* number of elements smaller than 2^i */
  149.   int na = a;  /* number of elements to go to array part */
  150.   int n = (na == 0) ? -1 : 0;  /* (log of) optimal size for array part */
  151.   for (i = 1; a < *narray && *narray >= twoto(i-1); i++) {
  152.     if (nums[i] > 0) {
  153.       a += nums[i];
  154.       if (a >= twoto(i-1)) {  /* more than half elements in use? */
  155.         n = i;
  156.         na = a;
  157.       }
  158.     }
  159.   }
  160.   lua_assert(na <= *narray && *narray <= ntotal);
  161.   *nhash = ntotal - na;
  162.   *narray = (n == -1) ? 0 : twoto(n);
  163.   lua_assert(na <= *narray && na >= *narray/2);
  164. }
  165. static void numuse (const Table *t, int *narray, int *nhash) {
  166.   int nums[MAXBITS+1];
  167.   int i, lg;
  168.   int totaluse = 0;
  169.   /* count elements in array part */
  170.   for (i=0, lg=0; lg<=MAXBITS; lg++) {  /* for each slice [2^(lg-1) to 2^lg) */
  171.     int ttlg = twoto(lg);  /* 2^lg */
  172.     if (ttlg > t->sizearray) {
  173.       ttlg = t->sizearray;
  174.       if (i >= ttlg) break;
  175.     }
  176.     nums[lg] = 0;
  177.     for (; i<ttlg; i++) {
  178.       if (!ttisnil(&t->array[i])) {
  179.         nums[lg]++;
  180.         totaluse++;
  181.       }
  182.     }
  183.   }
  184.   for (; lg<=MAXBITS; lg++) nums[lg] = 0;  /* reset other counts */
  185.   *narray = totaluse;  /* all previous uses were in array part */
  186.   /* count elements in hash part */
  187.   i = sizenode(t);
  188.   while (i--) {
  189.     Node *n = &t->node[i];
  190.     if (!ttisnil(gval(n))) {
  191.       int k = arrayindex(gkey(n));
  192.       if (k >= 0) {  /* is `key' an appropriate array index? */
  193.         nums[luaO_log2(k-1)+1]++;  /* count as such */
  194.         (*narray)++;
  195.       }
  196.       totaluse++;
  197.     }
  198.   }
  199.   computesizes(nums, totaluse, narray, nhash);
  200. }
  201. static void setarrayvector (lua_State *L, Table *t, int size) {
  202.   int i;
  203.   luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
  204.   for (i=t->sizearray; i<size; i++)
  205.      setnilvalue(&t->array[i]);
  206.   t->sizearray = size;
  207. }
  208. static void setnodevector (lua_State *L, Table *t, int lsize) {
  209.   int i;
  210.   int size = twoto(lsize);
  211.   if (lsize > MAXBITS)
  212.     luaG_runerror(L, "table overflow");
  213.   if (lsize == 0) {  /* no elements to hash part? */
  214.     t->node = G(L)->dummynode;  /* use common `dummynode' */
  215.     lua_assert(ttisnil(gkey(t->node)));  /* assert invariants: */
  216.     lua_assert(ttisnil(gval(t->node)));
  217.     lua_assert(t->node->next == NULL);  /* (`dummynode' must be empty) */
  218.   }
  219.   else {
  220.     t->node = luaM_newvector(L, size, Node);
  221.     for (i=0; i<size; i++) {
  222.       t->node[i].next = NULL;
  223.       setnilvalue(gkey(gnode(t, i)));
  224.       setnilvalue(gval(gnode(t, i)));
  225.     }
  226.   }
  227.   t->lsizenode = cast(lu_byte, lsize);
  228.   t->firstfree = gnode(t, size-1);  /* first free position to be used */
  229. }
  230. static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
  231.   int i;
  232.   int oldasize = t->sizearray;
  233.   int oldhsize = t->lsizenode;
  234.   Node *nold;
  235.   Node temp[1];
  236.   if (oldhsize)
  237.     nold = t->node;  /* save old hash ... */
  238.   else {  /* old hash is `dummynode' */
  239.     lua_assert(t->node == G(L)->dummynode);
  240.     temp[0] = t->node[0];  /* copy it to `temp' */
  241.     nold = temp;
  242.     setnilvalue(gkey(G(L)->dummynode));  /* restate invariant */
  243.     setnilvalue(gval(G(L)->dummynode));
  244.     lua_assert(G(L)->dummynode->next == NULL);
  245.   }
  246.   if (nasize > oldasize)  /* array part must grow? */
  247.     setarrayvector(L, t, nasize);
  248.   /* create new hash part with appropriate size */
  249.   setnodevector(L, t, nhsize);  
  250.   /* re-insert elements */
  251.   if (nasize < oldasize) {  /* array part must shrink? */
  252.     t->sizearray = nasize;
  253.     /* re-insert elements from vanishing slice */
  254.     for (i=nasize; i<oldasize; i++) {
  255.       if (!ttisnil(&t->array[i]))
  256.         setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
  257.     }
  258.     /* shrink array */
  259.     luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
  260.   }
  261.   /* re-insert elements in hash part */
  262.   for (i = twoto(oldhsize) - 1; i >= 0; i--) {
  263.     Node *old = nold+i;
  264.     if (!ttisnil(gval(old)))
  265.       setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
  266.   }
  267.   if (oldhsize)
  268.     luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
  269. }
  270. static void rehash (lua_State *L, Table *t) {
  271.   int nasize, nhsize;
  272.   numuse(t, &nasize, &nhsize);  /* compute new sizes for array and hash parts */
  273.   resize(L, t, nasize, luaO_log2(nhsize)+1);
  274. }
  275. /*
  276. ** }=============================================================
  277. */
  278. Table *luaH_new (lua_State *L, int narray, int lnhash) {
  279.   Table *t = luaM_new(L, Table);
  280.   luaC_link(L, valtogco(t), LUA_TTABLE);
  281.   t->metatable = hvalue(defaultmeta(L));
  282.   t->flags = cast(lu_byte, ~0);
  283.   /* temporary values (kept only if some malloc fails) */
  284.   t->array = NULL;
  285.   t->sizearray = 0;
  286.   t->lsizenode = 0;
  287.   t->node = NULL;
  288.   setarrayvector(L, t, narray);
  289.   setnodevector(L, t, lnhash);
  290.   return t;
  291. }
  292. void luaH_free (lua_State *L, Table *t) {
  293.   if (t->lsizenode)
  294.     luaM_freearray(L, t->node, sizenode(t), Node);
  295.   luaM_freearray(L, t->array, t->sizearray, TObject);
  296.   luaM_freelem(L, t);
  297. }
  298. #if 0
  299. /*
  300. ** try to remove an element from a hash table; cannot move any element
  301. ** (because gc can call `remove' during a table traversal)
  302. */
  303. void luaH_remove (Table *t, Node *e) {
  304.   Node *mp = luaH_mainposition(t, gkey(e));
  305.   if (e != mp) {  /* element not in its main position? */
  306.     while (mp->next != e) mp = mp->next;  /* find previous */
  307.     mp->next = e->next;  /* remove `e' from its list */
  308.   }
  309.   else {
  310.     if (e->next != NULL) ??
  311.   }
  312.   lua_assert(ttisnil(gval(node)));
  313.   setnilvalue(gkey(e));  /* clear node `e' */
  314.   e->next = NULL;
  315. }
  316. #endif
  317. /*
  318. ** inserts a new key into a hash table; first, check whether key's main 
  319. ** position is free. If not, check whether colliding node is in its main 
  320. ** position or not: if it is not, move colliding node to an empty place and 
  321. ** put new key in its main position; otherwise (colliding node is in its main 
  322. ** position), new key goes to an empty position. 
  323. */
  324. static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
  325.   TObject *val;
  326.   Node *mp = luaH_mainposition(t, key);
  327.   if (!ttisnil(gval(mp))) {  /* main position is not free? */
  328.     Node *othern = luaH_mainposition(t, gkey(mp));  /* `mp' of colliding node */
  329.     Node *n = t->firstfree;  /* get a free place */
  330.     if (othern != mp) {  /* is colliding node out of its main position? */
  331.       /* yes; move colliding node into free position */
  332.       while (othern->next != mp) othern = othern->next;  /* find previous */
  333.       othern->next = n;  /* redo the chain with `n' in place of `mp' */
  334.       *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
  335.       mp->next = NULL;  /* now `mp' is free */
  336.       setnilvalue(gval(mp));
  337.     }
  338.     else {  /* colliding node is in its own main position */
  339.       /* new node will go into free position */
  340.       n->next = mp->next;  /* chain new position */
  341.       mp->next = n;
  342.       mp = n;
  343.     }
  344.   }
  345.   setobj2t(gkey(mp), key);  /* write barrier */
  346.   lua_assert(ttisnil(gval(mp)));
  347.   for (;;) {  /* correct `firstfree' */
  348.     if (ttisnil(gkey(t->firstfree)))
  349.       return gval(mp);  /* OK; table still has a free place */
  350.     else if (t->firstfree == t->node) break;  /* cannot decrement from here */
  351.     else (t->firstfree)--;
  352.   }
  353.   /* no more free places; must create one */
  354.   setbvalue(gval(mp), 0);  /* avoid new key being removed */
  355.   rehash(L, t);  /* grow table */
  356.   val = cast(TObject *, luaH_get(t, key));  /* get new position */
  357.   lua_assert(ttisboolean(val));
  358.   setnilvalue(val);
  359.   return val;
  360. }
  361. /*
  362. ** generic search function
  363. */
  364. static const TObject *luaH_getany (Table *t, const TObject *key) {
  365.   if (ttisnil(key)) return &luaO_nilobject;
  366.   else {
  367.     Node *n = luaH_mainposition(t, key);
  368.     do {  /* check whether `key' is somewhere in the chain */
  369.       if (luaO_rawequalObj(gkey(n), key)) return gval(n);  /* that's it */
  370.       else n = n->next;
  371.     } while (n);
  372.     return &luaO_nilobject;
  373.   }
  374. }
  375. /*
  376. ** search function for integers
  377. */
  378. const TObject *luaH_getnum (Table *t, int key) {
  379.   if (1 <= key && key <= t->sizearray)
  380.     return &t->array[key-1];
  381.   else {
  382.     lua_Number nk = cast(lua_Number, key);
  383.     Node *n = hashnum(t, nk);
  384.     do {  /* check whether `key' is somewhere in the chain */
  385.       if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk)
  386.         return gval(n);  /* that's it */
  387.       else n = n->next;
  388.     } while (n);
  389.     return &luaO_nilobject;
  390.   }
  391. }
  392. /*
  393. ** search function for strings
  394. */
  395. const TObject *luaH_getstr (Table *t, TString *key) {
  396.   Node *n = hashstr(t, key);
  397.   do {  /* check whether `key' is somewhere in the chain */
  398.     if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key)
  399.       return gval(n);  /* that's it */
  400.     else n = n->next;
  401.   } while (n);
  402.   return &luaO_nilobject;
  403. }
  404. /*
  405. ** main search function
  406. */
  407. const TObject *luaH_get (Table *t, const TObject *key) {
  408.   switch (ttype(key)) {
  409.     case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
  410.     case LUA_TNUMBER: {
  411.       int k;
  412.       lua_number2int(k, (nvalue(key)));
  413.       if (cast(lua_Number, k) == nvalue(key))  /* is an integer index? */
  414.         return luaH_getnum(t, k);  /* use specialized version */
  415.       /* else go through */
  416.     }
  417.     default: return luaH_getany(t, key);
  418.   }
  419. }
  420. TObject *luaH_set (lua_State *L, Table *t, const TObject *key) {
  421.   const TObject *p = luaH_get(t, key);
  422.   t->flags = 0;
  423.   if (p != &luaO_nilobject)
  424.     return cast(TObject *, p);
  425.   else {
  426.     if (ttisnil(key)) luaG_runerror(L, "table index is nil");
  427.     else if (ttisnumber(key) && nvalue(key) != nvalue(key))
  428.       luaG_runerror(L, "table index is NaN");
  429.     return newkey(L, t, key);
  430.   }
  431. }
  432. TObject *luaH_setnum (lua_State *L, Table *t, int key) {
  433.   const TObject *p = luaH_getnum(t, key);
  434.   if (p != &luaO_nilobject)
  435.     return cast(TObject *, p);
  436.   else {
  437.     TObject k;
  438.     setnvalue(&k, cast(lua_Number, key));
  439.     return newkey(L, t, &k);
  440.   }
  441. }