diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-03-16 13:58:41 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-03-16 13:58:41 -0300 |
| commit | 9ffae705ee8894d68bbc07a1a5f77a112c40efad (patch) | |
| tree | e162bb7ecfd1a3e6776cf09e62736ec8eb0fca41 /ltable.c | |
| parent | 6bfef60e77f5eec1057470010b4179ee6f830fe6 (diff) | |
| download | lua-9ffae705ee8894d68bbc07a1a5f77a112c40efad.tar.gz lua-9ffae705ee8894d68bbc07a1a5f77a112c40efad.tar.bz2 lua-9ffae705ee8894d68bbc07a1a5f77a112c40efad.zip | |
new "primitive" getn
Diffstat (limited to 'ltable.c')
| -rw-r--r-- | ltable.c | 50 |
1 files changed, 49 insertions, 1 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 2.17 2005/03/08 20:10:05 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.18 2005/03/09 16:28:07 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 | */ |
| @@ -524,3 +524,51 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { | |||
| 524 | } | 524 | } |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | |||
| 528 | static int unbound_search (Table *t, unsigned int j) { | ||
| 529 | unsigned int i = j; /* i is zero or a present index */ | ||
| 530 | j = j+1; | ||
| 531 | /* find `i' and `j' such that i is present and j is not */ | ||
| 532 | while (!ttisnil(luaH_getnum(t, j))) { | ||
| 533 | i = j; | ||
| 534 | j = i*2; | ||
| 535 | if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ | ||
| 536 | /* table was built with bad purposes: resort to linear search */ | ||
| 537 | i = 1; | ||
| 538 | while (!ttisnil(luaH_getnum(t, i))) i++; | ||
| 539 | return i - 1; | ||
| 540 | } | ||
| 541 | } | ||
| 542 | /* now do a binary search between them */ | ||
| 543 | while (i < j-1) { | ||
| 544 | unsigned int m = (i+j)/2; | ||
| 545 | if (ttisnil(luaH_getnum(t, m))) j = m; | ||
| 546 | else i = m; | ||
| 547 | } | ||
| 548 | return i; | ||
| 549 | } | ||
| 550 | |||
| 551 | |||
| 552 | /* | ||
| 553 | ** Try to find a boundary in table `t'. A `boundary' is an integer index | ||
| 554 | ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). | ||
| 555 | */ | ||
| 556 | int luaH_getn (Table *t) { | ||
| 557 | unsigned int j = t->sizearray; | ||
| 558 | if (j > 0 && ttisnil(&t->array[j - 1])) { | ||
| 559 | /* there is a boundary in the array part: (binary) search for it */ | ||
| 560 | unsigned int i = 1; | ||
| 561 | if (ttisnil(&t->array[1 - 1])) return 0; | ||
| 562 | while (i < j - 1) { | ||
| 563 | unsigned int m = (i+j)/2; | ||
| 564 | if (ttisnil(&t->array[m - 1])) j = m; | ||
| 565 | else i = m; | ||
| 566 | } | ||
| 567 | return i; | ||
| 568 | } | ||
| 569 | /* else must find a boundary in hash part */ | ||
| 570 | else if (t->node == &luaH_dummynode) /* hash part is empty? */ | ||
| 571 | return j; /* that is easy... */ | ||
| 572 | else return unbound_search(t, j); | ||
| 573 | } | ||
| 574 | |||
