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 (!(1 <= pos && pos <= e))
00122 return 0;
00123 luaL_setn(L, 1, e - 1);
00124 lua_rawgeti(L, 1, pos);
00125 for ( ;pos<e; pos++) {
00126 lua_rawgeti(L, 1, pos+1);
00127 lua_rawseti(L, 1, pos);
00128 }
00129 lua_pushnil(L);
00130 lua_rawseti(L, 1, e);
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)
00158 addfield(L, &b, i);
00159 luaL_pushresult(&b);
00160 return 1;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
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)) {
00180 int res;
00181 lua_pushvalue(L, 2);
00182 lua_pushvalue(L, a-1);
00183 lua_pushvalue(L, b-2);
00184 lua_call(L, 2, 1);
00185 res = lua_toboolean(L, -1);
00186 lua_pop(L, 1);
00187 return res;
00188 }
00189 else
00190 return lua_lessthan(L, a, b);
00191 }
00192
00193 static void auxsort (lua_State *L, int l, int u) {
00194 while (l < u) {
00195 int i, j;
00196
00197 lua_rawgeti(L, 1, l);
00198 lua_rawgeti(L, 1, u);
00199 if (sort_comp(L, -1, -2))
00200 set2(L, l, u);
00201 else
00202 lua_pop(L, 2);
00203 if (u-l == 1) break;
00204 i = (l+u)/2;
00205 lua_rawgeti(L, 1, i);
00206 lua_rawgeti(L, 1, l);
00207 if (sort_comp(L, -2, -1))
00208 set2(L, i, l);
00209 else {
00210 lua_pop(L, 1);
00211 lua_rawgeti(L, 1, u);
00212 if (sort_comp(L, -1, -2))
00213 set2(L, i, u);
00214 else
00215 lua_pop(L, 2);
00216 }
00217 if (u-l == 2) break;
00218 lua_rawgeti(L, 1, i);
00219 lua_pushvalue(L, -1);
00220 lua_rawgeti(L, 1, u-1);
00221 set2(L, i, u-1);
00222
00223 i = l; j = u-1;
00224 for (;;) {
00225
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);
00229 }
00230
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);
00234 }
00235 if (j<i) {
00236 lua_pop(L, 3);
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);
00244
00245
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);
00253 }
00254 }
00255
00256 static int sort (lua_State *L) {
00257 int n = aux_getn(L, 1);
00258 luaL_checkstack(L, 40, "");
00259 if (!lua_isnoneornil(L, 2))
00260 luaL_checktype(L, 2, LUA_TFUNCTION);
00261 lua_settop(L, 2);
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 }