diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-06-02 16:06:14 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-06-02 16:06:14 -0300 |
| commit | b8691f13a8e3e9bb7fbd91d1f099eb517a9d5b35 (patch) | |
| tree | f3375e6a5c13c92e58a257aff7c7672c2c149dc0 | |
| parent | f4718544de97bd2fc22117424ba0736c5295a8f2 (diff) | |
| download | lua-b8691f13a8e3e9bb7fbd91d1f099eb517a9d5b35.tar.gz lua-b8691f13a8e3e9bb7fbd91d1f099eb517a9d5b35.tar.bz2 lua-b8691f13a8e3e9bb7fbd91d1f099eb517a9d5b35.zip | |
`getn' uses binary search if it has to count elements
| -rw-r--r-- | lauxlib.c | 35 |
1 files changed, 27 insertions, 8 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.c,v 1.113 2004/05/31 19:27:14 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.114 2004/06/02 13:50:46 roberto Exp roberto $ |
| 3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -299,6 +299,31 @@ LUALIB_API void luaL_setn (lua_State *L, int t, int n) { | |||
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | 301 | ||
| 302 | /* find an `n' such that t[n] ~= nil and t[n+1] == nil */ | ||
| 303 | static int countn (lua_State *L, int t) { | ||
| 304 | int i = LUA_FIRSTINDEX - 1; | ||
| 305 | int j = 2; | ||
| 306 | /* find `i' such that i <= n < i*2 (= j) */ | ||
| 307 | for (;;) { | ||
| 308 | lua_rawgeti(L, t, j); | ||
| 309 | if (lua_isnil(L, -1)) break; | ||
| 310 | lua_pop(L, 1); | ||
| 311 | i = j; | ||
| 312 | j = i*2; | ||
| 313 | } | ||
| 314 | lua_pop(L, 1); | ||
| 315 | /* i <= n < j; do a binary search */ | ||
| 316 | while (i < j-1) { | ||
| 317 | int m = (i+j)/2; | ||
| 318 | lua_rawgeti(L, t, m); | ||
| 319 | if (lua_isnil(L, -1)) j = m; | ||
| 320 | else i = m; | ||
| 321 | lua_pop(L, 1); | ||
| 322 | } | ||
| 323 | return i - LUA_FIRSTINDEX + 1; | ||
| 324 | } | ||
| 325 | |||
| 326 | |||
| 302 | LUALIB_API int luaL_getn (lua_State *L, int t) { | 327 | LUALIB_API int luaL_getn (lua_State *L, int t) { |
| 303 | int n; | 328 | int n; |
| 304 | t = abs_index(L, t); | 329 | t = abs_index(L, t); |
| @@ -308,13 +333,7 @@ LUALIB_API int luaL_getn (lua_State *L, int t) { | |||
| 308 | if ((n = checkint(L, 2)) >= 0) return n; | 333 | if ((n = checkint(L, 2)) >= 0) return n; |
| 309 | lua_getfield(L, t, "n"); /* else try t.n */ | 334 | lua_getfield(L, t, "n"); /* else try t.n */ |
| 310 | if ((n = checkint(L, 1)) >= 0) return n; | 335 | if ((n = checkint(L, 1)) >= 0) return n; |
| 311 | for (n = LUA_FIRSTINDEX; ; n++) { /* else must count elements */ | 336 | return countn(L, t); |
| 312 | lua_rawgeti(L, t, n); | ||
| 313 | if (lua_isnil(L, -1)) break; | ||
| 314 | lua_pop(L, 1); | ||
| 315 | } | ||
| 316 | lua_pop(L, 1); | ||
| 317 | return n - LUA_FIRSTINDEX; | ||
| 318 | } | 337 | } |
| 319 | 338 | ||
| 320 | /* }====================================================== */ | 339 | /* }====================================================== */ |
