diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-01-10 16:56:11 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-01-10 16:56:11 -0200 |
| commit | dabb19fc17acee55f9052c5d17ec07360cec809d (patch) | |
| tree | 76983221f936eee7e681559093b3b23f8968e711 /ltable.c | |
| parent | 08496eea8b277d37c4de9cf75a011715ad6a4100 (diff) | |
| download | lua-dabb19fc17acee55f9052c5d17ec07360cec809d.tar.gz lua-dabb19fc17acee55f9052c5d17ec07360cec809d.tar.bz2 lua-dabb19fc17acee55f9052c5d17ec07360cec809d.zip | |
specialized versions for luaH_set (numbers and strings)
Diffstat (limited to 'ltable.c')
| -rw-r--r-- | ltable.c | 128 |
1 files changed, 71 insertions, 57 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 1.61 2000/12/22 16:57:46 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.62 2000/12/28 12:55:41 roberto Exp roberto $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -23,7 +23,6 @@ | |||
| 23 | #include "lmem.h" | 23 | #include "lmem.h" |
| 24 | #include "lobject.h" | 24 | #include "lobject.h" |
| 25 | #include "lstate.h" | 25 | #include "lstate.h" |
| 26 | #include "lstring.h" | ||
| 27 | #include "ltable.h" | 26 | #include "ltable.h" |
| 28 | 27 | ||
| 29 | 28 | ||
| @@ -31,6 +30,9 @@ | |||
| 31 | #define TagDefault LUA_TTABLE | 30 | #define TagDefault LUA_TTABLE |
| 32 | 31 | ||
| 33 | 32 | ||
| 33 | #define hashnum(t,n) (&t->node[(luint32)(lint32)(n)&(t->size-1)]) | ||
| 34 | #define hashstr(t,str) (&t->node[(str)->u.s.hash&(t->size-1)]) | ||
| 35 | |||
| 34 | 36 | ||
| 35 | /* | 37 | /* |
| 36 | ** returns the `main' position of an element in a table (that is, the index | 38 | ** returns the `main' position of an element in a table (that is, the index |
| @@ -40,11 +42,9 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) { | |||
| 40 | luint32 h; | 42 | luint32 h; |
| 41 | switch (ttype(key)) { | 43 | switch (ttype(key)) { |
| 42 | case LUA_TNUMBER: | 44 | case LUA_TNUMBER: |
| 43 | h = (luint32)(lint32)nvalue(key); | 45 | return hashnum(t, nvalue(key)); |
| 44 | break; | ||
| 45 | case LUA_TSTRING: | 46 | case LUA_TSTRING: |
| 46 | h = tsvalue(key)->u.s.hash; | 47 | return hashstr(t, tsvalue(key)); |
| 47 | break; | ||
| 48 | case LUA_TUSERDATA: | 48 | case LUA_TUSERDATA: |
| 49 | h = IntPoint(tsvalue(key)); | 49 | h = IntPoint(tsvalue(key)); |
| 50 | break; | 50 | break; |
| @@ -57,31 +57,26 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) { | |||
| 57 | default: | 57 | default: |
| 58 | return NULL; /* invalid key */ | 58 | return NULL; /* invalid key */ |
| 59 | } | 59 | } |
| 60 | LUA_ASSERT(h%(unsigned int)t->size == (h&((unsigned int)t->size-1)), | ||
| 61 | "a&(x-1) == a%x, for x power of 2"); | ||
| 62 | return &t->node[h&(t->size-1)]; | 60 | return &t->node[h&(t->size-1)]; |
| 63 | } | 61 | } |
| 64 | 62 | ||
| 65 | 63 | ||
| 66 | static const TObject *luaH_getany (lua_State *L, const Hash *t, | 64 | static const TObject *luaH_getany (const Hash *t, const TObject *key) { |
| 67 | const TObject *key) { | ||
| 68 | Node *n = luaH_mainposition(t, key); | 65 | Node *n = luaH_mainposition(t, key); |
| 69 | if (!n) | 66 | while (n) { |
| 70 | lua_error(L, "table index is nil"); | ||
| 71 | else do { | ||
| 72 | if (luaO_equalObj(key, &n->key)) | 67 | if (luaO_equalObj(key, &n->key)) |
| 73 | return &n->val; | 68 | return &n->val; |
| 74 | n = n->next; | 69 | n = n->next; |
| 75 | } while (n); | 70 | } |
| 76 | return &luaO_nilobject; /* key not found */ | 71 | return &luaO_nilobject; /* key not found */ |
| 77 | } | 72 | } |
| 78 | 73 | ||
| 79 | 74 | ||
| 80 | /* specialized version for numbers */ | 75 | /* specialized version for numbers */ |
| 81 | const TObject *luaH_getnum (const Hash *t, lua_Number key) { | 76 | const TObject *luaH_getnum (const Hash *t, lua_Number key) { |
| 82 | Node *n = &t->node[(luint32)(lint32)key&(t->size-1)]; | 77 | Node *n = hashnum(t, key); |
| 83 | do { | 78 | do { |
| 84 | if (ttype(&n->key) == LUA_TNUMBER && nvalue(&n->key) == key) | 79 | if (nvalue(&n->key) == key && ttype(&n->key) == LUA_TNUMBER) |
| 85 | return &n->val; | 80 | return &n->val; |
| 86 | n = n->next; | 81 | n = n->next; |
| 87 | } while (n); | 82 | } while (n); |
| @@ -91,9 +86,9 @@ const TObject *luaH_getnum (const Hash *t, lua_Number key) { | |||
| 91 | 86 | ||
| 92 | /* specialized version for strings */ | 87 | /* specialized version for strings */ |
| 93 | const TObject *luaH_getstr (const Hash *t, TString *key) { | 88 | const TObject *luaH_getstr (const Hash *t, TString *key) { |
| 94 | Node *n = &t->node[key->u.s.hash&(t->size-1)]; | 89 | Node *n = hashstr(t, key); |
| 95 | do { | 90 | do { |
| 96 | if (ttype(&n->key) == LUA_TSTRING && tsvalue(&n->key) == key) | 91 | if (tsvalue(&n->key) == key && ttype(&n->key) == LUA_TSTRING) |
| 97 | return &n->val; | 92 | return &n->val; |
| 98 | n = n->next; | 93 | n = n->next; |
| 99 | } while (n); | 94 | } while (n); |
| @@ -101,11 +96,11 @@ const TObject *luaH_getstr (const Hash *t, TString *key) { | |||
| 101 | } | 96 | } |
| 102 | 97 | ||
| 103 | 98 | ||
| 104 | const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) { | 99 | const TObject *luaH_get (const Hash *t, const TObject *key) { |
| 105 | switch (ttype(key)) { | 100 | switch (ttype(key)) { |
| 106 | case LUA_TNUMBER: return luaH_getnum(t, nvalue(key)); | 101 | case LUA_TNUMBER: return luaH_getnum(t, nvalue(key)); |
| 107 | case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); | 102 | case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); |
| 108 | default: return luaH_getany(L, t, key); | 103 | default: return luaH_getany(t, key); |
| 109 | } | 104 | } |
| 110 | } | 105 | } |
| 111 | 106 | ||
| @@ -115,7 +110,7 @@ Node *luaH_next (lua_State *L, const Hash *t, const TObject *key) { | |||
| 115 | if (ttype(key) == LUA_TNIL) | 110 | if (ttype(key) == LUA_TNIL) |
| 116 | i = 0; /* first iteration */ | 111 | i = 0; /* first iteration */ |
| 117 | else { | 112 | else { |
| 118 | const TObject *v = luaH_get(L, t, key); | 113 | const TObject *v = luaH_get(t, key); |
| 119 | if (v == &luaO_nilobject) | 114 | if (v == &luaO_nilobject) |
| 120 | lua_error(L, "invalid key for `next'"); | 115 | lua_error(L, "invalid key for `next'"); |
| 121 | i = (int)(((const char *)v - | 116 | i = (int)(((const char *)v - |
| @@ -224,30 +219,17 @@ static void rehash (lua_State *L, Hash *t) { | |||
| 224 | 219 | ||
| 225 | 220 | ||
| 226 | /* | 221 | /* |
| 227 | ** inserts a key into a hash table; first, check whether key is | 222 | ** inserts a new key into a hash table; first, check whether key's main |
| 228 | ** already present; if not, check whether key's main position is free; | 223 | ** position is free; if not, check whether colliding node is in its main |
| 229 | ** if not, check whether colliding node is in its main position or not; | 224 | ** position or not; if it is not, move colliding node to an empty place and |
| 230 | ** if it is not, move colliding node to an empty place and put new key | 225 | ** put new key in its main position; otherwise (colliding node is in its main |
| 231 | ** in its main position; otherwise (colliding node is in its main position), | 226 | ** position), new key goes to an empty position. |
| 232 | ** new key goes to an empty position. | ||
| 233 | */ | 227 | */ |
| 234 | TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { | 228 | static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) { |
| 235 | Node *mp = luaH_mainposition(t, key); | ||
| 236 | Node *n = mp; | ||
| 237 | if (!mp) | ||
| 238 | lua_error(L, "table index is nil"); | ||
| 239 | do { /* check whether `key' is somewhere in the chain */ | ||
| 240 | if (luaO_equalObj(key, &n->key)) | ||
| 241 | return &n->val; /* that's all */ | ||
| 242 | else n = n->next; | ||
| 243 | } while (n); | ||
| 244 | /* `key' not found; must insert it */ | ||
| 245 | if (ttype(&mp->key) != LUA_TNIL) { /* main position is not free? */ | 229 | if (ttype(&mp->key) != LUA_TNIL) { /* main position is not free? */ |
| 246 | Node *othern; /* main position of colliding node */ | 230 | Node *othern = luaH_mainposition(t, &mp->key); /* `mp' of colliding node */ |
| 247 | n = t->firstfree; /* get a free place */ | 231 | Node *n = t->firstfree; /* get a free place */ |
| 248 | /* is colliding node out of its main position? (can only happens if | 232 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 249 | its position is after "firstfree") */ | ||
| 250 | if (mp > n && (othern=luaH_mainposition(t, &mp->key)) != mp) { | ||
| 251 | /* yes; move colliding node into free position */ | 233 | /* yes; move colliding node into free position */ |
| 252 | while (othern->next != mp) othern = othern->next; /* find previous */ | 234 | while (othern->next != mp) othern = othern->next; /* find previous */ |
| 253 | othern->next = n; /* redo the chain with `n' in place of `mp' */ | 235 | othern->next = n; /* redo the chain with `n' in place of `mp' */ |
| @@ -273,25 +255,57 @@ TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { | |||
| 273 | } | 255 | } |
| 274 | 256 | ||
| 275 | 257 | ||
| 276 | TObject *luaH_setint (lua_State *L, Hash *t, int key) { | 258 | static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) { |
| 277 | TObject index; | 259 | Node *mp = luaH_mainposition(t, key); |
| 278 | ttype(&index) = LUA_TNUMBER; | 260 | Node *n = mp; |
| 279 | nvalue(&index) = key; | 261 | if (!mp) |
| 280 | return luaH_set(L, t, &index); | 262 | lua_error(L, "table index is nil"); |
| 263 | do { /* check whether `key' is somewhere in the chain */ | ||
| 264 | if (luaO_equalObj(key, &n->key)) | ||
| 265 | return &n->val; /* that's all */ | ||
| 266 | else n = n->next; | ||
| 267 | } while (n); | ||
| 268 | return newkey(L, t, mp, key); /* `key' not found; must insert it */ | ||
| 269 | } | ||
| 270 | |||
| 271 | |||
| 272 | TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key) { | ||
| 273 | TObject kobj; | ||
| 274 | Node *mp = hashnum(t, key); | ||
| 275 | Node *n = mp; | ||
| 276 | do { /* check whether `key' is somewhere in the chain */ | ||
| 277 | if (nvalue(&n->key) == key && ttype(&n->key) == LUA_TNUMBER) | ||
| 278 | return &n->val; /* that's all */ | ||
| 279 | else n = n->next; | ||
| 280 | } while (n); | ||
| 281 | /* `key' not found; must insert it */ | ||
| 282 | ttype(&kobj) = LUA_TNUMBER; | ||
| 283 | nvalue(&kobj) = key; | ||
| 284 | return newkey(L, t, mp, &kobj); | ||
| 281 | } | 285 | } |
| 282 | 286 | ||
| 283 | 287 | ||
| 284 | void luaH_setstrnum (lua_State *L, Hash *t, TString *key, lua_Number val) { | 288 | TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) { |
| 285 | TObject *value, index; | 289 | TObject kobj; |
| 286 | ttype(&index) = LUA_TSTRING; | 290 | Node *mp = hashstr(t, key); |
| 287 | tsvalue(&index) = key; | 291 | Node *n = mp; |
| 288 | value = luaH_set(L, t, &index); | 292 | do { /* check whether `key' is somewhere in the chain */ |
| 289 | ttype(value) = LUA_TNUMBER; | 293 | if (tsvalue(&n->key) == key && ttype(&n->key) == LUA_TSTRING) |
| 290 | nvalue(value) = val; | 294 | return &n->val; /* that's all */ |
| 295 | else n = n->next; | ||
| 296 | } while (n); | ||
| 297 | /* `key' not found; must insert it */ | ||
| 298 | ttype(&kobj) = LUA_TSTRING; | ||
| 299 | tsvalue(&kobj) = key; | ||
| 300 | return newkey(L, t, mp, &kobj); | ||
| 291 | } | 301 | } |
| 292 | 302 | ||
| 293 | 303 | ||
| 294 | const TObject *luaH_getglobal (lua_State *L, const char *name) { | 304 | TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { |
| 295 | return luaH_getstr(L->gt, luaS_new(L, name)); | 305 | switch (ttype(key)) { |
| 306 | case LUA_TNUMBER: return luaH_setnum(L, t, nvalue(key)); | ||
| 307 | case LUA_TSTRING: return luaH_setstr(L, t, tsvalue(key)); | ||
| 308 | default: return luaH_setany(L, t, key); | ||
| 309 | } | ||
| 296 | } | 310 | } |
| 297 | 311 | ||
