aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-09 17:19:06 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-04-09 17:19:06 -0300
commitaf4721f7a37834e5b5469f342caed0629932a4aa (patch)
tree6077968abadf7864178714d31c6f7cdc69233877
parent018e50ad7f24aa8f8f4afe50d513964624c4ca35 (diff)
downloadlua-af4721f7a37834e5b5469f342caed0629932a4aa.tar.gz
lua-af4721f7a37834e5b5469f342caed0629932a4aa.tar.bz2
lua-af4721f7a37834e5b5469f342caed0629932a4aa.zip
library with table manipulation functions
-rw-r--r--ltablib.c308
1 files changed, 308 insertions, 0 deletions
diff --git a/ltablib.c b/ltablib.c
new file mode 100644
index 00000000..292a8f7a
--- /dev/null
+++ b/ltablib.c
@@ -0,0 +1,308 @@
1/*
2** $Id: $
3** Library for Table Manipulation
4** See Copyright Notice in lua.h
5*/
6
7
8#include <stddef.h>
9
10#include "lua.h"
11
12#include "lauxlib.h"
13#include "luadebug.h"
14#include "lualib.h"
15
16
17
18
19static int luaB_foreachi (lua_State *L) {
20 int n, i;
21 luaL_check_type(L, 1, LUA_TTABLE);
22 luaL_check_type(L, 2, LUA_TFUNCTION);
23 n = lua_getn(L, 1);
24 for (i=1; i<=n; i++) {
25 lua_pushvalue(L, 2); /* function */
26 lua_pushnumber(L, i); /* 1st argument */
27 lua_rawgeti(L, 1, i); /* 2nd argument */
28 lua_rawcall(L, 2, 1);
29 if (!lua_isnil(L, -1))
30 return 1;
31 lua_pop(L, 1); /* remove nil result */
32 }
33 return 0;
34}
35
36
37static int luaB_foreach (lua_State *L) {
38 luaL_check_type(L, 1, LUA_TTABLE);
39 luaL_check_type(L, 2, LUA_TFUNCTION);
40 lua_pushnil(L); /* first key */
41 for (;;) {
42 if (lua_next(L, 1) == 0)
43 return 0;
44 lua_pushvalue(L, 2); /* function */
45 lua_pushvalue(L, -3); /* key */
46 lua_pushvalue(L, -3); /* value */
47 lua_rawcall(L, 2, 1);
48 if (!lua_isnil(L, -1))
49 return 1;
50 lua_pop(L, 2); /* remove value and result */
51 }
52}
53
54
55static void aux_setn (lua_State *L, int t, int n) {
56 lua_pushliteral(L, "n");
57 lua_pushnumber(L, n);
58 lua_rawset(L, t);
59}
60
61
62static int luaB_getn (lua_State *L) {
63 luaL_check_type(L, 1, LUA_TTABLE);
64 lua_pushnumber(L, lua_getn(L, 1));
65 return 1;
66}
67
68
69static int luaB_tinsert (lua_State *L) {
70 int v = lua_gettop(L); /* number of arguments */
71 int n, pos;
72 luaL_check_type(L, 1, LUA_TTABLE);
73 n = lua_getn(L, 1);
74 if (v == 2) /* called with only 2 arguments */
75 pos = n+1;
76 else {
77 v = 3; /* function may be called with more than 3 args */
78 pos = luaL_check_int(L, 2); /* 2nd argument is the position */
79 }
80 if (pos > n+1) n = pos-1;
81 aux_setn(L, 1, n+1); /* t.n = n+1 */
82 for (; n>=pos; n--) {
83 lua_rawgeti(L, 1, n);
84 lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
85 }
86 lua_pushvalue(L, v);
87 lua_rawseti(L, 1, pos); /* t[pos] = v */
88 return 0;
89}
90
91
92static int luaB_tremove (lua_State *L) {
93 int pos, n;
94 luaL_check_type(L, 1, LUA_TTABLE);
95 n = lua_getn(L, 1);
96 pos = luaL_opt_int(L, 2, n);
97 if (n <= 0) return 0; /* table is `empty' */
98 aux_setn(L, 1, n-1); /* t.n = n-1 */
99 lua_rawgeti(L, 1, pos); /* result = t[pos] */
100 for ( ;pos<n; pos++) {
101 lua_rawgeti(L, 1, pos+1);
102 lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */
103 }
104 lua_pushnil(L);
105 lua_rawseti(L, 1, n); /* t[n] = nil */
106 return 1;
107}
108
109
110
111/*
112** {======================================================
113** Quicksort
114** (based on `Algorithms in MODULA-3', Robert Sedgewick;
115** Addison-Wesley, 1993.)
116*/
117
118
119static void set2 (lua_State *L, int i, int j) {
120 lua_rawseti(L, 1, i);
121 lua_rawseti(L, 1, j);
122}
123
124static int sort_comp (lua_State *L, int a, int b) {
125 /* WARNING: the caller (auxsort) must ensure stack space */
126 if (!lua_isnoneornil(L, 2)) { /* function? */
127 int res;
128 lua_pushvalue(L, 2);
129 lua_pushvalue(L, a-1); /* -1 to compensate function */
130 lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
131 lua_rawcall(L, 2, 1);
132 res = lua_toboolean(L, -1);
133 lua_pop(L, 1);
134 return res;
135 }
136 else /* a < b? */
137 return lua_lessthan(L, a, b);
138}
139
140static void auxsort (lua_State *L, int l, int u) {
141 while (l < u) { /* for tail recursion */
142 int i, j;
143 /* sort elements a[l], a[(l+u)/2] and a[u] */
144 lua_rawgeti(L, 1, l);
145 lua_rawgeti(L, 1, u);
146 if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
147 set2(L, l, u); /* swap a[l] - a[u] */
148 else
149 lua_pop(L, 2);
150 if (u-l == 1) break; /* only 2 elements */
151 i = (l+u)/2;
152 lua_rawgeti(L, 1, i);
153 lua_rawgeti(L, 1, l);
154 if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
155 set2(L, i, l);
156 else {
157 lua_pop(L, 1); /* remove a[l] */
158 lua_rawgeti(L, 1, u);
159 if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
160 set2(L, i, u);
161 else
162 lua_pop(L, 2);
163 }
164 if (u-l == 2) break; /* only 3 elements */
165 lua_rawgeti(L, 1, i); /* Pivot */
166 lua_pushvalue(L, -1);
167 lua_rawgeti(L, 1, u-1);
168 set2(L, i, u-1);
169 /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
170 i = l; j = u-1;
171 for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
172 /* repeat ++i until a[i] >= P */
173 while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
174 if (i>u) lua_error(L, "invalid order function for sorting");
175 lua_pop(L, 1); /* remove a[i] */
176 }
177 /* repeat --j until a[j] <= P */
178 while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
179 if (j<l) lua_error(L, "invalid order function for sorting");
180 lua_pop(L, 1); /* remove a[j] */
181 }
182 if (j<i) {
183 lua_pop(L, 3); /* pop pivot, a[i], a[j] */
184 break;
185 }
186 set2(L, i, j);
187 }
188 lua_rawgeti(L, 1, u-1);
189 lua_rawgeti(L, 1, i);
190 set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
191 /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
192 /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
193 if (i-l < u-i) {
194 j=l; i=i-1; l=i+2;
195 }
196 else {
197 j=i+1; i=u; u=j-2;
198 }
199 auxsort(L, j, i); /* call recursively the smaller one */
200 } /* repeat the routine for the larger one */
201}
202
203static int luaB_sort (lua_State *L) {
204 int n;
205 luaL_check_type(L, 1, LUA_TTABLE);
206 n = lua_getn(L, 1);
207 if (!lua_isnone(L, 2)) /* is there a 2nd argument? */
208 luaL_check_type(L, 2, LUA_TFUNCTION);
209 lua_settop(L, 2); /* make sure there is two arguments */
210 auxsort(L, 1, n);
211 return 0;
212}
213
214/* }====================================================== */
215
216
217/*
218** {======================================================
219** Coroutine library
220** =======================================================
221*/
222
223
224static int luaB_resume (lua_State *L) {
225 lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1));
226 lua_settop(L, 0);
227 if (lua_resume(L, co) != 0)
228 lua_error(L, "error running co-routine");
229 return lua_gettop(L);
230}
231
232
233
234static int gc_coroutine (lua_State *L) {
235 lua_State *co = (lua_State *)lua_getfrombox(L, 1);
236 lua_closethread(L, co);
237 return 0;
238}
239
240
241static int luaB_coroutine (lua_State *L) {
242 lua_State *NL;
243 int ref;
244 int i;
245 int n = lua_gettop(L);
246 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
247 "Lua function expected");
248 NL = lua_newthread(L);
249 if (NL == NULL) lua_error(L, "unable to create new thread");
250 /* move function and arguments from L to NL */
251 for (i=0; i<n; i++) {
252 ref = lua_ref(L, 1);
253 lua_getref(NL, ref);
254 lua_insert(NL, 1);
255 lua_unref(L, ref);
256 }
257 lua_cobegin(NL, n-1);
258 lua_newpointerbox(L, NL);
259 lua_pushliteral(L, "Coroutine");
260 lua_rawget(L, LUA_REGISTRYINDEX);
261 lua_setmetatable(L, -2);
262 lua_pushcclosure(L, luaB_resume, 1);
263 return 1;
264}
265
266
267static int luaB_yield (lua_State *L) {
268 return lua_yield(L, lua_gettop(L));
269}
270
271static const luaL_reg co_funcs[] = {
272 {"create", luaB_coroutine},
273 {"yield", luaB_yield},
274 {NULL, NULL}
275};
276
277
278static void co_open (lua_State *L) {
279 luaL_opennamedlib(L, "co", co_funcs, 0);
280 /* create metatable for coroutines */
281 lua_pushliteral(L, "Coroutine");
282 lua_newtable(L);
283 lua_pushliteral(L, "__gc");
284 lua_pushcfunction(L, gc_coroutine);
285 lua_rawset(L, -3);
286 lua_rawset(L, LUA_REGISTRYINDEX);
287}
288
289/* }====================================================== */
290
291
292static const luaL_reg tab_funcs[] = {
293 {"foreach", luaB_foreach},
294 {"foreachi", luaB_foreachi},
295 {"getn", luaB_getn},
296 {"sort", luaB_sort},
297 {"insert", luaB_tinsert},
298 {"remove", luaB_tremove},
299 {NULL, NULL}
300};
301
302
303LUALIB_API int lua_tablibopen (lua_State *L) {
304 luaL_opennamedlib(L, "tab", tab_funcs, 0);
305 co_open(L);
306 return 0;
307}
308