00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #include <string.h>
00025 
00026 #define ltable_c
00027 
00028 #include "lua.h"
00029 
00030 #include "ldebug.h"
00031 #include "ldo.h"
00032 #include "lgc.h"
00033 #include "lmem.h"
00034 #include "lobject.h"
00035 #include "lstate.h"
00036 #include "ltable.h"
00037 
00038 
00039 
00040 
00041 
00042 #if BITS_INT > 26
00043 #define MAXBITS         24
00044 #else
00045 #define MAXBITS         (BITS_INT-2)
00046 #endif
00047 
00048 
00049 #define toobig(x)       ((((x)-1) >> MAXBITS) != 0)
00050 
00051 
00052 
00053 #ifndef lua_number2int
00054 #define lua_number2int(i,n)     ((i)=(int)(n))
00055 #endif
00056 
00057 
00058 #define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))
00059   
00060 #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
00061 #define hashboolean(t,p)        hashpow2(t, p)
00062 
00063 
00064 
00065 
00066 
00067 
00068 #define hashmod(t,n)    (gnode(t, ((n) % ((sizenode(t)-1)|1))))
00069 
00070 
00071 #define hashpointer(t,p)        hashmod(t, IntPoint(p))
00072 
00073 
00074 
00075 
00076 
00077 #define numints         cast(int, sizeof(lua_Number)/sizeof(int))
00078 
00079 
00080 
00081 
00082 
00083 static Node *hashnum (const Table *t, lua_Number n)
00084         
00085 {
00086   unsigned int a[numints];
00087   int i;
00088   n += 1;  
00089   lua_assert(sizeof(a) <= sizeof(n));
00090   memcpy(a, &n, sizeof(a));
00091   for (i = 1; i < numints; i++) a[0] += a[i];
00092   return hashmod(t, cast(lu_hash, a[0]));
00093 }
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 Node *luaH_mainposition (const Table *t, const TObject *key) {
00102   switch (ttype(key)) {
00103     case LUA_TNUMBER:
00104       return hashnum(t, nvalue(key));
00105     case LUA_TSTRING:
00106       return hashstr(t, tsvalue(key));
00107     case LUA_TBOOLEAN:
00108       return hashboolean(t, bvalue(key));
00109     case LUA_TLIGHTUSERDATA:
00110       return hashpointer(t, pvalue(key));
00111     default:
00112       return hashpointer(t, gcvalue(key));
00113   }
00114 }
00115 
00116 
00117 
00118 
00119 
00120 
00121 static int arrayindex (const TObject *key)
00122         
00123 {
00124   if (ttisnumber(key)) {
00125     int k;
00126     lua_number2int(k, (nvalue(key)));
00127     if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k))
00128       return k;
00129   }
00130   return -1;  
00131 }
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 static int luaH_index (lua_State *L, Table *t, StkId key)
00140         
00141 {
00142   int i;
00143   if (ttisnil(key)) return -1;  
00144   i = arrayindex(key);
00145   if (0 <= i && i <= t->sizearray) {  
00146     return i-1;  
00147   }
00148   else {
00149     const TObject *v = luaH_get(t, key);
00150     if (v == &luaO_nilobject)
00151       luaG_runerror(L, "invalid key for `next'");
00152     i = cast(int, (cast(const lu_byte *, v) -
00153                    cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node));
00154     return i + t->sizearray;  
00155   }
00156 }
00157 
00158 
00159 int luaH_next (lua_State *L, Table *t, StkId key) {
00160   int i = luaH_index(L, t, key);  
00161   for (i++; i < t->sizearray; i++) {  
00162     if (!ttisnil(&t->array[i])) {  
00163       setnvalue(key, cast(lua_Number, i+1));
00164       setobj2s(key+1, &t->array[i]);
00165       return 1;
00166     }
00167   }
00168   for (i -= t->sizearray; i < sizenode(t); i++) {  
00169     if (!ttisnil(gval(gnode(t, i)))) {  
00170       setobj2s(key, gkey(gnode(t, i)));
00171       setobj2s(key+1, gval(gnode(t, i)));
00172       return 1;
00173     }
00174   }
00175   return 0;  
00176 }
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 static void computesizes  (int nums[], int ntotal, int *narray, int *nhash)
00187         
00188 {
00189   int i;
00190   int a = nums[0];  
00191   int na = a;  
00192   int n = (na == 0) ? -1 : 0;  
00193   for (i = 1; a < *narray && *narray >= twoto(i-1); i++) {
00194     if (nums[i] > 0) {
00195       a += nums[i];
00196       if (a >= twoto(i-1)) {  
00197         n = i;
00198         na = a;
00199       }
00200     }
00201   }
00202   lua_assert(na <= *narray && *narray <= ntotal);
00203   *nhash = ntotal - na;
00204   *narray = (n == -1) ? 0 : twoto(n);
00205   lua_assert(na <= *narray && na >= *narray/2);
00206 }
00207 
00208 
00209 static void numuse (const Table *t, int *narray, int *nhash)
00210         
00211 {
00212   int nums[MAXBITS+1];
00213   int i, lg;
00214   int totaluse = 0;
00215   
00216   for (i=0, lg=0; lg<=MAXBITS; lg++) {  
00217     int ttlg = twoto(lg);  
00218     if (ttlg > t->sizearray) {
00219       ttlg = t->sizearray;
00220       if (i >= ttlg) break;
00221     }
00222     nums[lg] = 0;
00223     for (; i<ttlg; i++) {
00224       if (!ttisnil(&t->array[i])) {
00225         nums[lg]++;
00226         totaluse++;
00227       }
00228     }
00229   }
00230   for (; lg<=MAXBITS; lg++) nums[lg] = 0;  
00231   *narray = totaluse;  
00232   
00233   i = sizenode(t);
00234   while (i--) {
00235     Node *n = &t->node[i];
00236     if (!ttisnil(gval(n))) {
00237       int k = arrayindex(gkey(n));
00238       if (k >= 0) {  
00239         nums[luaO_log2(k-1)+1]++;  
00240         (*narray)++;
00241       }
00242       totaluse++;
00243     }
00244   }
00245   computesizes(nums, totaluse, narray, nhash);
00246 }
00247 
00248 
00249 static void setarrayvector (lua_State *L, Table *t, int size)
00250         
00251 {
00252   int i;
00253   luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
00254   for (i=t->sizearray; i<size; i++)
00255      setnilvalue(&t->array[i]);
00256   t->sizearray = size;
00257 }
00258 
00259 
00260 static void setnodevector (lua_State *L, Table *t, int lsize)
00261         
00262 {
00263   int i;
00264   int size = twoto(lsize);
00265   if (lsize > MAXBITS)
00266     luaG_runerror(L, "table overflow");
00267   if (lsize == 0) {  
00268     t->node = G(L)->dummynode;  
00269     lua_assert(ttisnil(gkey(t->node)));  
00270     lua_assert(ttisnil(gval(t->node)));
00271     lua_assert(t->node->next == NULL);  
00272   }
00273   else {
00274     t->node = luaM_newvector(L, size, Node);
00275     for (i=0; i<size; i++) {
00276       t->node[i].next = NULL;
00277       setnilvalue(gkey(gnode(t, i)));
00278       setnilvalue(gval(gnode(t, i)));
00279     }
00280   }
00281   t->lsizenode = cast(lu_byte, lsize);
00282   t->firstfree = gnode(t, size-1);  
00283 }
00284 
00285 
00286 static void resize (lua_State *L, Table *t, int nasize, int nhsize)
00287         
00288 {
00289   int i;
00290   int oldasize = t->sizearray;
00291   int oldhsize = t->lsizenode;
00292   Node *nold;
00293   Node temp[1];
00294   if (oldhsize)
00295     nold = t->node;  
00296   else {  
00297     lua_assert(t->node == G(L)->dummynode);
00298     temp[0] = t->node[0];  
00299     nold = temp;
00300     setnilvalue(gkey(G(L)->dummynode));  
00301     setnilvalue(gval(G(L)->dummynode));
00302     lua_assert(G(L)->dummynode->next == NULL);
00303   }
00304   if (nasize > oldasize)  
00305     setarrayvector(L, t, nasize);
00306   
00307   setnodevector(L, t, nhsize);  
00308   
00309   if (nasize < oldasize) {  
00310     t->sizearray = nasize;
00311     
00312     for (i=nasize; i<oldasize; i++) {
00313       if (!ttisnil(&t->array[i]))
00314         setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
00315     }
00316     
00317     luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
00318   }
00319   
00320   for (i = twoto(oldhsize) - 1; i >= 0; i--) {
00321     Node *old = nold+i;
00322     if (!ttisnil(gval(old)))
00323       setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
00324   }
00325   if (oldhsize)
00326     luaM_freearray(L, nold, twoto(oldhsize), Node);  
00327 }
00328 
00329 
00330 static void rehash (lua_State *L, Table *t)
00331         
00332 {
00333   int nasize, nhsize;
00334   numuse(t, &nasize, &nhsize);  
00335   resize(L, t, nasize, luaO_log2(nhsize)+1);
00336 }
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 Table *luaH_new (lua_State *L, int narray, int lnhash) {
00346   Table *t = luaM_new(L, Table);
00347   luaC_link(L, valtogco(t), LUA_TTABLE);
00348   t->metatable = hvalue(defaultmeta(L));
00349   t->flags = cast(lu_byte, ~0);
00350   
00351   t->array = NULL;
00352   t->sizearray = 0;
00353   t->lsizenode = 0;
00354   t->node = NULL;
00355   setarrayvector(L, t, narray);
00356   setnodevector(L, t, lnhash);
00357   return t;
00358 }
00359 
00360 
00361 void luaH_free (lua_State *L, Table *t) {
00362   if (t->lsizenode)
00363     luaM_freearray(L, t->node, sizenode(t), Node);
00364   luaM_freearray(L, t->array, t->sizearray, TObject);
00365   luaM_freelem(L, t);
00366 }
00367 
00368 
00369 #if 0
00370 
00371 
00372 
00373 
00374 void luaH_remove (Table *t, Node *e) {
00375   Node *mp = luaH_mainposition(t, gkey(e));
00376   if (e != mp) {  
00377     while (mp->next != e) mp = mp->next;  
00378     mp->next = e->next;  
00379   }
00380   else {
00381     if (e->next != NULL) ??
00382   }
00383   lua_assert(ttisnil(gval(node)));
00384   setnilvalue(gkey(e));  
00385   e->next = NULL;
00386 }
00387 #endif
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 static TObject *newkey (lua_State *L, Table *t, const TObject *key)
00398         
00399 {
00400   TObject *val;
00401   Node *mp = luaH_mainposition(t, key);
00402   if (!ttisnil(gval(mp))) {  
00403     Node *othern = luaH_mainposition(t, gkey(mp));  
00404     Node *n = t->firstfree;  
00405     if (othern != mp) {  
00406       
00407       while (othern->next != mp) othern = othern->next;  
00408       othern->next = n;  
00409       *n = *mp;  
00410       mp->next = NULL;  
00411       setnilvalue(gval(mp));
00412     }
00413     else {  
00414       
00415       n->next = mp->next;  
00416       mp->next = n;
00417       mp = n;
00418     }
00419   }
00420   setobj2t(gkey(mp), key);  
00421   lua_assert(ttisnil(gval(mp)));
00422   for (;;) {  
00423     if (ttisnil(gkey(t->firstfree)))
00424       return gval(mp);  
00425     else if (t->firstfree == t->node) break;  
00426     else (t->firstfree)--;
00427   }
00428   
00429   setbvalue(gval(mp), 0);  
00430   rehash(L, t);  
00431   val = cast(TObject *, luaH_get(t, key));  
00432   lua_assert(ttisboolean(val));
00433   setnilvalue(val);
00434 
00435   return val;
00436 
00437 }
00438 
00439 
00440 
00441 
00442 
00443 
00444 static const TObject *luaH_getany (Table *t, const TObject *key)
00445         
00446 {
00447   if (ttisnil(key)) return &luaO_nilobject;
00448   else {
00449     Node *n = luaH_mainposition(t, key);
00450     do {  
00451       if (luaO_rawequalObj(gkey(n), key)) return gval(n);  
00452       else n = n->next;
00453     } while (n);
00454     return &luaO_nilobject;
00455   }
00456 }
00457 
00458 
00459 
00460 
00461 
00462 const TObject *luaH_getnum (Table *t, int key) {
00463   if (1 <= key && key <= t->sizearray)
00464     return &t->array[key-1];
00465   else {
00466     lua_Number nk = cast(lua_Number, key);
00467     Node *n = hashnum(t, nk);
00468     do {  
00469       if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk)
00470         return gval(n);  
00471       else n = n->next;
00472     } while (n);
00473     return &luaO_nilobject;
00474   }
00475 }
00476 
00477 
00478 
00479 
00480 
00481 const TObject *luaH_getstr (Table *t, TString *key) {
00482   Node *n = hashstr(t, key);
00483   do {  
00484     if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key)
00485       return gval(n);  
00486     else n = n->next;
00487   } while (n);
00488   return &luaO_nilobject;
00489 }
00490 
00491 
00492 
00493 
00494 
00495 const TObject *luaH_get (Table *t, const TObject *key) {
00496   switch (ttype(key)) {
00497     case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
00498     case LUA_TNUMBER: {
00499       int k;
00500       lua_number2int(k, (nvalue(key)));
00501       if (cast(lua_Number, k) == nvalue(key))  
00502         return luaH_getnum(t, k);  
00503       
00504     }
00505     default: return luaH_getany(t, key);
00506   }
00507 }
00508 
00509 
00510 TObject *luaH_set (lua_State *L, Table *t, const TObject *key) {
00511   const TObject *p = luaH_get(t, key);
00512   t->flags = 0;
00513   if (p != &luaO_nilobject)
00514 
00515     return cast(TObject *, p);
00516 
00517   else {
00518     if (ttisnil(key)) luaG_runerror(L, "table index is nil");
00519     else if (ttisnumber(key) && nvalue(key) != nvalue(key))
00520       luaG_runerror(L, "table index is NaN");
00521     return newkey(L, t, key);
00522   }
00523 }
00524 
00525 
00526 TObject *luaH_setnum (lua_State *L, Table *t, int key) {
00527   const TObject *p = luaH_getnum(t, key);
00528   if (p != &luaO_nilobject)
00529 
00530     return cast(TObject *, p);
00531 
00532   else {
00533     TObject k;
00534     setnvalue(&k, cast(lua_Number, key));
00535     return newkey(L, t, &k);
00536   }
00537 }
00538