diff options
Diffstat (limited to '')
| -rw-r--r-- | ltable.c | 342 |
1 files changed, 245 insertions, 97 deletions
| @@ -1,13 +1,17 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 1.83 2001/07/05 20:31:14 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.86 2001/09/07 17:30:16 roberto Exp $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | /* | 8 | /* |
| 9 | ** Implementation of tables (aka arrays, objects, or hash tables); | 9 | ** Implementation of tables (aka arrays, objects, or hash tables). |
| 10 | ** uses a mix of chained scatter table with Brent's variation. | 10 | ** Tables keep its elements in two parts: an array part and a hash part. |
| 11 | ** Non-negative integer keys are all candidates to be kept in the array | ||
| 12 | ** part. The actual size of the array is the largest `n' such that at | ||
| 13 | ** least half the slots between 0 and n are in use. | ||
| 14 | ** Hash uses a mix of chained scatter table with Brent's variation. | ||
| 11 | ** A main invariant of these tables is that, if an element is not | 15 | ** A main invariant of these tables is that, if an element is not |
| 12 | ** in its main position (i.e. the `original' position that its hash gives | 16 | ** in its main position (i.e. the `original' position that its hash gives |
| 13 | ** to it), then the colliding element is in its own main position. | 17 | ** to it), then the colliding element is in its own main position. |
| @@ -18,6 +22,7 @@ | |||
| 18 | */ | 22 | */ |
| 19 | 23 | ||
| 20 | 24 | ||
| 25 | |||
| 21 | #define LUA_PRIVATE | 26 | #define LUA_PRIVATE |
| 22 | #include "lua.h" | 27 | #include "lua.h" |
| 23 | 28 | ||
| @@ -28,20 +33,34 @@ | |||
| 28 | #include "ltable.h" | 33 | #include "ltable.h" |
| 29 | 34 | ||
| 30 | 35 | ||
| 36 | /* | ||
| 37 | ** max size of array part is 2^MAXBITS | ||
| 38 | */ | ||
| 39 | #if BITS_INT > 24 | ||
| 40 | #define MAXBITS 24 | ||
| 41 | #else | ||
| 42 | #define MAXBITS (BITS_INT-1) | ||
| 43 | #endif | ||
| 44 | |||
| 45 | /* check whether `x' < 2^MAXBITS */ | ||
| 46 | #define toobig(x) ((((x)-1) >> MAXBITS) != 0) | ||
| 47 | |||
| 48 | |||
| 31 | 49 | ||
| 32 | #define TagDefault LUA_TTABLE | 50 | #define TagDefault LUA_TTABLE |
| 33 | 51 | ||
| 34 | 52 | ||
| 35 | #define hashnum(t,n) (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), t->size))) | 53 | #define hashnum(t,n) \ |
| 36 | #define hashstr(t,str) (node(t, lmod((str)->tsv.hash, t->size))) | 54 | (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t)))) |
| 37 | #define hashpointer(t,p) (node(t, lmod(IntPoint(p), t->size))) | 55 | #define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t)))) |
| 56 | #define hashpointer(t,p) (node(t, lmod(IntPoint(p), sizenode(t)))) | ||
| 38 | 57 | ||
| 39 | 58 | ||
| 40 | /* | 59 | /* |
| 41 | ** returns the `main' position of an element in a table (that is, the index | 60 | ** returns the `main' position of an element in a table (that is, the index |
| 42 | ** of its hash value) | 61 | ** of its hash value) |
| 43 | */ | 62 | */ |
| 44 | Node *luaH_mainposition (const Hash *t, const TObject *key) { | 63 | Node *luaH_mainposition (const Table *t, const TObject *key) { |
| 45 | switch (ttype(key)) { | 64 | switch (ttype(key)) { |
| 46 | case LUA_TNUMBER: | 65 | case LUA_TNUMBER: |
| 47 | return hashnum(t, nvalue(key)); | 66 | return hashnum(t, nvalue(key)); |
| @@ -53,119 +72,237 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) { | |||
| 53 | } | 72 | } |
| 54 | 73 | ||
| 55 | 74 | ||
| 56 | Node *luaH_next (lua_State *L, Hash *t, const TObject *key) { | 75 | /* |
| 76 | ** returns the index for `key' if `key' is an appropriate key to live in | ||
| 77 | ** the array part of the table, -1 otherwise. | ||
| 78 | */ | ||
| 79 | static int arrayindex (const TObject *key) { | ||
| 80 | if (ttype(key) == LUA_TNUMBER) { | ||
| 81 | int k = cast(int, nvalue(key)); | ||
| 82 | if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k)) | ||
| 83 | return k; | ||
| 84 | } | ||
| 85 | return -1; /* `key' did not match some condition */ | ||
| 86 | } | ||
| 87 | |||
| 88 | |||
| 89 | /* | ||
| 90 | ** returns the index of a `key' for table traversals. First goes all | ||
| 91 | ** elements in the array part, then elements in the hash part. The | ||
| 92 | ** beginning and end of a traversal are signalled by -1. | ||
| 93 | */ | ||
| 94 | int luaH_index (lua_State *L, Table *t, const TObject *key) { | ||
| 57 | int i; | 95 | int i; |
| 58 | if (ttype(key) == LUA_TNIL) | 96 | if (ttype(key) == LUA_TNIL) return -1; /* first iteration */ |
| 59 | i = 0; /* first iteration */ | 97 | i = arrayindex(key); |
| 98 | if (0 <= i && i < t->sizearray) { /* is `key' inside array part? */ | ||
| 99 | return i; /* yes; that's the index */ | ||
| 100 | } | ||
| 60 | else { | 101 | else { |
| 61 | const TObject *v = luaH_get(t, key); | 102 | const TObject *v = luaH_get(t, key); |
| 62 | if (v == &luaO_nilobject) | 103 | if (v == &luaO_nilobject) |
| 63 | luaD_error(L, l_s("invalid key for `next'")); | 104 | luaD_error(L, l_s("invalid key for `next'")); |
| 64 | i = cast(int, (cast(const lu_byte *, v) - | 105 | i = cast(int, (cast(const lu_byte *, v) - |
| 65 | cast(const lu_byte *, val(node(t, 0)))) / sizeof(Node)) + 1; | 106 | cast(const lu_byte *, val(node(t, 0)))) / sizeof(Node)); |
| 66 | } | 107 | return i + t->sizearray; /* hash elements are numbered after array ones */ |
| 67 | for (; i<t->size; i++) { | ||
| 68 | Node *n = node(t, i); | ||
| 69 | if (ttype(val(n)) != LUA_TNIL) | ||
| 70 | return n; | ||
| 71 | } | 108 | } |
| 72 | return NULL; /* no more elements */ | ||
| 73 | } | 109 | } |
| 74 | 110 | ||
| 75 | 111 | ||
| 76 | int luaH_nexti (Hash *t, int i) { | 112 | int luaH_nexti (Table *t, int i, TObject *where) { |
| 77 | while ((++i)<t->size) { | 113 | for (i++; i < t->sizearray; i++) { /* try first array part */ |
| 78 | if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */ | 114 | if (ttype(&t->array[i]) != LUA_TNIL) { /* a non-nil value? */ |
| 115 | setnvalue(where, i+1); | ||
| 116 | setobj(where+1, &t->array[i]); | ||
| 79 | return i; | 117 | return i; |
| 118 | } | ||
| 119 | } | ||
| 120 | for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ | ||
| 121 | if (ttype(val(node(t, i))) != LUA_TNIL) { /* a non-nil value? */ | ||
| 122 | setobj(where, key(node(t, i))); | ||
| 123 | setobj(where+1, val(node(t, i))); | ||
| 124 | return i + t->sizearray; | ||
| 125 | } | ||
| 80 | } | 126 | } |
| 81 | return -1; /* no more elements */ | 127 | return -1; /* no more elements */ |
| 82 | } | 128 | } |
| 83 | 129 | ||
| 84 | 130 | ||
| 85 | #define check_grow(L, p, n) \ | ||
| 86 | if ((p) >= MAX_INT/(n)) luaD_error(L, l_s("table overflow")); | ||
| 87 | |||
| 88 | /* | 131 | /* |
| 89 | ** returns smaller power of 2 larger than `n' (minimum is MINPOWER2) | 132 | ** {============================================================= |
| 133 | ** Rehash | ||
| 134 | ** ============================================================== | ||
| 90 | */ | 135 | */ |
| 91 | static int power2 (lua_State *L, int n) { | 136 | |
| 92 | int p = MINPOWER2; | 137 | |
| 93 | while (p <= n) { | 138 | static void computesizes (int nums[], int ntotal, int *narray, int *nhash) { |
| 94 | check_grow(L, p, 2); | 139 | int n = 0; /* optimal (log of) size for array part */ |
| 95 | p *= 2; | 140 | int na = 0; /* number of elements to go to array part */ |
| 141 | int a = nums[0]; /* accumulator */ | ||
| 142 | int i; | ||
| 143 | for (i=1; i<=MAXBITS; i++) { | ||
| 144 | if (nums[i] == 0) continue; /* ignore empty slices */ | ||
| 145 | a += nums[i]; /* number of elements smaller than 2^i */ | ||
| 146 | if (a >= (1<<(i-1))) { /* more than half elements in use? */ | ||
| 147 | n = i; | ||
| 148 | na = a; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | *nhash = ntotal - na; | ||
| 152 | *narray = (n == 0) ? 0 : (1<<n); | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | static void numuse (const Table *t, int *narray, int *nhash) { | ||
| 157 | int nums[MAXBITS+1]; | ||
| 158 | int i; | ||
| 159 | int totaluse = 0; | ||
| 160 | for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* init `nums' */ | ||
| 161 | /* count elements in array part */ | ||
| 162 | i = luaO_log2(t->sizearray) + 1; /* number of `slices' */ | ||
| 163 | while (i--) { /* for each slice [2^(i-1) to 2^i) */ | ||
| 164 | int to = twoto(i); | ||
| 165 | int from = to/2; | ||
| 166 | if (to > t->sizearray) to = t->sizearray; | ||
| 167 | for (; from < to; from++) | ||
| 168 | if (ttype(&t->array[from]) != LUA_TNIL) { | ||
| 169 | nums[i]++; | ||
| 170 | totaluse++; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | /* count elements in hash part */ | ||
| 174 | i = sizenode(t); | ||
| 175 | while (i--) { | ||
| 176 | if (ttype(&t->node[i].val) != LUA_TNIL) { | ||
| 177 | int k = arrayindex(&t->node[i].key); | ||
| 178 | if (k >= 0) /* is `key' an appropriate array index? */ | ||
| 179 | nums[luaO_log2(k-1)+1]++; /* count as such */ | ||
| 180 | totaluse++; | ||
| 181 | } | ||
| 96 | } | 182 | } |
| 97 | return p; | 183 | computesizes(nums, totaluse, narray, nhash); |
| 98 | } | 184 | } |
| 99 | 185 | ||
| 100 | 186 | ||
| 101 | static void setnodevector (lua_State *L, Hash *t, int size) { | 187 | /* |
| 188 | ** (log of) minimum size for hash part of a table | ||
| 189 | */ | ||
| 190 | #define MINHASHSIZE 1 | ||
| 191 | |||
| 192 | |||
| 193 | static void setarrayvector (lua_State *L, Table *t, int size) { | ||
| 194 | int i; | ||
| 195 | if (size > twoto(MAXBITS)) | ||
| 196 | luaD_error(L, l_s("table overflow")); | ||
| 197 | luaM_reallocvector(L, t->array, t->sizearray, size, TObject); | ||
| 198 | for (i=t->sizearray; i<size; i++) | ||
| 199 | setnilvalue(&t->array[i]); | ||
| 200 | t->sizearray = size; | ||
| 201 | } | ||
| 202 | |||
| 203 | |||
| 204 | static void setnodevector (lua_State *L, Table *t, int lsize) { | ||
| 102 | int i; | 205 | int i; |
| 206 | int size; | ||
| 207 | if (lsize < MINHASHSIZE) lsize = MINHASHSIZE; | ||
| 208 | else if (lsize > MAXBITS) | ||
| 209 | luaD_error(L, l_s("table overflow")); | ||
| 210 | size = twoto(lsize); | ||
| 103 | t->node = luaM_newvector(L, size, Node); | 211 | t->node = luaM_newvector(L, size, Node); |
| 104 | for (i=0; i<size; i++) { | 212 | for (i=0; i<size; i++) { |
| 105 | t->node[i].next = NULL; | 213 | t->node[i].next = NULL; |
| 106 | setnilvalue(key(node(t, i))); | 214 | setnilvalue(key(node(t, i))); |
| 107 | setnilvalue(val(node(t, i))); | 215 | setnilvalue(val(node(t, i))); |
| 108 | } | 216 | } |
| 109 | t->size = size; | 217 | t->lsizenode = cast(lu_byte, lsize); |
| 110 | t->firstfree = node(t, size-1); /* first free position to be used */ | 218 | t->firstfree = node(t, size-1); /* first free position to be used */ |
| 111 | } | 219 | } |
| 112 | 220 | ||
| 113 | 221 | ||
| 114 | Hash *luaH_new (lua_State *L, int size) { | 222 | static void rehash (lua_State *L, Table *t) { |
| 115 | Hash *t = luaM_new(L, Hash); | 223 | int i; |
| 224 | int oldasize, oldhsize, nasize, nhsize; | ||
| 225 | Node *nold; | ||
| 226 | numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */ | ||
| 227 | oldasize = t->sizearray; | ||
| 228 | if (nasize > oldasize) /* should grow array part? */ | ||
| 229 | setarrayvector(L, t, nasize); | ||
| 230 | /* create new hash part with appropriate size */ | ||
| 231 | nold = t->node; /* save old hash ... */ | ||
| 232 | oldhsize = t->lsizenode; /* ... and (log of) old size */ | ||
| 233 | setnodevector(L, t, luaO_log2(nhsize+nhsize/4)+1); | ||
| 234 | /* re-insert elements */ | ||
| 235 | if (nasize < oldasize) { /* array part must shrink? */ | ||
| 236 | t->sizearray = nasize; | ||
| 237 | /* re-insert elements from vanishing slice */ | ||
| 238 | for (i=nasize; i<oldasize; i++) { | ||
| 239 | if (ttype(&t->array[i]) != LUA_TNIL) | ||
| 240 | luaH_setnum(L, t, i+1, &t->array[i]); | ||
| 241 | } | ||
| 242 | /* shink array */ | ||
| 243 | luaM_reallocvector(L, t->array, oldasize, nasize, TObject); | ||
| 244 | } | ||
| 245 | /* re-insert elements in hash part */ | ||
| 246 | i = twoto(oldhsize); | ||
| 247 | while (i--) { | ||
| 248 | Node *old = nold+i; | ||
| 249 | if (ttype(val(old)) != LUA_TNIL) | ||
| 250 | luaH_set(L, t, key(old), val(old)); | ||
| 251 | } | ||
| 252 | luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ | ||
| 253 | } | ||
| 254 | |||
| 255 | /* | ||
| 256 | ** }============================================================= | ||
| 257 | */ | ||
| 258 | |||
| 259 | |||
| 260 | Table *luaH_new (lua_State *L, int narray, int lnhash) { | ||
| 261 | Table *t = luaM_new(L, Table); | ||
| 116 | t->htag = TagDefault; | 262 | t->htag = TagDefault; |
| 117 | t->next = G(L)->roottable; | 263 | t->next = G(L)->roottable; |
| 118 | G(L)->roottable = t; | 264 | G(L)->roottable = t; |
| 119 | t->mark = t; | 265 | t->mark = t; |
| 120 | t->size = 0; | ||
| 121 | t->weakmode = 0; | 266 | t->weakmode = 0; |
| 267 | /* temporary values (kept only if some malloc fails) */ | ||
| 268 | t->array = NULL; | ||
| 269 | t->sizearray = 0; | ||
| 270 | t->lsizenode = 0; | ||
| 122 | t->node = NULL; | 271 | t->node = NULL; |
| 123 | setnodevector(L, t, power2(L, size)); | 272 | setarrayvector(L, t, narray); |
| 273 | setnodevector(L, t, lnhash); | ||
| 124 | return t; | 274 | return t; |
| 125 | } | 275 | } |
| 126 | 276 | ||
| 127 | 277 | ||
| 128 | void luaH_free (lua_State *L, Hash *t) { | 278 | void luaH_free (lua_State *L, Table *t) { |
| 129 | luaM_freearray(L, t->node, t->size, Node); | 279 | lua_assert(t->lsizenode > 0 || t->node == NULL); |
| 280 | if (t->lsizenode > 0) | ||
| 281 | luaM_freearray(L, t->node, sizenode(t), Node); | ||
| 282 | luaM_freearray(L, t->array, t->sizearray, TObject); | ||
| 130 | luaM_freelem(L, t); | 283 | luaM_freelem(L, t); |
| 131 | } | 284 | } |
| 132 | 285 | ||
| 133 | 286 | ||
| 134 | static int numuse (const Hash *t) { | 287 | #if 0 |
| 135 | Node *v = t->node; | 288 | /* |
| 136 | int size = t->size; | 289 | ** try to remove an element from a hash table; cannot move any element |
| 137 | int realuse = 0; | 290 | ** (because gc can call `remove' during a table traversal) |
| 138 | int i; | 291 | */ |
| 139 | for (i=0; i<size; i++) { | 292 | void luaH_remove (Table *t, Node *e) { |
| 140 | if (ttype(&v[i].val) != LUA_TNIL) | 293 | Node *mp = luaH_mainposition(t, key(e)); |
| 141 | realuse++; | 294 | if (e != mp) { /* element not in its main position? */ |
| 142 | } | 295 | while (mp->next != e) mp = mp->next; /* find previous */ |
| 143 | return realuse; | 296 | mp->next = e->next; /* remove `e' from its list */ |
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | static void rehash (lua_State *L, Hash *t) { | ||
| 148 | int oldsize = t->size; | ||
| 149 | Node *nold = t->node; | ||
| 150 | int nelems = numuse(t); | ||
| 151 | int i; | ||
| 152 | lua_assert(nelems<=oldsize); | ||
| 153 | if (nelems >= oldsize-oldsize/4) { /* using more than 3/4? */ | ||
| 154 | check_grow(L, oldsize, 2); | ||
| 155 | setnodevector(L, t, oldsize*2); /* grow array */ | ||
| 156 | } | 297 | } |
| 157 | else if (nelems <= oldsize/4 && /* less than 1/4? */ | 298 | else { |
| 158 | oldsize > MINPOWER2) | 299 | if (e->next != NULL) ?? |
| 159 | setnodevector(L, t, oldsize/2); /* shrink array */ | ||
| 160 | else | ||
| 161 | setnodevector(L, t, oldsize); /* just rehash; keep the same size */ | ||
| 162 | for (i=0; i<oldsize; i++) { | ||
| 163 | Node *old = nold+i; | ||
| 164 | if (ttype(val(old)) != LUA_TNIL) | ||
| 165 | luaH_set(L, t, key(old), val(old)); | ||
| 166 | } | 300 | } |
| 167 | luaM_freearray(L, nold, oldsize, Node); /* free old array */ | 301 | lua_assert(ttype(val(node)) == LUA_TNIL); |
| 302 | setnilvalue(key(e)); /* clear node `e' */ | ||
| 303 | e->next = NULL; | ||
| 168 | } | 304 | } |
| 305 | #endif | ||
| 169 | 306 | ||
| 170 | 307 | ||
| 171 | /* | 308 | /* |
| @@ -175,7 +312,8 @@ static void rehash (lua_State *L, Hash *t) { | |||
| 175 | ** put new key in its main position; otherwise (colliding node is in its main | 312 | ** put new key in its main position; otherwise (colliding node is in its main |
| 176 | ** position), new key goes to an empty position. | 313 | ** position), new key goes to an empty position. |
| 177 | */ | 314 | */ |
| 178 | static TObject *newkey (lua_State *L, Hash *t, const TObject *key) { | 315 | static void newkey (lua_State *L, Table *t, const TObject *key, |
| 316 | const TObject *val) { | ||
| 179 | Node *mp = luaH_mainposition(t, key); | 317 | Node *mp = luaH_mainposition(t, key); |
| 180 | if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */ | 318 | if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */ |
| 181 | Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */ | 319 | Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */ |
| @@ -197,21 +335,21 @@ static TObject *newkey (lua_State *L, Hash *t, const TObject *key) { | |||
| 197 | } | 335 | } |
| 198 | setobj(key(mp), key); | 336 | setobj(key(mp), key); |
| 199 | lua_assert(ttype(val(mp)) == LUA_TNIL); | 337 | lua_assert(ttype(val(mp)) == LUA_TNIL); |
| 338 | settableval(val(mp), val); | ||
| 200 | for (;;) { /* correct `firstfree' */ | 339 | for (;;) { /* correct `firstfree' */ |
| 201 | if (ttype(key(t->firstfree)) == LUA_TNIL) | 340 | if (ttype(key(t->firstfree)) == LUA_TNIL) |
| 202 | return val(mp); /* OK; table still has a free place */ | 341 | return; /* OK; table still has a free place */ |
| 203 | else if (t->firstfree == t->node) break; /* cannot decrement from here */ | 342 | else if (t->firstfree == t->node) break; /* cannot decrement from here */ |
| 204 | else (t->firstfree)--; | 343 | else (t->firstfree)--; |
| 205 | } | 344 | } |
| 206 | rehash(L, t); /* no more free places */ | 345 | rehash(L, t); /* no more free places; must create one */ |
| 207 | return newkey(L, t, key); /* `rehash' invalidates this insertion */ | ||
| 208 | } | 346 | } |
| 209 | 347 | ||
| 210 | 348 | ||
| 211 | /* | 349 | /* |
| 212 | ** generic search function | 350 | ** generic search function |
| 213 | */ | 351 | */ |
| 214 | static const TObject *luaH_getany (Hash *t, const TObject *key) { | 352 | static const TObject *luaH_getany (Table *t, const TObject *key) { |
| 215 | if (ttype(key) == LUA_TNIL) return &luaO_nilobject; | 353 | if (ttype(key) == LUA_TNIL) return &luaO_nilobject; |
| 216 | else { | 354 | else { |
| 217 | Node *n = luaH_mainposition(t, key); | 355 | Node *n = luaH_mainposition(t, key); |
| @@ -227,21 +365,25 @@ static const TObject *luaH_getany (Hash *t, const TObject *key) { | |||
| 227 | /* | 365 | /* |
| 228 | ** search function for integers | 366 | ** search function for integers |
| 229 | */ | 367 | */ |
| 230 | const TObject *luaH_getnum (Hash *t, int key) { | 368 | const TObject *luaH_getnum (Table *t, int key) { |
| 231 | Node *n = hashnum(t, key); | 369 | if (1 <= key && key <= t->sizearray) |
| 232 | do { /* check whether `key' is somewhere in the chain */ | 370 | return &t->array[key-1]; |
| 233 | if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key) | 371 | else { |
| 234 | return val(n); /* that's it */ | 372 | Node *n = hashnum(t, key); |
| 235 | else n = n->next; | 373 | do { /* check whether `key' is somewhere in the chain */ |
| 236 | } while (n); | 374 | if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key) |
| 237 | return &luaO_nilobject; | 375 | return val(n); /* that's it */ |
| 376 | else n = n->next; | ||
| 377 | } while (n); | ||
| 378 | return &luaO_nilobject; | ||
| 379 | } | ||
| 238 | } | 380 | } |
| 239 | 381 | ||
| 240 | 382 | ||
| 241 | /* | 383 | /* |
| 242 | ** search function for strings | 384 | ** search function for strings |
| 243 | */ | 385 | */ |
| 244 | const TObject *luaH_getstr (Hash *t, TString *key) { | 386 | const TObject *luaH_getstr (Table *t, TString *key) { |
| 245 | Node *n = hashstr(t, key); | 387 | Node *n = hashstr(t, key); |
| 246 | do { /* check whether `key' is somewhere in the chain */ | 388 | do { /* check whether `key' is somewhere in the chain */ |
| 247 | if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key) | 389 | if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key) |
| @@ -255,7 +397,7 @@ const TObject *luaH_getstr (Hash *t, TString *key) { | |||
| 255 | /* | 397 | /* |
| 256 | ** main search function | 398 | ** main search function |
| 257 | */ | 399 | */ |
| 258 | const TObject *luaH_get (Hash *t, const TObject *key) { | 400 | const TObject *luaH_get (Table *t, const TObject *key) { |
| 259 | switch (ttype(key)) { | 401 | switch (ttype(key)) { |
| 260 | case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); | 402 | case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); |
| 261 | case LUA_TNUMBER: { | 403 | case LUA_TNUMBER: { |
| @@ -269,34 +411,40 @@ const TObject *luaH_get (Hash *t, const TObject *key) { | |||
| 269 | } | 411 | } |
| 270 | 412 | ||
| 271 | 413 | ||
| 272 | void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val) { | 414 | void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val) { |
| 273 | const TObject *p = luaH_get(t, key); | 415 | const TObject *p = luaH_get(t, key); |
| 274 | if (p == &luaO_nilobject) { | 416 | if (p != &luaO_nilobject) { |
| 417 | settableval(p, val); | ||
| 418 | } | ||
| 419 | else { | ||
| 275 | if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil")); | 420 | if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil")); |
| 276 | p = newkey(L, t, key); | 421 | newkey(L, t, key, val); |
| 277 | } | 422 | } |
| 278 | settableval(p, val); | ||
| 279 | } | 423 | } |
| 280 | 424 | ||
| 281 | 425 | ||
| 282 | void luaH_setstr (lua_State *L, Hash *t, TString *key, const TObject *val) { | 426 | void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val) { |
| 283 | const TObject *p = luaH_getstr(t, key); | 427 | const TObject *p = luaH_getstr(t, key); |
| 284 | if (p == &luaO_nilobject) { | 428 | if (p != &luaO_nilobject) { |
| 429 | settableval(p, val); | ||
| 430 | } | ||
| 431 | else { | ||
| 285 | TObject k; | 432 | TObject k; |
| 286 | setsvalue(&k, key); | 433 | setsvalue(&k, key); |
| 287 | p = newkey(L, t, &k); | 434 | newkey(L, t, &k, val); |
| 288 | } | 435 | } |
| 289 | settableval(p, val); | ||
| 290 | } | 436 | } |
| 291 | 437 | ||
| 292 | 438 | ||
| 293 | void luaH_setnum (lua_State *L, Hash *t, int key, const TObject *val) { | 439 | void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val) { |
| 294 | const TObject *p = luaH_getnum(t, key); | 440 | const TObject *p = luaH_getnum(t, key); |
| 295 | if (p == &luaO_nilobject) { | 441 | if (p != &luaO_nilobject) { |
| 442 | settableval(p, val); | ||
| 443 | } | ||
| 444 | else { | ||
| 296 | TObject k; | 445 | TObject k; |
| 297 | setnvalue(&k, key); | 446 | setnvalue(&k, key); |
| 298 | p = newkey(L, t, &k); | 447 | newkey(L, t, &k, val); |
| 299 | } | 448 | } |
| 300 | settableval(p, val); | ||
| 301 | } | 449 | } |
| 302 | 450 | ||
