ltable.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. ** $Id: ltable.c,v 1.18 1999/01/22 18:47:23 roberto Exp roberto $
  3. ** Lua tables (hash)
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdlib.h>
  7. #include "lauxlib.h"
  8. #include "lmem.h"
  9. #include "lobject.h"
  10. #include "lstate.h"
  11. #include "ltable.h"
  12. #include "lua.h"
  13. #define gcsize(n) (1+(n/16))
  14. #define nuse(t) ((t)->nuse)
  15. #define nodevector(t) ((t)->node)
  16. #define TagDefault LUA_T_ARRAY;
  17. static long int hashindex (TObject *ref) {
  18. long int h;
  19. switch (ttype(ref)) {
  20. case LUA_T_NUMBER:
  21. h = (long int)nvalue(ref);
  22. break;
  23. case LUA_T_STRING: case LUA_T_USERDATA:
  24. h = (IntPoint)tsvalue(ref);
  25. break;
  26. case LUA_T_ARRAY:
  27. h = (IntPoint)avalue(ref);
  28. break;
  29. case LUA_T_PROTO:
  30. h = (IntPoint)tfvalue(ref);
  31. break;
  32. case LUA_T_CPROTO:
  33. h = (IntPoint)fvalue(ref);
  34. break;
  35. case LUA_T_CLOSURE:
  36. h = (IntPoint)clvalue(ref);
  37. break;
  38. default:
  39. lua_error("unexpected type to index table");
  40. h = 0; /* to avoid warnings */
  41. }
  42. return (h >= 0 ? h : -(h+1));
  43. }
  44. Node *luaH_present (Hash *t, TObject *ref) {
  45. int tsize = nhash(t);
  46. long int h = hashindex(ref);
  47. int h1 = h%tsize;
  48. Node *n = node(t, h1);
  49. /* keep looking until an entry with "ref" equal to ref or nil */
  50. if ((ttype(ref(n)) == ttype(ref) ? !luaO_equalval(ref, ref(n))
  51. : ttype(ref(n)) != LUA_T_NIL)) {
  52. int h2 = h%(tsize-2) + 1;
  53. do {
  54. h1 += h2;
  55. if (h1 >= tsize) h1 -= tsize;
  56. n = node(t, h1);
  57. } while ((ttype(ref(n)) == ttype(ref) ? !luaO_equalval(ref, ref(n))
  58. : ttype(ref(n)) != LUA_T_NIL));
  59. }
  60. return n;
  61. }
  62. void luaH_free (Hash *frees) {
  63. while (frees) {
  64. Hash *next = (Hash *)frees->head.next;
  65. L->nblocks -= gcsize(frees->nhash);
  66. luaM_free(nodevector(frees));
  67. luaM_free(frees);
  68. frees = next;
  69. }
  70. }
  71. static Node *hashnodecreate (int nhash) {
  72. Node *v = luaM_newvector(nhash, Node);
  73. int i;
  74. for (i=0; i<nhash; i++)
  75. ttype(ref(&v[i])) = ttype(val(&v[i])) = LUA_T_NIL;
  76. return v;
  77. }
  78. Hash *luaH_new (int nhash) {
  79. Hash *t = luaM_new(Hash);
  80. nhash = luaO_redimension(nhash*3/2);
  81. nodevector(t) = hashnodecreate(nhash);
  82. nhash(t) = nhash;
  83. nuse(t) = 0;
  84. t->htag = TagDefault;
  85. luaO_insertlist(&(L->roottable), (GCnode *)t);
  86. L->nblocks += gcsize(nhash);
  87. return t;
  88. }
  89. static int newsize (Hash *t) {
  90. Node *v = t->node;
  91. int size = nhash(t);
  92. int realuse = 0;
  93. int i;
  94. for (i=0; i<size; i++) {
  95. if (ttype(val(v+i)) != LUA_T_NIL)
  96. realuse++;
  97. }
  98. return luaO_redimension((realuse+1)*2); /* +1 is the new element */
  99. }
  100. static void rehash (Hash *t) {
  101. int nold = nhash(t);
  102. Node *vold = nodevector(t);
  103. int nnew = newsize(t);
  104. int i;
  105. nodevector(t) = hashnodecreate(nnew);
  106. nhash(t) = nnew;
  107. nuse(t) = 0;
  108. for (i=0; i<nold; i++) {
  109. Node *n = vold+i;
  110. if (ttype(val(n)) != LUA_T_NIL) {
  111. *luaH_present(t, ref(n)) = *n; /* copy old node to new hash */
  112. nuse(t)++;
  113. }
  114. }
  115. L->nblocks += gcsize(nnew)-gcsize(nold);
  116. luaM_free(vold);
  117. }
  118. /*
  119. ** If the hash node is present, return its pointer, otherwise create a new
  120. ** node for the given reference and also return its pointer.
  121. */
  122. TObject *luaH_set (Hash *t, TObject *ref) {
  123. Node *n = luaH_present(t, ref);
  124. if (ttype(ref(n)) == LUA_T_NIL) {
  125. if ((long)nuse(t)*3L > (long)nhash(t)*2L) {
  126. rehash(t);
  127. n = luaH_present(t, ref);
  128. }
  129. nuse(t)++;
  130. *ref(n) = *ref;
  131. }
  132. return (val(n));
  133. }
  134. static Node *hashnext (Hash *t, int i) {
  135. Node *n;
  136. int tsize = nhash(t);
  137. if (i >= tsize)
  138. return NULL;
  139. n = node(t, i);
  140. while (ttype(val(n)) == LUA_T_NIL) {
  141. if (++i >= tsize)
  142. return NULL;
  143. n = node(t, i);
  144. }
  145. return n;
  146. }
  147. Node *luaH_next (Hash *t, TObject *r) {
  148. if (ttype(r) == LUA_T_NIL)
  149. return hashnext(t, 0);
  150. else {
  151. Node *n = luaH_present(t, r);
  152. luaL_arg_check(ttype(val(n)) != LUA_T_NIL, 2, "key not found");
  153. return hashnext(t, (n-(t->node))+1);
  154. }
  155. }
  156. void luaH_setint (Hash *t, int ref, TObject *val) {
  157. TObject index;
  158. ttype(&index) = LUA_T_NUMBER;
  159. nvalue(&index) = ref;
  160. *(luaH_set(t, &index)) = *val;
  161. }
  162. TObject *luaH_getint (Hash *t, int ref) {
  163. TObject index;
  164. ttype(&index) = LUA_T_NUMBER;
  165. nvalue(&index) = ref;
  166. return luaH_get(t, &index);
  167. }
  168. void luaH_move (Hash *t, int from, int to) {
  169. TObject index;
  170. TObject *toadd;
  171. ttype(&index) = LUA_T_NUMBER;
  172. nvalue(&index) = to;
  173. toadd = luaH_set(t, &index);
  174. nvalue(&index) = from;
  175. *toadd = *luaH_get(t, &index);
  176. }