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) \
00020 (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
00021
00022
00023 #if defined(LUA_COMPAT_MAXN)
00024 static int maxn (lua_State *L) {
00025 lua_Number max = 0;
00026 luaL_checktype(L, 1, LUA_TTABLE);
00027 lua_pushnil(L);
00028 while (lua_next(L, 1)) {
00029 lua_pop(L, 1);
00030 if (lua_type(L, -1) == LUA_TNUMBER) {
00031 lua_Number v = lua_tonumber(L, -1);
00032 if (v > max) max = v;
00033 }
00034 }
00035 lua_pushnumber(L, max);
00036 return 1;
00037 }
00038 #endif
00039
00040
00041 static int tinsert (lua_State *L) {
00042 int e = aux_getn(L, 1) + 1;
00043 int pos;
00044 switch (lua_gettop(L)) {
00045 case 2: {
00046 pos = e;
00047 break;
00048 }
00049 case 3: {
00050 int i;
00051 pos = luaL_checkint(L, 2);
00052 if (pos > e) e = pos;
00053 for (i = e; i > pos; i--) {
00054 lua_rawgeti(L, 1, i-1);
00055 lua_rawseti(L, 1, i);
00056 }
00057 break;
00058 }
00059 default: {
00060 return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
00061 }
00062 }
00063 lua_rawseti(L, 1, pos);
00064 return 0;
00065 }
00066
00067
00068 static int tremove (lua_State *L) {
00069 int e = aux_getn(L, 1);
00070 int pos = luaL_optint(L, 2, e);
00071 if (!(1 <= pos && pos <= e))
00072 return 0;
00073 lua_rawgeti(L, 1, pos);
00074 for ( ;pos<e; pos++) {
00075 lua_rawgeti(L, 1, pos+1);
00076 lua_rawseti(L, 1, pos);
00077 }
00078 lua_pushnil(L);
00079 lua_rawseti(L, 1, e);
00080 return 1;
00081 }
00082
00083
00084 static void addfield (lua_State *L, luaL_Buffer *b, int i) {
00085 lua_rawgeti(L, 1, i);
00086 if (!lua_isstring(L, -1))
00087 luaL_error(L, "invalid value (%s) at index %d in table for "
00088 LUA_QL("concat"), luaL_typename(L, -1), i);
00089 luaL_addvalue(b);
00090 }
00091
00092
00093 static int tconcat (lua_State *L) {
00094 luaL_Buffer b;
00095 size_t lsep;
00096 int i, last;
00097 const char *sep = luaL_optlstring(L, 2, "", &lsep);
00098 luaL_checktype(L, 1, LUA_TTABLE);
00099 i = luaL_optint(L, 3, 1);
00100 last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
00101 luaL_buffinit(L, &b);
00102 for (; i < last; i++) {
00103 addfield(L, &b, i);
00104 luaL_addlstring(&b, sep, lsep);
00105 }
00106 if (i == last)
00107 addfield(L, &b, i);
00108 luaL_pushresult(&b);
00109 return 1;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119 static int pack (lua_State *L) {
00120 int n = lua_gettop(L);
00121 lua_createtable(L, n, 1);
00122 lua_pushinteger(L, n);
00123 lua_setfield(L, -2, "n");
00124 if (n > 0) {
00125 int i;
00126 lua_pushvalue(L, 1);
00127 lua_rawseti(L, -2, 1);
00128 lua_replace(L, 1);
00129 for (i = n; i >= 2; i--)
00130 lua_rawseti(L, 1, i);
00131 }
00132 return 1;
00133 }
00134
00135
00136 static int unpack (lua_State *L) {
00137 int i, e, n;
00138 luaL_checktype(L, 1, LUA_TTABLE);
00139 i = luaL_optint(L, 2, 1);
00140 e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
00141 if (i > e) return 0;
00142 n = e - i + 1;
00143 if (n <= 0 || !lua_checkstack(L, n))
00144 return luaL_error(L, "too many results to unpack");
00145 lua_rawgeti(L, 1, i);
00146 while (i++ < e)
00147 lua_rawgeti(L, 1, i);
00148 return n;
00149 }
00150
00151
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_compare(L, a, b, LUA_OPLT);
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 #if defined(LUA_COMPAT_MAXN)
00263 {"maxn", maxn},
00264 #endif
00265 {"insert", tinsert},
00266 {"pack", pack},
00267 {"unpack", unpack},
00268 {"remove", tremove},
00269 {"sort", sort},
00270 {NULL, NULL}
00271 };
00272
00273
00274 LUAMOD_API int luaopen_table (lua_State *L) {
00275 luaL_newlib(L, tab_funcs);
00276 #if defined(LUA_COMPAT_UNPACK)
00277
00278 lua_getfield(L, -1, "unpack");
00279 lua_setglobal(L, "unpack");
00280 #endif
00281 return 1;
00282 }
00283