1 /* $NetBSD: ltablib.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */
4 ** $Id: ltablib.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $
5 ** Library for Table Manipulation
6 ** See Copyright Notice in lua.h
21 #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
24 static int foreachi (lua_State
*L
) {
26 int n
= aux_getn(L
, 1);
27 luaL_checktype(L
, 2, LUA_TFUNCTION
);
28 for (i
=1; i
<= n
; i
++) {
29 lua_pushvalue(L
, 2); /* function */
30 lua_pushinteger(L
, i
); /* 1st argument */
31 lua_rawgeti(L
, 1, i
); /* 2nd argument */
33 if (!lua_isnil(L
, -1))
35 lua_pop(L
, 1); /* remove nil result */
41 static int foreach (lua_State
*L
) {
42 luaL_checktype(L
, 1, LUA_TTABLE
);
43 luaL_checktype(L
, 2, LUA_TFUNCTION
);
44 lua_pushnil(L
); /* first key */
45 while (lua_next(L
, 1)) {
46 lua_pushvalue(L
, 2); /* function */
47 lua_pushvalue(L
, -3); /* key */
48 lua_pushvalue(L
, -3); /* value */
50 if (!lua_isnil(L
, -1))
52 lua_pop(L
, 2); /* remove value and result */
58 static int maxn (lua_State
*L
) {
60 luaL_checktype(L
, 1, LUA_TTABLE
);
61 lua_pushnil(L
); /* first key */
62 while (lua_next(L
, 1)) {
63 lua_pop(L
, 1); /* remove value */
64 if (lua_type(L
, -1) == LUA_TNUMBER
) {
65 lua_Number v
= lua_tonumber(L
, -1);
69 lua_pushnumber(L
, max
);
74 static int getn (lua_State
*L
) {
75 lua_pushinteger(L
, aux_getn(L
, 1));
80 static int setn (lua_State
*L
) {
81 luaL_checktype(L
, 1, LUA_TTABLE
);
83 luaL_setn(L
, 1, luaL_checkint(L
, 2));
85 luaL_error(L
, LUA_QL("setn") " is obsolete");
92 static int tinsert (lua_State
*L
) {
93 int e
= aux_getn(L
, 1) + 1; /* first empty element */
94 int pos
; /* where to insert new element */
95 switch (lua_gettop(L
)) {
96 case 2: { /* called with only 2 arguments */
97 pos
= e
; /* insert new element at the end */
102 pos
= luaL_checkint(L
, 2); /* 2nd argument is the position */
103 if (pos
> e
) e
= pos
; /* `grow' array if necessary */
104 for (i
= e
; i
> pos
; i
--) { /* move up elements */
105 lua_rawgeti(L
, 1, i
-1);
106 lua_rawseti(L
, 1, i
); /* t[i] = t[i-1] */
111 return luaL_error(L
, "wrong number of arguments to " LUA_QL("insert"));
114 luaL_setn(L
, 1, e
); /* new size */
115 lua_rawseti(L
, 1, pos
); /* t[pos] = v */
120 static int tremove (lua_State
*L
) {
121 int e
= aux_getn(L
, 1);
122 int pos
= luaL_optint(L
, 2, e
);
123 if (!(1 <= pos
&& pos
<= e
)) /* position is outside bounds? */
124 return 0; /* nothing to remove */
125 luaL_setn(L
, 1, e
- 1); /* t.n = n-1 */
126 lua_rawgeti(L
, 1, pos
); /* result = t[pos] */
127 for ( ;pos
<e
; pos
++) {
128 lua_rawgeti(L
, 1, pos
+1);
129 lua_rawseti(L
, 1, pos
); /* t[pos] = t[pos+1] */
132 lua_rawseti(L
, 1, e
); /* t[e] = nil */
137 static void addfield (lua_State
*L
, luaL_Buffer
*b
, int i
) {
138 lua_rawgeti(L
, 1, i
);
139 if (!lua_isstring(L
, -1))
140 luaL_error(L
, "invalid value (%s) at index %d in table for "
141 LUA_QL("concat"), luaL_typename(L
, -1), i
);
146 static int tconcat (lua_State
*L
) {
150 const char *sep
= luaL_optlstring(L
, 2, "", &lsep
);
151 luaL_checktype(L
, 1, LUA_TTABLE
);
152 i
= luaL_optint(L
, 3, 1);
153 last
= luaL_opt(L
, luaL_checkint
, 4, luaL_getn(L
, 1));
154 luaL_buffinit(L
, &b
);
155 for (; i
< last
; i
++) {
157 luaL_addlstring(&b
, sep
, lsep
);
159 if (i
== last
) /* add last value (if interval was not empty) */
168 ** {======================================================
170 ** (based on `Algorithms in MODULA-3', Robert Sedgewick;
171 ** Addison-Wesley, 1993.)
175 static void set2 (lua_State
*L
, int i
, int j
) {
176 lua_rawseti(L
, 1, i
);
177 lua_rawseti(L
, 1, j
);
180 static int sort_comp (lua_State
*L
, int a
, int b
) {
181 if (!lua_isnil(L
, 2)) { /* function? */
184 lua_pushvalue(L
, a
-1); /* -1 to compensate function */
185 lua_pushvalue(L
, b
-2); /* -2 to compensate function and `a' */
187 res
= lua_toboolean(L
, -1);
192 return lua_lessthan(L
, a
, b
);
195 static void auxsort (lua_State
*L
, int l
, int u
) {
196 while (l
< u
) { /* for tail recursion */
198 /* sort elements a[l], a[(l+u)/2] and a[u] */
199 lua_rawgeti(L
, 1, l
);
200 lua_rawgeti(L
, 1, u
);
201 if (sort_comp(L
, -1, -2)) /* a[u] < a[l]? */
202 set2(L
, l
, u
); /* swap a[l] - a[u] */
205 if (u
-l
== 1) break; /* only 2 elements */
207 lua_rawgeti(L
, 1, i
);
208 lua_rawgeti(L
, 1, l
);
209 if (sort_comp(L
, -2, -1)) /* a[i]<a[l]? */
212 lua_pop(L
, 1); /* remove a[l] */
213 lua_rawgeti(L
, 1, u
);
214 if (sort_comp(L
, -1, -2)) /* a[u]<a[i]? */
219 if (u
-l
== 2) break; /* only 3 elements */
220 lua_rawgeti(L
, 1, i
); /* Pivot */
221 lua_pushvalue(L
, -1);
222 lua_rawgeti(L
, 1, u
-1);
224 /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
226 for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
227 /* repeat ++i until a[i] >= P */
228 while (lua_rawgeti(L
, 1, ++i
), sort_comp(L
, -1, -2)) {
229 if (i
>u
) luaL_error(L
, "invalid order function for sorting");
230 lua_pop(L
, 1); /* remove a[i] */
232 /* repeat --j until a[j] <= P */
233 while (lua_rawgeti(L
, 1, --j
), sort_comp(L
, -3, -1)) {
234 if (j
<l
) luaL_error(L
, "invalid order function for sorting");
235 lua_pop(L
, 1); /* remove a[j] */
238 lua_pop(L
, 3); /* pop pivot, a[i], a[j] */
243 lua_rawgeti(L
, 1, u
-1);
244 lua_rawgeti(L
, 1, i
);
245 set2(L
, u
-1, i
); /* swap pivot (a[u-1]) with a[i] */
246 /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
247 /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
254 auxsort(L
, j
, i
); /* call recursively the smaller one */
255 } /* repeat the routine for the larger one */
258 static int sort (lua_State
*L
) {
259 int n
= aux_getn(L
, 1);
260 luaL_checkstack(L
, 40, ""); /* assume array is smaller than 2^40 */
261 if (!lua_isnoneornil(L
, 2)) /* is there a 2nd argument? */
262 luaL_checktype(L
, 2, LUA_TFUNCTION
);
263 lua_settop(L
, 2); /* make sure there is two arguments */
268 /* }====================================================== */
271 static const luaL_Reg tab_funcs
[] = {
273 {"foreach", foreach
},
274 {"foreachi", foreachi
},
285 LUALIB_API
int luaopen_table (lua_State
*L
) {
286 luaL_register(L
, LUA_TABLIBNAME
, tab_funcs
);