diff options
Diffstat (limited to 'ltable.c')
-rw-r--r-- | ltable.c | 64 |
1 files changed, 36 insertions, 28 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.119 2017/05/09 14:39:46 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.120 2017/05/16 19:07:08 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 | */ |
@@ -610,29 +610,35 @@ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { | |||
610 | 610 | ||
611 | /* | 611 | /* |
612 | ** Try to find a boundary in the hash part of table 't'. From the | 612 | ** Try to find a boundary in the hash part of table 't'. From the |
613 | ** caller, we know that 'i' is zero or present. We need to find an | 613 | ** caller, we know that 'j' is zero or present and that 'j + 1' is |
614 | ** upper bound (an absent index larger than 'i') to do a binary search | 614 | ** present. We want to find a larger key that is absent from the |
615 | ** for a boundary. We try 'max', a number larger than the total number | 615 | ** table, so that we can do a binary search between the two keys to |
616 | ** of keys in the table. (Given the size of the array elements, 'max' | 616 | ** find a boundary. We keep doubling 'j' until we get an absent index. |
617 | ** computation cannot overflow a 'size_t'.) If 'max' does not fit in a | 617 | ** If the doubling would overflow, we try LUA_MAXINTEGER. If it is |
618 | ** lua_Integer or it is present in the table, we try LUA_MAXINTEGER. If | 618 | ** absent, we are ready for the binary search. ('j', being max integer, |
619 | ** LUA_MAXINTEGER is present, it is a boundary, so we are done. Otherwise, | 619 | ** is larger or equal to 'i', but it cannot be equal because it is |
620 | ** we are left with a 'j' that is within the size of lua_Integers and | 620 | ** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a |
621 | ** absent, so can do the binary search. | 621 | ** boundary. ('j + 1' cannot be a present integer key because it is |
622 | ** not a valid integer in Lua.) | ||
622 | */ | 623 | */ |
623 | static lua_Unsigned hash_search (Table *t, lua_Unsigned i) { | 624 | static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { |
624 | lua_Unsigned j; | 625 | lua_Unsigned i; |
625 | size_t max = (cast(size_t, i) + sizenode(t) + 10) * 2; | 626 | if (j == 0) j++; /* the caller ensures 'j + 1' is present */ |
626 | if (max <= l_castS2U(LUA_MAXINTEGER) && ttisnil(luaH_getint(t, max))) | 627 | do { |
627 | j = max; | 628 | i = j; /* 'i' is a present index */ |
628 | else { | 629 | if (j <= l_castS2U(LUA_MAXINTEGER) / 2) |
629 | j = LUA_MAXINTEGER; | 630 | j *= 2; |
630 | if (!ttisnil(luaH_getint(t, j))) /* weird case? */ | 631 | else { |
631 | return j; /* well, that is a boundary... */ | 632 | j = LUA_MAXINTEGER; |
632 | } | 633 | if (ttisnil(luaH_getint(t, j))) /* t[j] == nil? */ |
633 | /* now, 'i' is zero or present and 'j' is absent */ | 634 | break; /* 'j' now is an absent index */ |
635 | else /* weird case */ | ||
636 | return j; /* well, max integer is a boundary... */ | ||
637 | } | ||
638 | } while (!ttisnil(luaH_getint(t, j))); /* repeat until t[j] == nil */ | ||
639 | /* i < j && t[i] !≃ nil && t[j] == nil */ | ||
634 | while (j - i > 1u) { /* do a binary search between them */ | 640 | while (j - i > 1u) { /* do a binary search between them */ |
635 | size_t m = (i + j) / 2; | 641 | lua_Unsigned m = (i + j) / 2; |
636 | if (ttisnil(luaH_getint(t, m))) j = m; | 642 | if (ttisnil(luaH_getint(t, m))) j = m; |
637 | else i = m; | 643 | else i = m; |
638 | } | 644 | } |
@@ -642,7 +648,8 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned i) { | |||
642 | 648 | ||
643 | /* | 649 | /* |
644 | ** Try to find a boundary in table 't'. (A 'boundary' is an integer index | 650 | ** Try to find a boundary in table 't'. (A 'boundary' is an integer index |
645 | ** such that t[i] is non-nil and t[i+1] is nil (or 0 if t[1] is nil).) | 651 | ** such that t[i] is non-nil and t[i+1] is nil, plus 0 if t[1] is nil |
652 | ** and 'maxinteger' if t[maxinteger] is not nil.) | ||
646 | ** First, try the array part: if there is an array part and its last | 653 | ** First, try the array part: if there is an array part and its last |
647 | ** element is nil, there must be a boundary there; a binary search | 654 | ** element is nil, there must be a boundary there; a binary search |
648 | ** finds that boundary. Otherwise, if the hash part is empty or does not | 655 | ** finds that boundary. Otherwise, if the hash part is empty or does not |
@@ -660,11 +667,12 @@ lua_Unsigned luaH_getn (Table *t) { | |||
660 | } | 667 | } |
661 | return i; | 668 | return i; |
662 | } | 669 | } |
663 | /* 'j' is zero or present in table */ | 670 | else { /* 'j' is zero or present in table */ |
664 | else if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1)))) | 671 | if (isdummy(t) || ttisnil(luaH_getint(t, l_castU2S(j + 1)))) |
665 | return j; /* 'j + 1' is absent... */ | 672 | return j; /* 'j + 1' is absent... */ |
666 | else | 673 | else /* 'j + 1' is also present */ |
667 | return hash_search(t, j); | 674 | return hash_search(t, j); |
675 | } | ||
668 | } | 676 | } |
669 | 677 | ||
670 | 678 | ||