00001 /* 00002 ** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ 00003 ** Library for Table Manipulation 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 00008 #include <stddef.h> 00009 00010 #define ltablib_c 00011 #define LUA_LIB 00012 00013 #include "lua.h" 00014 00015 #include "lauxlib.h" 00016 #include "lualib.h" 00017 00018 00019 #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) 00020 00021 00022 static int foreachi (lua_State *L) { 00023 int i; 00024 int n = aux_getn(L, 1); 00025 luaL_checktype(L, 2, LUA_TFUNCTION); 00026 for (i=1; i <= n; i++) { 00027 lua_pushvalue(L, 2); /* function */ 00028 lua_pushinteger(L, i); /* 1st argument */ 00029 lua_rawgeti(L, 1, i); /* 2nd argument */ 00030 lua_call(L, 2, 1); 00031 if (!lua_isnil(L, -1)) 00032 return 1; 00033 lua_pop(L, 1); /* remove nil result */ 00034 } 00035 return 0; 00036 } 00037 00038 00039 static int foreach (lua_State *L) { 00040 luaL_checktype(L, 1, LUA_TTABLE); 00041 luaL_checktype(L, 2, LUA_TFUNCTION); 00042 lua_pushnil(L); /* first key */ 00043 while (lua_next(L, 1)) { 00044 lua_pushvalue(L, 2); /* function */ 00045 lua_pushvalue(L, -3); /* key */ 00046 lua_pushvalue(L, -3); /* value */ 00047 lua_call(L, 2, 1); 00048 if (!lua_isnil(L, -1)) 00049 return 1; 00050 lua_pop(L, 2); /* remove value and result */ 00051 } 00052 return 0; 00053 } 00054 00055 00056 static int maxn (lua_State *L) { 00057 lua_Number max = 0; 00058 luaL_checktype(L, 1, LUA_TTABLE); 00059 lua_pushnil(L); /* first key */ 00060 while (lua_next(L, 1)) { 00061 lua_pop(L, 1); /* remove value */ 00062 if (lua_type(L, -1) == LUA_TNUMBER) { 00063 lua_Number v = lua_tonumber(L, -1); 00064 if (v > max) max = v; 00065 } 00066 } 00067 lua_pushnumber(L, max); 00068 return 1; 00069 } 00070 00071 00072 static int getn (lua_State *L) { 00073 lua_pushinteger(L, aux_getn(L, 1)); 00074 return 1; 00075 } 00076 00077 00078 static int setn (lua_State *L) { 00079 luaL_checktype(L, 1, LUA_TTABLE); 00080 #ifndef luaL_setn 00081 luaL_setn(L, 1, luaL_checkint(L, 2)); 00082 #else 00083 luaL_error(L, LUA_QL("setn") " is obsolete"); 00084 #endif 00085 lua_pushvalue(L, 1); 00086 return 1; 00087 } 00088 00089 00090 static int tinsert (lua_State *L) { 00091 int e = aux_getn(L, 1) + 1; /* first empty element */ 00092 int pos; /* where to insert new element */ 00093 switch (lua_gettop(L)) { 00094 case 2: { /* called with only 2 arguments */ 00095 pos = e; /* insert new element at the end */ 00096 break; 00097 } 00098 case 3: { 00099 int i; 00100 pos = luaL_checkint(L, 2); /* 2nd argument is the position */ 00101 if (pos > e) e = pos; /* `grow' array if necessary */ 00102 for (i = e; i > pos; i--) { /* move up elements */ 00103 lua_rawgeti(L, 1, i-1); 00104 lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ 00105 } 00106 break; 00107 } 00108 default: { 00109 return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); 00110 } 00111 } 00112 luaL_setn(L, 1, e); /* new size */ 00113 lua_rawseti(L, 1, pos); /* t[pos] = v */ 00114 return 0; 00115 } 00116 00117 00118 static int tremove (lua_State *L) { 00119 int e = aux_getn(L, 1); 00120 int pos = luaL_optint(L, 2, e); 00121 if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ 00122 return 0; /* nothing to remove */ 00123 luaL_setn(L, 1, e - 1); /* t.n = n-1 */ 00124 lua_rawgeti(L, 1, pos); /* result = t[pos] */ 00125 for ( ;pos<e; pos++) { 00126 lua_rawgeti(L, 1, pos+1); 00127 lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ 00128 } 00129 lua_pushnil(L); 00130 lua_rawseti(L, 1, e); /* t[e] = nil */ 00131 return 1; 00132 } 00133 00134 00135 static void addfield (lua_State *L, luaL_Buffer *b, int i) { 00136 lua_rawgeti(L, 1, i); 00137 if (!lua_isstring(L, -1)) 00138 luaL_error(L, "invalid value (%s) at index %d in table for " 00139 LUA_QL("concat"), luaL_typename(L, -1), i); 00140 luaL_addvalue(b); 00141 } 00142 00143 00144 static int tconcat (lua_State *L) { 00145 luaL_Buffer b; 00146 size_t lsep; 00147 int i, last; 00148 const char *sep = luaL_optlstring(L, 2, "", &lsep); 00149 luaL_checktype(L, 1, LUA_TTABLE); 00150 i = luaL_optint(L, 3, 1); 00151 last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); 00152 luaL_buffinit(L, &b); 00153 for (; i < last; i++) { 00154 addfield(L, &b, i); 00155 luaL_addlstring(&b, sep, lsep); 00156 } 00157 if (i == last) /* add last value (if interval was not empty) */ 00158 addfield(L, &b, i); 00159 luaL_pushresult(&b); 00160 return 1; 00161 } 00162 00163 00164 00165 /* 00166 ** {====================================================== 00167 ** Quicksort 00168 ** (based on `Algorithms in MODULA-3', Robert Sedgewick; 00169 ** Addison-Wesley, 1993.) 00170 */ 00171 00172 00173 static void set2 (lua_State *L, int i, int j) { 00174 lua_rawseti(L, 1, i); 00175 lua_rawseti(L, 1, j); 00176 } 00177 00178 static int sort_comp (lua_State *L, int a, int b) { 00179 if (!lua_isnil(L, 2)) { /* function? */ 00180 int res; 00181 lua_pushvalue(L, 2); 00182 lua_pushvalue(L, a-1); /* -1 to compensate function */ 00183 lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ 00184 lua_call(L, 2, 1); 00185 res = lua_toboolean(L, -1); 00186 lua_pop(L, 1); 00187 return res; 00188 } 00189 else /* a < b? */ 00190 return lua_lessthan(L, a, b); 00191 } 00192 00193 static void auxsort (lua_State *L, int l, int u) { 00194 while (l < u) { /* for tail recursion */ 00195 int i, j; 00196 /* sort elements a[l], a[(l+u)/2] and a[u] */ 00197 lua_rawgeti(L, 1, l); 00198 lua_rawgeti(L, 1, u); 00199 if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ 00200 set2(L, l, u); /* swap a[l] - a[u] */ 00201 else 00202 lua_pop(L, 2); 00203 if (u-l == 1) break; /* only 2 elements */ 00204 i = (l+u)/2; 00205 lua_rawgeti(L, 1, i); 00206 lua_rawgeti(L, 1, l); 00207 if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ 00208 set2(L, i, l); 00209 else { 00210 lua_pop(L, 1); /* remove a[l] */ 00211 lua_rawgeti(L, 1, u); 00212 if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ 00213 set2(L, i, u); 00214 else 00215 lua_pop(L, 2); 00216 } 00217 if (u-l == 2) break; /* only 3 elements */ 00218 lua_rawgeti(L, 1, i); /* Pivot */ 00219 lua_pushvalue(L, -1); 00220 lua_rawgeti(L, 1, u-1); 00221 set2(L, i, u-1); 00222 /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ 00223 i = l; j = u-1; 00224 for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ 00225 /* repeat ++i until a[i] >= P */ 00226 while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { 00227 if (i>u) luaL_error(L, "invalid order function for sorting"); 00228 lua_pop(L, 1); /* remove a[i] */ 00229 } 00230 /* repeat --j until a[j] <= P */ 00231 while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { 00232 if (j<l) luaL_error(L, "invalid order function for sorting"); 00233 lua_pop(L, 1); /* remove a[j] */ 00234 } 00235 if (j<i) { 00236 lua_pop(L, 3); /* pop pivot, a[i], a[j] */ 00237 break; 00238 } 00239 set2(L, i, j); 00240 } 00241 lua_rawgeti(L, 1, u-1); 00242 lua_rawgeti(L, 1, i); 00243 set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ 00244 /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ 00245 /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ 00246 if (i-l < u-i) { 00247 j=l; i=i-1; l=i+2; 00248 } 00249 else { 00250 j=i+1; i=u; u=j-2; 00251 } 00252 auxsort(L, j, i); /* call recursively the smaller one */ 00253 } /* repeat the routine for the larger one */ 00254 } 00255 00256 static int sort (lua_State *L) { 00257 int n = aux_getn(L, 1); 00258 luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ 00259 if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ 00260 luaL_checktype(L, 2, LUA_TFUNCTION); 00261 lua_settop(L, 2); /* make sure there is two arguments */ 00262 auxsort(L, 1, n); 00263 return 0; 00264 } 00265 00266 /* }====================================================== */ 00267 00268 00269 static const luaL_Reg tab_funcs[] = { 00270 {"concat", tconcat}, 00271 {"foreach", foreach}, 00272 {"foreachi", foreachi}, 00273 {"getn", getn}, 00274 {"maxn", maxn}, 00275 {"insert", tinsert}, 00276 {"remove", tremove}, 00277 {"setn", setn}, 00278 {"sort", sort}, 00279 {NULL, NULL} 00280 }; 00281 00282 00283 LUALIB_API int luaopen_table (lua_State *L) { 00284 luaL_register(L, LUA_TABLIBNAME, tab_funcs); 00285 return 1; 00286 } 00287
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1