aboutsummaryrefslogtreecommitdiff
path: root/ltablib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-07-01 16:25:28 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-07-01 16:25:28 -0300
commit76a73cb2eef71eac3c93e9263443131164ee9fb9 (patch)
treef3ab35adb7cbc484f89473d9275ead30a02ff0b6 /ltablib.c
parentaa3da1605ceb50fe8353ecb7d03b6f074e131284 (diff)
downloadlua-76a73cb2eef71eac3c93e9263443131164ee9fb9.tar.gz
lua-76a73cb2eef71eac3c93e9263443131164ee9fb9.tar.bz2
lua-76a73cb2eef71eac3c93e9263443131164ee9fb9.zip
new `getn' (and `setn')
Diffstat (limited to 'ltablib.c')
-rw-r--r--ltablib.c127
1 files changed, 97 insertions, 30 deletions
diff --git a/ltablib.c b/ltablib.c
index d1d56748..b7ab7a63 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltablib.c,v 1.7 2002/06/18 15:16:18 roberto Exp roberto $ 2** $Id: ltablib.c,v 1.8 2002/06/25 19:16:44 roberto Exp roberto $
3** Library for Table Manipulation 3** Library for Table Manipulation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -15,12 +15,57 @@
15 15
16 16
17 17
18static int checkint (lua_State *L) {
19 int n = lua_tonumber(L, -1);
20 if (n == 0 && !lua_isnumber(L, -1)) n = -1;
21 lua_pop(L, 1);
22 return n;
23}
24
25
26static void aux_setn (lua_State *L, int t, int n) {
27 lua_pushliteral(L, "n");
28 lua_rawget(L, t);
29 if (checkint(L) >= 0) {
30 lua_pushliteral(L, "n"); /* use it */
31 lua_pushnumber(L, n);
32 lua_rawset(L, t);
33 }
34 else { /* use N */
35 lua_pushvalue(L, t);
36 lua_pushnumber(L, n);
37 lua_rawset(L, lua_upvalueindex(1)); /* N[t] = n */
38 }
39}
40
41
42static int aux_getn (lua_State *L, int t) {
43 int n;
44 luaL_check_type(L, t, LUA_TTABLE);
45 lua_pushliteral(L, "n"); /* try t.n */
46 lua_rawget(L, t);
47 if ((n = checkint(L)) >= 0) return n;
48 lua_pushvalue(L, t); /* try N[t] */
49 lua_rawget(L, lua_upvalueindex(1));
50 if ((n = checkint(L)) >= 0) return n;
51 else { /* must count elements */
52 n = 0;
53 for (;;) {
54 lua_rawgeti(L, t, ++n);
55 if (lua_isnil(L, -1)) break;
56 lua_pop(L, 1);
57 }
58 lua_pop(L, 1);
59 aux_setn(L, t, n - 1);
60 return n - 1;
61 }
62}
63
18 64
19static int luaB_foreachi (lua_State *L) { 65static int luaB_foreachi (lua_State *L) {
20 int n, i; 66 int i;
21 luaL_check_type(L, 1, LUA_TTABLE); 67 int n = aux_getn(L, 1);
22 luaL_check_type(L, 2, LUA_TFUNCTION); 68 luaL_check_type(L, 2, LUA_TFUNCTION);
23 n = lua_getn(L, 1);
24 for (i=1; i<=n; i++) { 69 for (i=1; i<=n; i++) {
25 lua_pushvalue(L, 2); /* function */ 70 lua_pushvalue(L, 2); /* function */
26 lua_pushnumber(L, i); /* 1st argument */ 71 lua_pushnumber(L, i); /* 1st argument */
@@ -52,34 +97,32 @@ static int luaB_foreach (lua_State *L) {
52} 97}
53 98
54 99
55static void aux_setn (lua_State *L, int t, int n) { 100static int luaB_getn (lua_State *L) {
56 lua_pushliteral(L, "n"); 101 lua_pushnumber(L, aux_getn(L, 1));
57 lua_pushnumber(L, n); 102 return 1;
58 lua_rawset(L, t);
59} 103}
60 104
61 105
62static int luaB_getn (lua_State *L) { 106static int luaB_setn (lua_State *L) {
63 luaL_check_type(L, 1, LUA_TTABLE); 107 luaL_check_type(L, 1, LUA_TTABLE);
64 lua_pushnumber(L, lua_getn(L, 1)); 108 aux_setn(L, 1, luaL_check_int(L, 2));
65 return 1; 109 return 0;
66} 110}
67 111
68 112
69static int luaB_tinsert (lua_State *L) { 113static int luaB_tinsert (lua_State *L) {
70 int v = lua_gettop(L); /* number of arguments */ 114 int v = lua_gettop(L); /* number of arguments */
71 int n, pos; 115 int n = aux_getn(L, 1) + 1;
72 luaL_check_type(L, 1, LUA_TTABLE); 116 int pos; /* where to insert new element */
73 n = lua_getn(L, 1);
74 if (v == 2) /* called with only 2 arguments */ 117 if (v == 2) /* called with only 2 arguments */
75 pos = n+1; 118 pos = n; /* insert new element at the end */
76 else { 119 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 */ 120 pos = luaL_check_int(L, 2); /* 2nd argument is the position */
121 if (pos > n) n = pos; /* `grow' array if necessary */
122 v = 3; /* function may be called with more than 3 args */
79 } 123 }
80 if (pos > n+1) n = pos-1; 124 aux_setn(L, 1, n); /* new size */
81 aux_setn(L, 1, n+1); /* t.n = n+1 */ 125 while (--n >= pos) { /* move up elements */
82 for (; n>=pos; n--) {
83 lua_rawgeti(L, 1, n); 126 lua_rawgeti(L, 1, n);
84 lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ 127 lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
85 } 128 }
@@ -90,16 +133,14 @@ static int luaB_tinsert (lua_State *L) {
90 133
91 134
92static int luaB_tremove (lua_State *L) { 135static int luaB_tremove (lua_State *L) {
93 int pos, n; 136 int n = aux_getn(L, 1);
94 luaL_check_type(L, 1, LUA_TTABLE); 137 int pos = luaL_opt_int(L, 2, n);
95 n = lua_getn(L, 1);
96 pos = luaL_opt_int(L, 2, n);
97 if (n <= 0) return 0; /* table is `empty' */ 138 if (n <= 0) return 0; /* table is `empty' */
98 aux_setn(L, 1, n-1); /* t.n = n-1 */ 139 aux_setn(L, 1, n-1); /* t.n = n-1 */
99 lua_rawgeti(L, 1, pos); /* result = t[pos] */ 140 lua_rawgeti(L, 1, pos); /* result = t[pos] */
100 for ( ;pos<n; pos++) { 141 for ( ;pos<n; pos++) {
101 lua_rawgeti(L, 1, pos+1); 142 lua_rawgeti(L, 1, pos+1);
102 lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */ 143 lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
103 } 144 }
104 lua_pushnil(L); 145 lua_pushnil(L);
105 lua_rawseti(L, 1, n); /* t[n] = nil */ 146 lua_rawseti(L, 1, n); /* t[n] = nil */
@@ -107,6 +148,26 @@ static int luaB_tremove (lua_State *L) {
107} 148}
108 149
109 150
151static int str_concat (lua_State *L) {
152 luaL_Buffer b;
153 int n = aux_getn(L, 1);
154 size_t lsep;
155 const char *sep = luaL_opt_lstr(L, 2, "", &lsep);
156 int i;
157 luaL_buffinit(L, &b);
158 for (i=1; i<=n; i++) {
159 lua_rawgeti(L, 1, i);
160 luaL_arg_check(L, lua_isstring(L, -1), 1,
161 "table contains non-strings");
162 luaL_addvalue(&b);
163 if (i != n)
164 luaL_addlstring(&b, sep, lsep);
165 }
166 luaL_pushresult(&b);
167 return 1;
168}
169
170
110 171
111/* 172/*
112** {====================================================== 173** {======================================================
@@ -122,8 +183,7 @@ static void set2 (lua_State *L, int i, int j) {
122} 183}
123 184
124static int sort_comp (lua_State *L, int a, int b) { 185static int sort_comp (lua_State *L, int a, int b) {
125 /* WARNING: the caller (auxsort) must ensure stack space */ 186 if (!lua_isnil(L, 2)) { /* function? */
126 if (!lua_isnoneornil(L, 2)) { /* function? */
127 int res; 187 int res;
128 lua_pushvalue(L, 2); 188 lua_pushvalue(L, 2);
129 lua_pushvalue(L, a-1); /* -1 to compensate function */ 189 lua_pushvalue(L, a-1); /* -1 to compensate function */
@@ -201,9 +261,8 @@ static void auxsort (lua_State *L, int l, int u) {
201} 261}
202 262
203static int luaB_sort (lua_State *L) { 263static int luaB_sort (lua_State *L) {
204 int n; 264 int n = aux_getn(L, 1);
205 luaL_check_type(L, 1, LUA_TTABLE); 265 luaL_check_stack(L, 40, ""); /* assume array is smaller than 2^40 */
206 n = lua_getn(L, 1);
207 if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ 266 if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
208 luaL_check_type(L, 2, LUA_TFUNCTION); 267 luaL_check_type(L, 2, LUA_TFUNCTION);
209 lua_settop(L, 2); /* make sure there is two arguments */ 268 lua_settop(L, 2); /* make sure there is two arguments */
@@ -215,9 +274,11 @@ static int luaB_sort (lua_State *L) {
215 274
216 275
217static const luaL_reg tab_funcs[] = { 276static const luaL_reg tab_funcs[] = {
277 {"concat", str_concat},
218 {"foreach", luaB_foreach}, 278 {"foreach", luaB_foreach},
219 {"foreachi", luaB_foreachi}, 279 {"foreachi", luaB_foreachi},
220 {"getn", luaB_getn}, 280 {"getn", luaB_getn},
281 {"setn", luaB_setn},
221 {"sort", luaB_sort}, 282 {"sort", luaB_sort},
222 {"insert", luaB_tinsert}, 283 {"insert", luaB_tinsert},
223 {"remove", luaB_tremove}, 284 {"remove", luaB_tremove},
@@ -226,7 +287,13 @@ static const luaL_reg tab_funcs[] = {
226 287
227 288
228LUALIB_API int lua_tablibopen (lua_State *L) { 289LUALIB_API int lua_tablibopen (lua_State *L) {
229 luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 0); 290 lua_newtable(L); /* create N (table to store num. elements in tables) */
291 lua_pushvalue(L, -1);
292 lua_setmetatable(L, -2); /* make it its own metatable */
293 lua_pushliteral(L, "__mode");
294 lua_pushliteral(L, "k");
295 lua_rawset(L, -3); /* make it a weak table */
296 luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1);
230 return 0; 297 return 0;
231} 298}
232 299