diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-07-01 16:25:28 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-07-01 16:25:28 -0300 |
| commit | 76a73cb2eef71eac3c93e9263443131164ee9fb9 (patch) | |
| tree | f3ab35adb7cbc484f89473d9275ead30a02ff0b6 | |
| parent | aa3da1605ceb50fe8353ecb7d03b6f074e131284 (diff) | |
| download | lua-76a73cb2eef71eac3c93e9263443131164ee9fb9.tar.gz lua-76a73cb2eef71eac3c93e9263443131164ee9fb9.tar.bz2 lua-76a73cb2eef71eac3c93e9263443131164ee9fb9.zip | |
new `getn' (and `setn')
| -rw-r--r-- | ltablib.c | 127 |
1 files changed, 97 insertions, 30 deletions
| @@ -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 | ||
| 18 | static 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 | |||
| 26 | static 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 | |||
| 42 | static 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 | ||
| 19 | static int luaB_foreachi (lua_State *L) { | 65 | static 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 | ||
| 55 | static void aux_setn (lua_State *L, int t, int n) { | 100 | static 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 | ||
| 62 | static int luaB_getn (lua_State *L) { | 106 | static 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 | ||
| 69 | static int luaB_tinsert (lua_State *L) { | 113 | static 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 | ||
| 92 | static int luaB_tremove (lua_State *L) { | 135 | static 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 | ||
| 151 | static 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 | ||
| 124 | static int sort_comp (lua_State *L, int a, int b) { | 185 | static 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 | ||
| 203 | static int luaB_sort (lua_State *L) { | 263 | static 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 | ||
| 217 | static const luaL_reg tab_funcs[] = { | 276 | static 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 | ||
| 228 | LUALIB_API int lua_tablibopen (lua_State *L) { | 289 | LUALIB_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 | ||
