diff options
Diffstat (limited to 'ltable.c')
-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 | ||