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