ltable.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. ** $Id: ltable.c,v 1.16 1998/12/30 13:14:46 roberto Exp $
  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. {
  19. long int h;
  20. switch (ttype(ref)) {
  21. case LUA_T_NUMBER:
  22. h = (long int)nvalue(ref);
  23. break;
  24. case LUA_T_STRING: case LUA_T_USERDATA:
  25. h = (IntPoint)tsvalue(ref);
  26. break;
  27. case LUA_T_ARRAY:
  28. h = (IntPoint)avalue(ref);
  29. break;
  30. case LUA_T_PROTO:
  31. h = (IntPoint)tfvalue(ref);
  32. break;
  33. case LUA_T_CPROTO:
  34. h = (IntPoint)fvalue(ref);
  35. break;
  36. case LUA_T_CLOSURE:
  37. h = (IntPoint)clvalue(ref);
  38. break;
  39. default:
  40. lua_error("unexpected type to index table");
  41. h = 0; /* to avoid warnings */
  42. }
  43. return (h >= 0 ? h : -(h+1));
  44. }
  45. static int present (Hash *t, TObject *key)
  46. {
  47. int tsize = nhash(t);
  48. long int h = hashindex(key);
  49. int h1 = h%tsize;
  50. TObject *rf = ref(node(t, h1));
  51. if (ttype(rf) != LUA_T_NIL && !luaO_equalObj(key, rf)) {
  52. int h2 = h%(tsize-2) + 1;
  53. do {
  54. h1 += h2;
  55. if (h1 >= tsize) h1 -= tsize;
  56. rf = ref(node(t, h1));
  57. } while (ttype(rf) != LUA_T_NIL && !luaO_equalObj(key, rf));
  58. }
  59. return h1;
  60. }
  61. /*
  62. ** Alloc a vector node
  63. */
  64. static Node *hashnodecreate (int nhash)
  65. {
  66. Node *v = luaM_newvector(nhash, Node);
  67. int i;
  68. for (i=0; i<nhash; i++)
  69. ttype(ref(&v[i])) = LUA_T_NIL;
  70. return v;
  71. }
  72. /*
  73. ** Delete a hash
  74. */
  75. static void hashdelete (Hash *t)
  76. {
  77. luaM_free(nodevector(t));
  78. luaM_free(t);
  79. }
  80. void luaH_free (Hash *frees)
  81. {
  82. while (frees) {
  83. Hash *next = (Hash *)frees->head.next;
  84. L->nblocks -= gcsize(frees->nhash);
  85. hashdelete(frees);
  86. frees = next;
  87. }
  88. }
  89. Hash *luaH_new (int nhash) {
  90. Hash *t = luaM_new(Hash);
  91. nhash = luaO_redimension(nhash*3/2);
  92. nodevector(t) = hashnodecreate(nhash);
  93. nhash(t) = nhash;
  94. nuse(t) = 0;
  95. t->htag = TagDefault;
  96. luaO_insertlist(&(L->roottable), (GCnode *)t);
  97. L->nblocks += gcsize(nhash);
  98. return t;
  99. }
  100. static int newsize (Hash *t) {
  101. Node *v = t->node;
  102. int size = nhash(t);
  103. int realuse = 0;
  104. int i;
  105. for (i=0; i<size; i++) {
  106. if (ttype(ref(v+i)) != LUA_T_NIL && ttype(val(v+i)) != LUA_T_NIL)
  107. realuse++;
  108. }
  109. return luaO_redimension((realuse+1)*2); /* +1 is the new element */
  110. }
  111. static void rehash (Hash *t) {
  112. int nold = nhash(t);
  113. Node *vold = nodevector(t);
  114. int nnew = newsize(t);
  115. int i;
  116. nodevector(t) = hashnodecreate(nnew);
  117. nhash(t) = nnew;
  118. nuse(t) = 0;
  119. for (i=0; i<nold; i++) {
  120. Node *n = vold+i;
  121. if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) != LUA_T_NIL) {
  122. *node(t, present(t, ref(n))) = *n; /* copy old node to luaM_new hash */
  123. nuse(t)++;
  124. }
  125. }
  126. L->nblocks += gcsize(nnew)-gcsize(nold);
  127. luaM_free(vold);
  128. }
  129. /*
  130. ** If the hash node is present, return its pointer, otherwise return
  131. ** null.
  132. */
  133. TObject *luaH_get (Hash *t, TObject *ref)
  134. {
  135. int h = present(t, ref);
  136. if (ttype(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h));
  137. else return &luaO_nilobject;
  138. }
  139. /*
  140. ** If the hash node is present, return its pointer, otherwise create a luaM_new
  141. ** node for the given reference and also return its pointer.
  142. */
  143. TObject *luaH_set (Hash *t, TObject *ref)
  144. {
  145. Node *n = node(t, present(t, ref));
  146. if (ttype(ref(n)) == LUA_T_NIL) {
  147. if ((long)nuse(t)*3L > (long)nhash(t)*2L) {
  148. rehash(t);
  149. n = node(t, present(t, ref));
  150. }
  151. nuse(t)++;
  152. *ref(n) = *ref;
  153. ttype(val(n)) = LUA_T_NIL;
  154. }
  155. return (val(n));
  156. }
  157. static Node *hashnext (Hash *t, int i) {
  158. Node *n;
  159. int tsize = nhash(t);
  160. if (i >= tsize)
  161. return NULL;
  162. n = node(t, i);
  163. while (ttype(ref(n)) == LUA_T_NIL || ttype(val(n)) == LUA_T_NIL) {
  164. if (++i >= tsize)
  165. return NULL;
  166. n = node(t, i);
  167. }
  168. return node(t, i);
  169. }
  170. Node *luaH_next (Hash *t, TObject *r) {
  171. if (ttype(r) == LUA_T_NIL)
  172. return hashnext(t, 0);
  173. else {
  174. int i = present(t, r);
  175. Node *n = node(t, i);
  176. luaL_arg_check(ttype(ref(n))!=LUA_T_NIL && ttype(val(n))!=LUA_T_NIL,
  177. 2, "key not found");
  178. return hashnext(t, i+1);
  179. }
  180. }
  181. void luaH_setint (Hash *t, int ref, TObject *val) {
  182. TObject index;
  183. ttype(&index) = LUA_T_NUMBER;
  184. nvalue(&index) = ref;
  185. *(luaH_set(t, &index)) = *val;
  186. }
  187. TObject *luaH_getint (Hash *t, int ref) {
  188. TObject index;
  189. ttype(&index) = LUA_T_NUMBER;
  190. nvalue(&index) = ref;
  191. return luaH_get(t, &index);
  192. }
  193. void luaH_move (Hash *t, int from, int to) {
  194. TObject index;
  195. TObject *toadd;
  196. ttype(&index) = LUA_T_NUMBER;
  197. nvalue(&index) = to;
  198. toadd = luaH_set(t, &index);
  199. nvalue(&index) = from;
  200. *toadd = *luaH_get(t, &index);
  201. }