diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-23 10:16:18 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-23 10:16:18 -0300 |
| commit | 9243c414d92c253edd908f438caa31e2aa16f3f4 (patch) | |
| tree | e8959a48f4672037aef061cc6eb82bba21d0766b /ltable.c | |
| parent | 477ca2fe8ceaf79038972977915987adbef0e425 (diff) | |
| download | lua-9243c414d92c253edd908f438caa31e2aa16f3f4.tar.gz lua-9243c414d92c253edd908f438caa31e2aa16f3f4.tar.bz2 lua-9243c414d92c253edd908f438caa31e2aa16f3f4.zip | |
first version of empty entries in tables
(so that, in the future, tables can contain regular nil entries)
Diffstat (limited to 'ltable.c')
| -rw-r--r-- | ltable.c | 63 |
1 files changed, 33 insertions, 30 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 2.132 2018/02/19 20:06:56 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.133 2018/02/21 12:54:26 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 | */ |
| @@ -88,11 +88,14 @@ | |||
| 88 | #define dummynode (&dummynode_) | 88 | #define dummynode (&dummynode_) |
| 89 | 89 | ||
| 90 | static const Node dummynode_ = { | 90 | static const Node dummynode_ = { |
| 91 | {{NULL}, LUA_TNIL, /* value's value and type */ | 91 | {{NULL}, LUA_TEMPTY, /* value's value and type */ |
| 92 | LUA_TNIL, 0, {NULL}} /* key type, next, and key value */ | 92 | LUA_TNIL, 0, {NULL}} /* key type, next, and key value */ |
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | 95 | ||
| 96 | LUAI_DDEF const TValue luaH_emptyobject_ = {EMPTYCONSTANT}; | ||
| 97 | |||
| 98 | |||
| 96 | /* | 99 | /* |
| 97 | ** Hash for floating-point numbers. | 100 | ** Hash for floating-point numbers. |
| 98 | ** The main computation should be just | 101 | ** The main computation should be just |
| @@ -200,7 +203,7 @@ static const TValue *getgeneric (Table *t, const TValue *key) { | |||
| 200 | else { | 203 | else { |
| 201 | int nx = gnext(n); | 204 | int nx = gnext(n); |
| 202 | if (nx == 0) | 205 | if (nx == 0) |
| 203 | return luaO_nilobject; /* not found */ | 206 | return luaH_emptyobject; /* not found */ |
| 204 | n += nx; | 207 | n += nx; |
| 205 | } | 208 | } |
| 206 | } | 209 | } |
| @@ -232,7 +235,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) { | |||
| 232 | return i; /* yes; that's the index */ | 235 | return i; /* yes; that's the index */ |
| 233 | else { | 236 | else { |
| 234 | const TValue *n = getgeneric(t, key); | 237 | const TValue *n = getgeneric(t, key); |
| 235 | if (n == luaO_nilobject) | 238 | if (n == luaH_emptyobject) |
| 236 | luaG_runerror(L, "invalid key to 'next'"); /* key not found */ | 239 | luaG_runerror(L, "invalid key to 'next'"); /* key not found */ |
| 237 | i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ | 240 | i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ |
| 238 | /* hash elements are numbered after array ones */ | 241 | /* hash elements are numbered after array ones */ |
| @@ -244,14 +247,14 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) { | |||
| 244 | int luaH_next (lua_State *L, Table *t, StkId key) { | 247 | int luaH_next (lua_State *L, Table *t, StkId key) { |
| 245 | unsigned int i = findindex(L, t, s2v(key)); /* find original element */ | 248 | unsigned int i = findindex(L, t, s2v(key)); /* find original element */ |
| 246 | for (; i < t->sizearray; i++) { /* try first array part */ | 249 | for (; i < t->sizearray; i++) { /* try first array part */ |
| 247 | if (!ttisnil(&t->array[i])) { /* a non-nil value? */ | 250 | if (!isempty(&t->array[i])) { /* a non-empty entry? */ |
| 248 | setivalue(s2v(key), i + 1); | 251 | setivalue(s2v(key), i + 1); |
| 249 | setobj2s(L, key + 1, &t->array[i]); | 252 | setobj2s(L, key + 1, &t->array[i]); |
| 250 | return 1; | 253 | return 1; |
| 251 | } | 254 | } |
| 252 | } | 255 | } |
| 253 | for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ | 256 | for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ |
| 254 | if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ | 257 | if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ |
| 255 | Node *n = gnode(t, i); | 258 | Node *n = gnode(t, i); |
| 256 | getnodekey(L, s2v(key), n); | 259 | getnodekey(L, s2v(key), n); |
| 257 | setobj2s(L, key + 1, gval(n)); | 260 | setobj2s(L, key + 1, gval(n)); |
| @@ -336,7 +339,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) { | |||
| 336 | } | 339 | } |
| 337 | /* count elements in range (2^(lg - 1), 2^lg] */ | 340 | /* count elements in range (2^(lg - 1), 2^lg] */ |
| 338 | for (; i <= lim; i++) { | 341 | for (; i <= lim; i++) { |
| 339 | if (!ttisnil(&t->array[i-1])) | 342 | if (!isempty(&t->array[i-1])) |
| 340 | lc++; | 343 | lc++; |
| 341 | } | 344 | } |
| 342 | nums[lg] += lc; | 345 | nums[lg] += lc; |
| @@ -352,7 +355,7 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { | |||
| 352 | int i = sizenode(t); | 355 | int i = sizenode(t); |
| 353 | while (i--) { | 356 | while (i--) { |
| 354 | Node *n = &t->node[i]; | 357 | Node *n = &t->node[i]; |
| 355 | if (!ttisnil(gval(n))) { | 358 | if (!isempty(gval(n))) { |
| 356 | if (keyisinteger(n)) | 359 | if (keyisinteger(n)) |
| 357 | ause += countint(keyival(n), nums); | 360 | ause += countint(keyival(n), nums); |
| 358 | totaluse++; | 361 | totaluse++; |
| @@ -387,7 +390,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { | |||
| 387 | Node *n = gnode(t, i); | 390 | Node *n = gnode(t, i); |
| 388 | gnext(n) = 0; | 391 | gnext(n) = 0; |
| 389 | setnilkey(n); | 392 | setnilkey(n); |
| 390 | setnilvalue(gval(n)); | 393 | setempty(gval(n)); |
| 391 | } | 394 | } |
| 392 | t->lsizenode = cast_byte(lsize); | 395 | t->lsizenode = cast_byte(lsize); |
| 393 | t->lastfree = gnode(t, size); /* all positions are free */ | 396 | t->lastfree = gnode(t, size); /* all positions are free */ |
| @@ -403,7 +406,7 @@ static void reinsert (lua_State *L, Table *ot, Table *t) { | |||
| 403 | int size = sizenode(ot); | 406 | int size = sizenode(ot); |
| 404 | for (j = 0; j < size; j++) { | 407 | for (j = 0; j < size; j++) { |
| 405 | Node *old = gnode(ot, j); | 408 | Node *old = gnode(ot, j); |
| 406 | if (!ttisnil(gval(old))) { | 409 | if (!isempty(gval(old))) { |
| 407 | /* doesn't need barrier/invalidate cache, as entry was | 410 | /* doesn't need barrier/invalidate cache, as entry was |
| 408 | already present in the table */ | 411 | already present in the table */ |
| 409 | TValue k; | 412 | TValue k; |
| @@ -456,7 +459,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize, | |||
| 456 | exchangehashpart(t, &newt); /* and new hash */ | 459 | exchangehashpart(t, &newt); /* and new hash */ |
| 457 | /* re-insert into the new hash the elements from vanishing slice */ | 460 | /* re-insert into the new hash the elements from vanishing slice */ |
| 458 | for (i = newasize; i < oldasize; i++) { | 461 | for (i = newasize; i < oldasize; i++) { |
| 459 | if (!ttisnil(&t->array[i])) | 462 | if (!isempty(&t->array[i])) |
| 460 | luaH_setint(L, t, i + 1, &t->array[i]); | 463 | luaH_setint(L, t, i + 1, &t->array[i]); |
| 461 | } | 464 | } |
| 462 | t->sizearray = oldasize; /* restore current size... */ | 465 | t->sizearray = oldasize; /* restore current size... */ |
| @@ -473,7 +476,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize, | |||
| 473 | t->array = newarray; /* set new array part */ | 476 | t->array = newarray; /* set new array part */ |
| 474 | t->sizearray = newasize; | 477 | t->sizearray = newasize; |
| 475 | for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ | 478 | for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ |
| 476 | setnilvalue(&t->array[i]); | 479 | setempty(&t->array[i]); |
| 477 | /* re-insert elements from old hash part into new parts */ | 480 | /* re-insert elements from old hash part into new parts */ |
| 478 | reinsert(L, &newt, t); /* 'newt' now has the old hash */ | 481 | reinsert(L, &newt, t); /* 'newt' now has the old hash */ |
| 479 | freehash(L, &newt); /* free old hash part */ | 482 | freehash(L, &newt); /* free old hash part */ |
| @@ -569,7 +572,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
| 569 | luaG_runerror(L, "table index is NaN"); | 572 | luaG_runerror(L, "table index is NaN"); |
| 570 | } | 573 | } |
| 571 | mp = mainpositionTV(t, key); | 574 | mp = mainpositionTV(t, key); |
| 572 | if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ | 575 | if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
| 573 | Node *othern; | 576 | Node *othern; |
| 574 | Node *f = getfreepos(t); /* get a free place */ | 577 | Node *f = getfreepos(t); /* get a free place */ |
| 575 | if (f == NULL) { /* cannot find a free place? */ | 578 | if (f == NULL) { /* cannot find a free place? */ |
| @@ -589,7 +592,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
| 589 | gnext(f) += cast_int(mp - f); /* correct 'next' */ | 592 | gnext(f) += cast_int(mp - f); /* correct 'next' */ |
| 590 | gnext(mp) = 0; /* now 'mp' is free */ | 593 | gnext(mp) = 0; /* now 'mp' is free */ |
| 591 | } | 594 | } |
| 592 | setnilvalue(gval(mp)); | 595 | setempty(gval(mp)); |
| 593 | } | 596 | } |
| 594 | else { /* colliding node is in its own main position */ | 597 | else { /* colliding node is in its own main position */ |
| 595 | /* new node will go into free position */ | 598 | /* new node will go into free position */ |
| @@ -602,7 +605,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
| 602 | } | 605 | } |
| 603 | setnodekey(L, mp, key); | 606 | setnodekey(L, mp, key); |
| 604 | luaC_barrierback(L, obj2gco(t), key); | 607 | luaC_barrierback(L, obj2gco(t), key); |
| 605 | lua_assert(ttisnil(gval(mp))); | 608 | lua_assert(isempty(gval(mp))); |
| 606 | return gval(mp); | 609 | return gval(mp); |
| 607 | } | 610 | } |
| 608 | 611 | ||
| @@ -625,7 +628,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
| 625 | n += nx; | 628 | n += nx; |
| 626 | } | 629 | } |
| 627 | } | 630 | } |
| 628 | return luaO_nilobject; | 631 | return luaH_emptyobject; |
| 629 | } | 632 | } |
| 630 | } | 633 | } |
| 631 | 634 | ||
| @@ -642,7 +645,7 @@ const TValue *luaH_getshortstr (Table *t, TString *key) { | |||
| 642 | else { | 645 | else { |
| 643 | int nx = gnext(n); | 646 | int nx = gnext(n); |
| 644 | if (nx == 0) | 647 | if (nx == 0) |
| 645 | return luaO_nilobject; /* not found */ | 648 | return luaH_emptyobject; /* not found */ |
| 646 | n += nx; | 649 | n += nx; |
| 647 | } | 650 | } |
| 648 | } | 651 | } |
| @@ -667,7 +670,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
| 667 | switch (ttype(key)) { | 670 | switch (ttype(key)) { |
| 668 | case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); | 671 | case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); |
| 669 | case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); | 672 | case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); |
| 670 | case LUA_TNIL: return luaO_nilobject; | 673 | case LUA_TNIL: return luaH_emptyobject; |
| 671 | case LUA_TNUMFLT: { | 674 | case LUA_TNUMFLT: { |
| 672 | lua_Integer k; | 675 | lua_Integer k; |
| 673 | if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */ | 676 | if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */ |
| @@ -686,7 +689,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
| 686 | */ | 689 | */ |
| 687 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | 690 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { |
| 688 | const TValue *p = luaH_get(t, key); | 691 | const TValue *p = luaH_get(t, key); |
| 689 | if (p != luaO_nilobject) | 692 | if (p != luaH_emptyobject) |
| 690 | return cast(TValue *, p); | 693 | return cast(TValue *, p); |
| 691 | else return luaH_newkey(L, t, key); | 694 | else return luaH_newkey(L, t, key); |
| 692 | } | 695 | } |
| @@ -695,7 +698,7 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | |||
| 695 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { | 698 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { |
| 696 | const TValue *p = luaH_getint(t, key); | 699 | const TValue *p = luaH_getint(t, key); |
| 697 | TValue *cell; | 700 | TValue *cell; |
| 698 | if (p != luaO_nilobject) | 701 | if (p != luaH_emptyobject) |
| 699 | cell = cast(TValue *, p); | 702 | cell = cast(TValue *, p); |
| 700 | else { | 703 | else { |
| 701 | TValue k; | 704 | TValue k; |
| @@ -728,16 +731,16 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { | |||
| 728 | j *= 2; | 731 | j *= 2; |
| 729 | else { | 732 | else { |
| 730 | j = LUA_MAXINTEGER; | 733 | j = LUA_MAXINTEGER; |
| 731 | if (ttisnil(luaH_getint(t, j))) /* t[j] == nil? */ | 734 | if (isempty(luaH_getint(t, j))) /* t[j] not present? */ |
| 732 | break; /* 'j' now is an absent index */ | 735 | break; /* 'j' now is an absent index */ |
| 733 | else /* weird case */ | 736 | else /* weird case */ |
| 734 | return j; /* well, max integer is a boundary... */ | 737 | return j; /* well, max integer is a boundary... */ |
| 735 | } | 738 | } |
| 736 | } while (!ttisnil(luaH_getint(t, j))); /* repeat until t[j] == nil */ | 739 | } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */ |
| 737 | /* i < j && t[i] !≃ nil && t[j] == nil */ | 740 | /* i < j && t[i] present && t[j] absent */ |
| 738 | while (j - i > 1u) { /* do a binary search between them */ | 741 | while (j - i > 1u) { /* do a binary search between them */ |
| 739 | lua_Unsigned m = (i + j) / 2; | 742 | lua_Unsigned m = (i + j) / 2; |
| 740 | if (ttisnil(luaH_getint(t, m))) j = m; | 743 | if (isempty(luaH_getint(t, m))) j = m; |
| 741 | else i = m; | 744 | else i = m; |
| 742 | } | 745 | } |
| 743 | return i; | 746 | return i; |
| @@ -746,27 +749,27 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { | |||
| 746 | 749 | ||
| 747 | /* | 750 | /* |
| 748 | ** Try to find a boundary in table 't'. (A 'boundary' is an integer index | 751 | ** Try to find a boundary in table 't'. (A 'boundary' is an integer index |
| 749 | ** such that t[i] is non-nil and t[i+1] is nil, plus 0 if t[1] is nil | 752 | ** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent |
| 750 | ** and 'maxinteger' if t[maxinteger] is not nil.) | 753 | ** and 'maxinteger' if t[maxinteger] is present.) |
| 751 | ** First, try the array part: if there is an array part and its last | 754 | ** First, try the array part: if there is an array part and its last |
| 752 | ** element is nil, there must be a boundary there; a binary search | 755 | ** element is absent, there must be a boundary there; a binary search |
| 753 | ** finds that boundary. Otherwise, if the hash part is empty or does not | 756 | ** finds that boundary. Otherwise, if the hash part is empty or does not |
| 754 | ** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search' | 757 | ** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search' |
| 755 | ** to find a boundary in the hash part. | 758 | ** to find a boundary in the hash part. |
| 756 | */ | 759 | */ |
| 757 | lua_Unsigned luaH_getn (Table *t) { | 760 | lua_Unsigned luaH_getn (Table *t) { |
| 758 | unsigned int j = t->sizearray; | 761 | unsigned int j = t->sizearray; |
| 759 | if (j > 0 && ttisnil(&t->array[j - 1])) { | 762 | if (j > 0 && isempty(&t->array[j - 1])) { |
| 760 | unsigned int i = 0; | 763 | unsigned int i = 0; |
| 761 | while (j - i > 1u) { /* binary search */ | 764 | while (j - i > 1u) { /* binary search */ |
| 762 | unsigned int m = (i + j) / 2; | 765 | unsigned int m = (i + j) / 2; |
| 763 | if (ttisnil(&t->array[m - 1])) j = m; | 766 | if (isempty(&t->array[m - 1])) j = m; |
| 764 | else i = m; | 767 | else i = m; |
| 765 | } | 768 | } |
| 766 | return i; | 769 | return i; |
| 767 | } | 770 | } |
| 768 | else { /* 'j' is zero or present in table */ | 771 | else { /* 'j' is zero or present in table */ |
| 769 | if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1)))) | 772 | if (isdummy(t) || isempty(luaH_getint(t, l_castU2S(j + 1)))) |
| 770 | return j; /* 'j + 1' is absent... */ | 773 | return j; /* 'j + 1' is absent... */ |
| 771 | else /* 'j + 1' is also present */ | 774 | else /* 'j + 1' is also present */ |
| 772 | return hash_search(t, j); | 775 | return hash_search(t, j); |
