00001
00002
00003
00004
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);
00028 lua_pushinteger(L, i);
00029 lua_rawgeti(L, 1, i);
00030 lua_call(L, 2, 1);
00031 if (!lua_isnil(L, -1))
00032 return 1;
00033 lua_pop(L, 1);
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);
00043 while (lua_next(L, 1)) {
00044 lua_pushvalue(L, 2);
00045 lua_pushvalue(L, -3);
00046 lua_pushvalue(L, -3);
00047 lua_call(L, 2, 1);
00048 if (!lua_isnil(L, -1))
00049 return 1;
00050 lua_pop(L, 2);
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);
00060 while (lua_next(L, 1)) {
00061 lua_pop(L, 1);
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;
00092 int pos;
00093 switch (lua_gettop(L)) {
00094 case 2: {
00095 pos = e;
00096 break;
00097 }
00098 case 3: {
00099 int i;
00100 pos = luaL_checkint(L, 2);
00101 if (pos > e) e = pos;
00102 for (i = e; i > pos; i--) {
00103 lua_rawgeti(L, 1, i-1);
00104 lua_rawseti(L, 1, i);
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);
00113 lua_rawseti(L, 1, pos);
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 (e == 0) return 0;
00122 luaL_setn(L, 1, e - 1);
00123 lua_rawgeti(L, 1, pos);
00124 for ( ;pos<e; pos++) {
00125 lua_rawgeti(L, 1, pos+1);
00126 lua_rawseti(L, 1, pos);
00127 }
00128 lua_pushnil(L);
00129 lua_rawseti(L, 1, e);
00130 return 1;
00131 }
00132
00133
00134 static int tconcat (lua_State *L) {
00135 luaL_Buffer b;
00136 size_t lsep;
00137 int i, last;
00138 const char *sep = luaL_optlstring(L, 2, "", &lsep);
00139 luaL_checktype(L, 1, LUA_TTABLE);
00140 i = luaL_optint(L, 3, 1);
00141 last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
00142 luaL_buffinit(L, &b);
00143 for (; i <= last; i++) {
00144 lua_rawgeti(L, 1, i);
00145 luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
00146 luaL_addvalue(&b);
00147 if (i != last)
00148 luaL_addlstring(&b, sep, lsep);
00149 }
00150 luaL_pushresult(&b);
00151 return 1;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static void set2 (lua_State *L, int i, int j) {
00165 lua_rawseti(L, 1, i);
00166 lua_rawseti(L, 1, j);
00167 }
00168
00169 static int sort_comp (lua_State *L, int a, int b) {
00170 if (!lua_isnil(L, 2)) {
00171 int res;
00172 lua_pushvalue(L, 2);
00173 lua_pushvalue(L, a-1);
00174 lua_pushvalue(L, b-2);
00175 lua_call(L, 2, 1);
00176 res = lua_toboolean(L, -1);
00177 lua_pop(L, 1);
00178 return res;
00179 }
00180 else
00181 return lua_lessthan(L, a, b);
00182 }
00183
00184 static void auxsort (lua_State *L, int l, int u) {
00185 while (l < u) {
00186 int i, j;
00187
00188 lua_rawgeti(L, 1, l);
00189 lua_rawgeti(L, 1, u);
00190 if (sort_comp(L, -1, -2))
00191 set2(L, l, u);
00192 else
00193 lua_pop(L, 2);
00194 if (u-l == 1) break;
00195 i = (l+u)/2;
00196 lua_rawgeti(L, 1, i);
00197 lua_rawgeti(L, 1, l);
00198 if (sort_comp(L, -2, -1))
00199 set2(L, i, l);
00200 else {
00201 lua_pop(L, 1);
00202 lua_rawgeti(L, 1, u);
00203 if (sort_comp(L, -1, -2))
00204 set2(L, i, u);
00205 else
00206 lua_pop(L, 2);
00207 }
00208 if (u-l == 2) break;
00209 lua_rawgeti(L, 1, i);
00210 lua_pushvalue(L, -1);
00211 lua_rawgeti(L, 1, u-1);
00212 set2(L, i, u-1);
00213
00214 i = l; j = u-1;
00215 for (;;) {
00216
00217 while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
00218 if (i>u) luaL_error(L, "invalid order function for sorting");
00219 lua_pop(L, 1);
00220 }
00221
00222 while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
00223 if (j<l) luaL_error(L, "invalid order function for sorting");
00224 lua_pop(L, 1);
00225 }
00226 if (j<i) {
00227 lua_pop(L, 3);
00228 break;
00229 }
00230 set2(L, i, j);
00231 }
00232 lua_rawgeti(L, 1, u-1);
00233 lua_rawgeti(L, 1, i);
00234 set2(L, u-1, i);
00235
00236
00237 if (i-l < u-i) {
00238 j=l; i=i-1; l=i+2;
00239 }
00240 else {
00241 j=i+1; i=u; u=j-2;
00242 }
00243 auxsort(L, j, i);
00244 }
00245 }
00246
00247 static int sort (lua_State *L) {
00248 int n = aux_getn(L, 1);
00249 luaL_checkstack(L, 40, "");
00250 if (!lua_isnoneornil(L, 2))
00251 luaL_checktype(L, 2, LUA_TFUNCTION);
00252 lua_settop(L, 2);
00253 auxsort(L, 1, n);
00254 return 0;
00255 }
00256
00257
00258
00259
00260 static const luaL_Reg tab_funcs[] = {
00261 {"concat", tconcat},
00262 {"foreach", foreach},
00263 {"foreachi", foreachi},
00264 {"getn", getn},
00265 {"maxn", maxn},
00266 {"insert", tinsert},
00267 {"remove", tremove},
00268 {"setn", setn},
00269 {"sort", sort},
00270 {NULL, NULL}
00271 };
00272
00273
00274 LUALIB_API int luaopen_table (lua_State *L) {
00275 luaL_register(L, LUA_TABLIBNAME, tab_funcs);
00276 return 1;
00277 }
00278