aboutsummaryrefslogtreecommitdiff
path: root/ltable.c
diff options
context:
space:
mode:
Diffstat (limited to 'ltable.c')
-rw-r--r--ltable.c64
1 files changed, 36 insertions, 28 deletions
diff --git a/ltable.c b/ltable.c
index c9a498e5..30e9ad3d 100644
--- a/ltable.c
+++ b/ltable.c
@@ -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*/
623static lua_Unsigned hash_search (Table *t, lua_Unsigned i) { 624static 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