hash.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. ** hash.c
  3. ** hash manager for lua
  4. */
  5. char *rcs_hash="$Id: hash.c,v 2.42 1997/05/08 20:43:30 roberto Exp roberto $";
  6. #include "luamem.h"
  7. #include "opcode.h"
  8. #include "hash.h"
  9. #include "table.h"
  10. #include "lua.h"
  11. #include "auxlib.h"
  12. #define nhash(t) ((t)->nhash)
  13. #define nuse(t) ((t)->nuse)
  14. #define markarray(t) ((t)->mark)
  15. #define nodevector(t) ((t)->node)
  16. #define node(t,i) (&(t)->node[i])
  17. #define ref(n) (&(n)->ref)
  18. #define val(n) (&(n)->val)
  19. #define REHASH_LIMIT 0.70 /* avoid more than this % full */
  20. #define TagDefault LUA_T_ARRAY;
  21. static Hash *listhead = NULL;
  22. /* hash dimensions values */
  23. static Long dimensions[] =
  24. {5L, 11L, 23L, 47L, 97L, 197L, 397L, 797L, 1597L, 3203L, 6421L,
  25. 12853L, 25717L, 51437L, 102811L, 205619L, 411233L, 822433L,
  26. 1644817L, 3289613L, 6579211L, 13158023L, MAX_INT};
  27. int luaI_redimension (int nhash)
  28. {
  29. int i;
  30. for (i=0; dimensions[i]<MAX_INT; i++)
  31. {
  32. if (dimensions[i] > nhash)
  33. return dimensions[i];
  34. }
  35. lua_error("table overflow");
  36. return 0; /* to avoid warnings */
  37. }
  38. int lua_equalObj (TObject *t1, TObject *t2)
  39. {
  40. if (ttype(t1) != ttype(t2)) return 0;
  41. switch (ttype(t1))
  42. {
  43. case LUA_T_NIL: return 1;
  44. case LUA_T_NUMBER: return nvalue(t1) == nvalue(t2);
  45. case LUA_T_STRING: case LUA_T_USERDATA: return svalue(t1) == svalue(t2);
  46. case LUA_T_ARRAY: return avalue(t1) == avalue(t2);
  47. case LUA_T_FUNCTION: return t1->value.tf == t2->value.tf;
  48. case LUA_T_CFUNCTION: return fvalue(t1) == fvalue(t2);
  49. default:
  50. lua_error("internal error in `lua_equalObj'");
  51. return 0; /* UNREACHEABLE */
  52. }
  53. }
  54. static long int hashindex (TObject *ref)
  55. {
  56. long int h;
  57. switch (ttype(ref)) {
  58. case LUA_T_NUMBER:
  59. h = (long int)nvalue(ref); break;
  60. case LUA_T_STRING: case LUA_T_USERDATA:
  61. h = tsvalue(ref)->hash; break;
  62. case LUA_T_FUNCTION:
  63. h = (IntPoint)ref->value.tf; break;
  64. case LUA_T_CFUNCTION:
  65. h = (IntPoint)fvalue(ref); break;
  66. case LUA_T_ARRAY:
  67. h = (IntPoint)avalue(ref); break;
  68. default:
  69. lua_error ("unexpected type to index table");
  70. h = 0; /* UNREACHEABLE */
  71. }
  72. if (h < 0) h = -h;
  73. return h;
  74. }
  75. static int present (Hash *t, TObject *key)
  76. {
  77. long int h = hashindex(key);
  78. int tsize = nhash(t);
  79. int h1 = h%tsize;
  80. TObject *rf = ref(node(t, h1));
  81. if (ttype(rf) != LUA_T_NIL && !lua_equalObj(key, rf)) {
  82. int h2 = h%(tsize-2) + 1;
  83. do {
  84. h1 = (h1+h2)%tsize;
  85. rf = ref(node(t, h1));
  86. } while (ttype(rf) != LUA_T_NIL && !lua_equalObj(key, rf));
  87. }
  88. return h1;
  89. }
  90. /*
  91. ** Alloc a vector node
  92. */
  93. static Node *hashnodecreate (int nhash)
  94. {
  95. int i;
  96. Node *v = newvector (nhash, Node);
  97. for (i=0; i<nhash; i++)
  98. ttype(ref(&v[i])) = LUA_T_NIL;
  99. return v;
  100. }
  101. /*
  102. ** Create a new hash. Return the hash pointer or NULL on error.
  103. */
  104. static Hash *hashcreate (int nhash)
  105. {
  106. Hash *t = new(Hash);
  107. nhash = luaI_redimension((int)((float)nhash/REHASH_LIMIT));
  108. nodevector(t) = hashnodecreate(nhash);
  109. nhash(t) = nhash;
  110. nuse(t) = 0;
  111. markarray(t) = 0;
  112. t->htag = TagDefault;
  113. return t;
  114. }
  115. /*
  116. ** Delete a hash
  117. */
  118. static void hashdelete (Hash *t)
  119. {
  120. luaI_free (nodevector(t));
  121. luaI_free(t);
  122. }
  123. /*
  124. ** Mark a hash and check its elements
  125. */
  126. void lua_hashmark (Hash *h)
  127. {
  128. if (markarray(h) == 0)
  129. {
  130. int i;
  131. markarray(h) = 1;
  132. for (i=0; i<nhash(h); i++)
  133. {
  134. Node *n = node(h,i);
  135. if (ttype(ref(n)) != LUA_T_NIL)
  136. {
  137. lua_markobject(&n->ref);
  138. lua_markobject(&n->val);
  139. }
  140. }
  141. }
  142. }
  143. void luaI_hashcallIM (Hash *l)
  144. {
  145. TObject t;
  146. ttype(&t) = LUA_T_ARRAY;
  147. for (; l; l=l->next) {
  148. avalue(&t) = l;
  149. luaI_gcIM(&t);
  150. }
  151. }
  152. void luaI_hashfree (Hash *frees)
  153. {
  154. while (frees) {
  155. Hash *next = frees->next;
  156. hashdelete(frees);
  157. frees = next;
  158. }
  159. }
  160. Hash *luaI_hashcollector (long *acum)
  161. {
  162. Hash *curr_array = listhead, *prev = NULL, *frees = NULL;
  163. long counter = 0;
  164. while (curr_array != NULL) {
  165. Hash *next = curr_array->next;
  166. if (markarray(curr_array) != 1) {
  167. if (prev == NULL)
  168. listhead = next;
  169. else
  170. prev->next = next;
  171. curr_array->next = frees;
  172. frees = curr_array;
  173. ++counter;
  174. }
  175. else {
  176. markarray(curr_array) = 0;
  177. prev = curr_array;
  178. }
  179. curr_array = next;
  180. }
  181. *acum += counter;
  182. return frees;
  183. }
  184. /*
  185. ** Create a new array
  186. ** This function inserts the new array in the array list. It also
  187. ** executes garbage collection if the number of arrays created
  188. ** exceed a pre-defined range.
  189. */
  190. Hash *lua_createarray (int nhash)
  191. {
  192. Hash *array;
  193. lua_pack();
  194. array = hashcreate(nhash);
  195. array->next = listhead;
  196. listhead = array;
  197. return array;
  198. }
  199. /*
  200. ** Rehash:
  201. ** Check if table has deleted slots. It it has, it does not need to
  202. ** grow, since rehash will reuse them.
  203. */
  204. static int emptyslots (Hash *t)
  205. {
  206. int i;
  207. for (i=nhash(t)-1; i>=0; i--) {
  208. Node *n = node(t, i);
  209. if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) == LUA_T_NIL)
  210. return 1;
  211. }
  212. return 0;
  213. }
  214. static void rehash (Hash *t)
  215. {
  216. int nold = nhash(t);
  217. Node *vold = nodevector(t);
  218. int i;
  219. if (!emptyslots(t))
  220. nhash(t) = luaI_redimension(nhash(t));
  221. nodevector(t) = hashnodecreate(nhash(t));
  222. for (i=0; i<nold; i++) {
  223. Node *n = vold+i;
  224. if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) != LUA_T_NIL)
  225. *node(t, present(t, ref(n))) = *n; /* copy old node to new hash */
  226. }
  227. luaI_free(vold);
  228. }
  229. /*
  230. ** If the hash node is present, return its pointer, otherwise return
  231. ** null.
  232. */
  233. TObject *lua_hashget (Hash *t, TObject *ref)
  234. {
  235. int h = present(t, ref);
  236. if (ttype(ref(node(t, h))) != LUA_T_NIL) return val(node(t, h));
  237. else return NULL;
  238. }
  239. /*
  240. ** If the hash node is present, return its pointer, otherwise create a new
  241. ** node for the given reference and also return its pointer.
  242. */
  243. TObject *lua_hashdefine (Hash *t, TObject *ref)
  244. {
  245. Node *n = node(t, present(t, ref));
  246. if (ttype(ref(n)) == LUA_T_NIL) {
  247. nuse(t)++;
  248. if ((float)nuse(t) > (float)nhash(t)*REHASH_LIMIT) {
  249. rehash(t);
  250. n = node(t, present(t, ref));
  251. }
  252. *ref(n) = *ref;
  253. ttype(val(n)) = LUA_T_NIL;
  254. }
  255. return (val(n));
  256. }
  257. /*
  258. ** Internal function to manipulate arrays.
  259. ** Given an array object and a reference value, return the next element
  260. ** in the hash.
  261. ** This function pushs the element value and its reference to the stack.
  262. */
  263. static void hashnext (Hash *t, int i)
  264. {
  265. Node *n;
  266. int tsize = nhash(t);
  267. if (i >= tsize)
  268. return;
  269. n = node(t, i);
  270. while (ttype(ref(n)) == LUA_T_NIL || ttype(val(n)) == LUA_T_NIL) {
  271. if (++i >= tsize)
  272. return;
  273. n = node(t, i);
  274. }
  275. luaI_pushobject(ref(node(t,i)));
  276. luaI_pushobject(val(node(t,i)));
  277. }
  278. void lua_next (void)
  279. {
  280. Hash *t;
  281. lua_Object o = lua_getparam(1);
  282. lua_Object r = lua_getparam(2);
  283. luaL_arg_check(lua_istable(o), 1, "table expected");
  284. luaL_arg_check(r != LUA_NOOBJECT, 2, "value expected");
  285. t = avalue(luaI_Address(o));
  286. if (lua_isnil(r))
  287. hashnext(t, 0);
  288. else
  289. hashnext(t, present(t, luaI_Address(r))+1);
  290. }