ltable.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. ** $Id: ltable.c,v 1.24 1999/09/22 14:38:45 roberto Exp roberto $
  3. ** Lua tables (hash)
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include "lauxlib.h"
  7. #include "lmem.h"
  8. #include "lobject.h"
  9. #include "lstate.h"
  10. #include "ltable.h"
  11. #include "lua.h"
  12. #define gcsize(n) (1+(n/16))
  13. #define nuse(t) ((t)->nuse)
  14. #define nodevector(t) ((t)->node)
  15. #define TagDefault LUA_T_ARRAY;
  16. static long int hashindex (const TObject *ref) {
  17. long int h;
  18. switch (ttype(ref)) {
  19. case LUA_T_NUMBER:
  20. h = (long int)nvalue(ref);
  21. break;
  22. case LUA_T_STRING: case LUA_T_USERDATA:
  23. h = (IntPoint)tsvalue(ref);
  24. break;
  25. case LUA_T_ARRAY:
  26. h = (IntPoint)avalue(ref);
  27. break;
  28. case LUA_T_PROTO:
  29. h = (IntPoint)tfvalue(ref);
  30. break;
  31. case LUA_T_CPROTO:
  32. h = (IntPoint)fvalue(ref);
  33. break;
  34. case LUA_T_CLOSURE:
  35. h = (IntPoint)clvalue(ref);
  36. break;
  37. default:
  38. lua_error("unexpected type to index table");
  39. h = 0; /* to avoid warnings */
  40. }
  41. return (h >= 0 ? h : -(h+1));
  42. }
  43. Node *luaH_present (const Hash *t, const TObject *key) {
  44. const int tsize = nhash(t);
  45. const long int h = hashindex(key);
  46. int h1 = h%tsize;
  47. Node *n = node(t, h1);
  48. /* keep looking until an entry with "ref" equal to key or nil */
  49. while ((ttype(ref(n)) == ttype(key)) ? !luaO_equalval(key, ref(n))
  50. : ttype(ref(n)) != LUA_T_NIL) {
  51. h1 += (h&(tsize-2)) + 1; /* double hashing */
  52. if (h1 >= tsize) h1 -= tsize;
  53. n = node(t, h1);
  54. }
  55. return n;
  56. }
  57. static Node *hashnodecreate (int nhash) {
  58. Node *const v = luaM_newvector(nhash, Node);
  59. int i;
  60. for (i=0; i<nhash; i++)
  61. ttype(ref(&v[i])) = ttype(val(&v[i])) = LUA_T_NIL;
  62. return v;
  63. }
  64. Hash *luaH_new (int nhash) {
  65. Hash *const t = luaM_new(Hash);
  66. nhash = luaO_redimension(nhash*3/2);
  67. nodevector(t) = hashnodecreate(nhash);
  68. nhash(t) = nhash;
  69. nuse(t) = 0;
  70. t->htag = TagDefault;
  71. t->next = L->roottable;
  72. L->roottable = t;
  73. t->marked = 0;
  74. L->nblocks += gcsize(nhash);
  75. return t;
  76. }
  77. void luaH_free (Hash *t) {
  78. L->nblocks -= gcsize(t->nhash);
  79. luaM_free(nodevector(t));
  80. luaM_free(t);
  81. }
  82. static int newsize (Hash *t) {
  83. Node *const v = t->node;
  84. const int size = nhash(t);
  85. int realuse = 0;
  86. int i;
  87. for (i=0; i<size; i++) {
  88. if (ttype(val(v+i)) != LUA_T_NIL)
  89. realuse++;
  90. }
  91. return luaO_redimension(realuse*2);
  92. }
  93. static void rehash (Hash *t) {
  94. const int nold = nhash(t);
  95. Node *const vold = nodevector(t);
  96. const int nnew = newsize(t);
  97. int i;
  98. nodevector(t) = hashnodecreate(nnew);
  99. nhash(t) = nnew;
  100. nuse(t) = 0;
  101. for (i=0; i<nold; i++) {
  102. Node *n = vold+i;
  103. if (ttype(val(n)) != LUA_T_NIL) {
  104. *luaH_present(t, ref(n)) = *n; /* copy old node to new hash */
  105. nuse(t)++;
  106. }
  107. }
  108. L->nblocks += gcsize(nnew)-gcsize(nold);
  109. luaM_free(vold);
  110. }
  111. void luaH_set (Hash *t, const TObject *ref, const TObject *val) {
  112. Node *const n = luaH_present(t, ref);
  113. *val(n) = *val;
  114. if (ttype(ref(n)) == LUA_T_NIL) { /* new node? */
  115. *ref(n) = *ref; /* set key */
  116. nuse(t)++; /* count it */
  117. if ((long)nuse(t)*3L > (long)nhash(t)*2L) /* check size */
  118. rehash(t);
  119. }
  120. }
  121. int luaH_pos (const Hash *t, const TObject *r) {
  122. Node *const n = luaH_present(t, r);
  123. luaL_arg_check(ttype(val(n)) != LUA_T_NIL, 2, "key not found");
  124. return n-(t->node);
  125. }
  126. void luaH_setint (Hash *t, int ref, const TObject *val) {
  127. TObject index;
  128. ttype(&index) = LUA_T_NUMBER;
  129. nvalue(&index) = ref;
  130. luaH_set(t, &index, val);
  131. }
  132. TObject *luaH_getint (const Hash *t, int ref) {
  133. TObject index;
  134. ttype(&index) = LUA_T_NUMBER;
  135. nvalue(&index) = ref;
  136. return luaH_get(t, &index);
  137. }