Mercurial > vba-linux
diff src/lua/ltablib.c @ 11:27763b933818
raise lua sources up one level
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:07:39 -0600 |
parents | src/lua/src/ltablib.c@f9f4f1b99eed |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/lua/ltablib.c Sat Mar 03 11:07:39 2012 -0600 1.3 @@ -0,0 +1,287 @@ 1.4 +/* 1.5 +** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ 1.6 +** Library for Table Manipulation 1.7 +** See Copyright Notice in lua.h 1.8 +*/ 1.9 + 1.10 + 1.11 +#include <stddef.h> 1.12 + 1.13 +#define ltablib_c 1.14 +#define LUA_LIB 1.15 + 1.16 +#include "lua.h" 1.17 + 1.18 +#include "lauxlib.h" 1.19 +#include "lualib.h" 1.20 + 1.21 + 1.22 +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) 1.23 + 1.24 + 1.25 +static int foreachi (lua_State *L) { 1.26 + int i; 1.27 + int n = aux_getn(L, 1); 1.28 + luaL_checktype(L, 2, LUA_TFUNCTION); 1.29 + for (i=1; i <= n; i++) { 1.30 + lua_pushvalue(L, 2); /* function */ 1.31 + lua_pushinteger(L, i); /* 1st argument */ 1.32 + lua_rawgeti(L, 1, i); /* 2nd argument */ 1.33 + lua_call(L, 2, 1); 1.34 + if (!lua_isnil(L, -1)) 1.35 + return 1; 1.36 + lua_pop(L, 1); /* remove nil result */ 1.37 + } 1.38 + return 0; 1.39 +} 1.40 + 1.41 + 1.42 +static int foreach (lua_State *L) { 1.43 + luaL_checktype(L, 1, LUA_TTABLE); 1.44 + luaL_checktype(L, 2, LUA_TFUNCTION); 1.45 + lua_pushnil(L); /* first key */ 1.46 + while (lua_next(L, 1)) { 1.47 + lua_pushvalue(L, 2); /* function */ 1.48 + lua_pushvalue(L, -3); /* key */ 1.49 + lua_pushvalue(L, -3); /* value */ 1.50 + lua_call(L, 2, 1); 1.51 + if (!lua_isnil(L, -1)) 1.52 + return 1; 1.53 + lua_pop(L, 2); /* remove value and result */ 1.54 + } 1.55 + return 0; 1.56 +} 1.57 + 1.58 + 1.59 +static int maxn (lua_State *L) { 1.60 + lua_Number max = 0; 1.61 + luaL_checktype(L, 1, LUA_TTABLE); 1.62 + lua_pushnil(L); /* first key */ 1.63 + while (lua_next(L, 1)) { 1.64 + lua_pop(L, 1); /* remove value */ 1.65 + if (lua_type(L, -1) == LUA_TNUMBER) { 1.66 + lua_Number v = lua_tonumber(L, -1); 1.67 + if (v > max) max = v; 1.68 + } 1.69 + } 1.70 + lua_pushnumber(L, max); 1.71 + return 1; 1.72 +} 1.73 + 1.74 + 1.75 +static int getn (lua_State *L) { 1.76 + lua_pushinteger(L, aux_getn(L, 1)); 1.77 + return 1; 1.78 +} 1.79 + 1.80 + 1.81 +static int setn (lua_State *L) { 1.82 + luaL_checktype(L, 1, LUA_TTABLE); 1.83 +#ifndef luaL_setn 1.84 + luaL_setn(L, 1, luaL_checkint(L, 2)); 1.85 +#else 1.86 + luaL_error(L, LUA_QL("setn") " is obsolete"); 1.87 +#endif 1.88 + lua_pushvalue(L, 1); 1.89 + return 1; 1.90 +} 1.91 + 1.92 + 1.93 +static int tinsert (lua_State *L) { 1.94 + int e = aux_getn(L, 1) + 1; /* first empty element */ 1.95 + int pos; /* where to insert new element */ 1.96 + switch (lua_gettop(L)) { 1.97 + case 2: { /* called with only 2 arguments */ 1.98 + pos = e; /* insert new element at the end */ 1.99 + break; 1.100 + } 1.101 + case 3: { 1.102 + int i; 1.103 + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ 1.104 + if (pos > e) e = pos; /* `grow' array if necessary */ 1.105 + for (i = e; i > pos; i--) { /* move up elements */ 1.106 + lua_rawgeti(L, 1, i-1); 1.107 + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ 1.108 + } 1.109 + break; 1.110 + } 1.111 + default: { 1.112 + return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); 1.113 + } 1.114 + } 1.115 + luaL_setn(L, 1, e); /* new size */ 1.116 + lua_rawseti(L, 1, pos); /* t[pos] = v */ 1.117 + return 0; 1.118 +} 1.119 + 1.120 + 1.121 +static int tremove (lua_State *L) { 1.122 + int e = aux_getn(L, 1); 1.123 + int pos = luaL_optint(L, 2, e); 1.124 + if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ 1.125 + return 0; /* nothing to remove */ 1.126 + luaL_setn(L, 1, e - 1); /* t.n = n-1 */ 1.127 + lua_rawgeti(L, 1, pos); /* result = t[pos] */ 1.128 + for ( ;pos<e; pos++) { 1.129 + lua_rawgeti(L, 1, pos+1); 1.130 + lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ 1.131 + } 1.132 + lua_pushnil(L); 1.133 + lua_rawseti(L, 1, e); /* t[e] = nil */ 1.134 + return 1; 1.135 +} 1.136 + 1.137 + 1.138 +static void addfield (lua_State *L, luaL_Buffer *b, int i) { 1.139 + lua_rawgeti(L, 1, i); 1.140 + if (!lua_isstring(L, -1)) 1.141 + luaL_error(L, "invalid value (%s) at index %d in table for " 1.142 + LUA_QL("concat"), luaL_typename(L, -1), i); 1.143 + luaL_addvalue(b); 1.144 +} 1.145 + 1.146 + 1.147 +static int tconcat (lua_State *L) { 1.148 + luaL_Buffer b; 1.149 + size_t lsep; 1.150 + int i, last; 1.151 + const char *sep = luaL_optlstring(L, 2, "", &lsep); 1.152 + luaL_checktype(L, 1, LUA_TTABLE); 1.153 + i = luaL_optint(L, 3, 1); 1.154 + last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); 1.155 + luaL_buffinit(L, &b); 1.156 + for (; i < last; i++) { 1.157 + addfield(L, &b, i); 1.158 + luaL_addlstring(&b, sep, lsep); 1.159 + } 1.160 + if (i == last) /* add last value (if interval was not empty) */ 1.161 + addfield(L, &b, i); 1.162 + luaL_pushresult(&b); 1.163 + return 1; 1.164 +} 1.165 + 1.166 + 1.167 + 1.168 +/* 1.169 +** {====================================================== 1.170 +** Quicksort 1.171 +** (based on `Algorithms in MODULA-3', Robert Sedgewick; 1.172 +** Addison-Wesley, 1993.) 1.173 +*/ 1.174 + 1.175 + 1.176 +static void set2 (lua_State *L, int i, int j) { 1.177 + lua_rawseti(L, 1, i); 1.178 + lua_rawseti(L, 1, j); 1.179 +} 1.180 + 1.181 +static int sort_comp (lua_State *L, int a, int b) { 1.182 + if (!lua_isnil(L, 2)) { /* function? */ 1.183 + int res; 1.184 + lua_pushvalue(L, 2); 1.185 + lua_pushvalue(L, a-1); /* -1 to compensate function */ 1.186 + lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ 1.187 + lua_call(L, 2, 1); 1.188 + res = lua_toboolean(L, -1); 1.189 + lua_pop(L, 1); 1.190 + return res; 1.191 + } 1.192 + else /* a < b? */ 1.193 + return lua_lessthan(L, a, b); 1.194 +} 1.195 + 1.196 +static void auxsort (lua_State *L, int l, int u) { 1.197 + while (l < u) { /* for tail recursion */ 1.198 + int i, j; 1.199 + /* sort elements a[l], a[(l+u)/2] and a[u] */ 1.200 + lua_rawgeti(L, 1, l); 1.201 + lua_rawgeti(L, 1, u); 1.202 + if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ 1.203 + set2(L, l, u); /* swap a[l] - a[u] */ 1.204 + else 1.205 + lua_pop(L, 2); 1.206 + if (u-l == 1) break; /* only 2 elements */ 1.207 + i = (l+u)/2; 1.208 + lua_rawgeti(L, 1, i); 1.209 + lua_rawgeti(L, 1, l); 1.210 + if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ 1.211 + set2(L, i, l); 1.212 + else { 1.213 + lua_pop(L, 1); /* remove a[l] */ 1.214 + lua_rawgeti(L, 1, u); 1.215 + if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ 1.216 + set2(L, i, u); 1.217 + else 1.218 + lua_pop(L, 2); 1.219 + } 1.220 + if (u-l == 2) break; /* only 3 elements */ 1.221 + lua_rawgeti(L, 1, i); /* Pivot */ 1.222 + lua_pushvalue(L, -1); 1.223 + lua_rawgeti(L, 1, u-1); 1.224 + set2(L, i, u-1); 1.225 + /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ 1.226 + i = l; j = u-1; 1.227 + for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ 1.228 + /* repeat ++i until a[i] >= P */ 1.229 + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { 1.230 + if (i>u) luaL_error(L, "invalid order function for sorting"); 1.231 + lua_pop(L, 1); /* remove a[i] */ 1.232 + } 1.233 + /* repeat --j until a[j] <= P */ 1.234 + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { 1.235 + if (j<l) luaL_error(L, "invalid order function for sorting"); 1.236 + lua_pop(L, 1); /* remove a[j] */ 1.237 + } 1.238 + if (j<i) { 1.239 + lua_pop(L, 3); /* pop pivot, a[i], a[j] */ 1.240 + break; 1.241 + } 1.242 + set2(L, i, j); 1.243 + } 1.244 + lua_rawgeti(L, 1, u-1); 1.245 + lua_rawgeti(L, 1, i); 1.246 + set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ 1.247 + /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ 1.248 + /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ 1.249 + if (i-l < u-i) { 1.250 + j=l; i=i-1; l=i+2; 1.251 + } 1.252 + else { 1.253 + j=i+1; i=u; u=j-2; 1.254 + } 1.255 + auxsort(L, j, i); /* call recursively the smaller one */ 1.256 + } /* repeat the routine for the larger one */ 1.257 +} 1.258 + 1.259 +static int sort (lua_State *L) { 1.260 + int n = aux_getn(L, 1); 1.261 + luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ 1.262 + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ 1.263 + luaL_checktype(L, 2, LUA_TFUNCTION); 1.264 + lua_settop(L, 2); /* make sure there is two arguments */ 1.265 + auxsort(L, 1, n); 1.266 + return 0; 1.267 +} 1.268 + 1.269 +/* }====================================================== */ 1.270 + 1.271 + 1.272 +static const luaL_Reg tab_funcs[] = { 1.273 + {"concat", tconcat}, 1.274 + {"foreach", foreach}, 1.275 + {"foreachi", foreachi}, 1.276 + {"getn", getn}, 1.277 + {"maxn", maxn}, 1.278 + {"insert", tinsert}, 1.279 + {"remove", tremove}, 1.280 + {"setn", setn}, 1.281 + {"sort", sort}, 1.282 + {NULL, NULL} 1.283 +}; 1.284 + 1.285 + 1.286 +LUALIB_API int luaopen_table (lua_State *L) { 1.287 + luaL_register(L, LUA_TABLIBNAME, tab_funcs); 1.288 + return 1; 1.289 +} 1.290 +