/* ** $Id: ltablib.c,v 1.12 2002/08/06 18:01:50 roberto Exp roberto $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ #include #include "lua.h" #include "lauxlib.h" #include "lualib.h" static int checkint (lua_State *L) { int n = (int)lua_tonumber(L, -1); if (n == 0 && !lua_isnumber(L, -1)) n = -1; lua_pop(L, 1); return n; } static void aux_setn (lua_State *L, int t, int n) { lua_pushliteral(L, "n"); lua_rawget(L, t); if (checkint(L) >= 0) { lua_pushliteral(L, "n"); /* use it */ lua_pushnumber(L, n); lua_rawset(L, t); } else { /* use N */ lua_pushvalue(L, t); lua_pushnumber(L, n); lua_rawset(L, lua_upvalueindex(1)); /* N[t] = n */ } } static int aux_getn (lua_State *L, int t) { int n; luaL_check_type(L, t, LUA_TTABLE); lua_pushliteral(L, "n"); /* try t.n */ lua_rawget(L, t); if ((n = checkint(L)) >= 0) return n; lua_pushvalue(L, t); /* try N[t] */ lua_rawget(L, lua_upvalueindex(1)); if ((n = checkint(L)) >= 0) return n; else { /* must count elements */ n = 0; for (;;) { lua_rawgeti(L, t, ++n); if (lua_isnil(L, -1)) break; lua_pop(L, 1); } lua_pop(L, 1); aux_setn(L, t, n - 1); return n - 1; } } static int luaB_foreachi (lua_State *L) { int i; int n = aux_getn(L, 1); luaL_check_type(L, 2, LUA_TFUNCTION); for (i=1; i<=n; i++) { lua_pushvalue(L, 2); /* function */ lua_pushnumber(L, i); /* 1st argument */ lua_rawgeti(L, 1, i); /* 2nd argument */ lua_call(L, 2, 1); if (!lua_isnil(L, -1)) return 1; lua_pop(L, 1); /* remove nil result */ } return 0; } static int luaB_foreach (lua_State *L) { luaL_check_type(L, 1, LUA_TTABLE); luaL_check_type(L, 2, LUA_TFUNCTION); lua_pushnil(L); /* first key */ for (;;) { if (lua_next(L, 1) == 0) return 0; lua_pushvalue(L, 2); /* function */ lua_pushvalue(L, -3); /* key */ lua_pushvalue(L, -3); /* value */ lua_call(L, 2, 1); if (!lua_isnil(L, -1)) return 1; lua_pop(L, 2); /* remove value and result */ } } static int luaB_getn (lua_State *L) { lua_pushnumber(L, aux_getn(L, 1)); return 1; } static int luaB_setn (lua_State *L) { luaL_check_type(L, 1, LUA_TTABLE); aux_setn(L, 1, luaL_check_int(L, 2)); return 0; } static int luaB_tinsert (lua_State *L) { int v = lua_gettop(L); /* number of arguments */ int n = aux_getn(L, 1) + 1; int pos; /* where to insert new element */ if (v == 2) /* called with only 2 arguments */ pos = n; /* insert new element at the end */ else { pos = luaL_check_int(L, 2); /* 2nd argument is the position */ if (pos > n) n = pos; /* `grow' array if necessary */ v = 3; /* function may be called with more than 3 args */ } aux_setn(L, 1, n); /* new size */ while (--n >= pos) { /* move up elements */ lua_rawgeti(L, 1, n); lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ } lua_pushvalue(L, v); lua_rawseti(L, 1, pos); /* t[pos] = v */ return 0; } static int luaB_tremove (lua_State *L) { int n = aux_getn(L, 1); int pos = luaL_opt_int(L, 2, n); if (n <= 0) return 0; /* table is `empty' */ aux_setn(L, 1, n-1); /* t.n = n-1 */ lua_rawgeti(L, 1, pos); /* result = t[pos] */ for ( ;pos= P */ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { if (i>u) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[i] */ } /* repeat --j until a[j] <= P */ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { if (j