[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Multiple assignment, numeric table keys
- From: Dirk Laurie <dirk.laurie@...>
- Date: Sat, 15 Dec 2012 06:51:38 +0200
2012/12/15 TNHarris <telliamed@whoopdedo.org>:
>
> This makes me wish that table.insert accepted multiple values.
>
> table.insert(t, 1, 1, 2)
>
Try the attached module.
/* xtable.c Enhanced drop-in replacements for some table library functions
(c) 2012 Dirk Laurie, same license as
Lua 5.2.1 (c) 1994-2012 Lua.org, PUC-Rio
from which much of the code has been borrowed anyway
*/
/* compile with `cc -shared xtable.c -o xtable.so` */
#include <stddef.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#define aux_getn(L,n) \
(luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
/* xtable.concat(list,sep,i,j) enhancements:
* - respects metamethods: if sep is a string, returns the same as
* list[i]..sep..list[i+1]..sep.. ... sep..list[j]..""
* (suggestion: if you define this __concat metamethod for strings only:
* getmetatable"".__concat =
* function(a,b) return tostring(a)..tostring(b) end
* then xtable.concat can concatenate anything)
* - when sep is a table or a function, respectively returns the same as
* list[i]..sep[i+1]..list[i+1]..sep[i+2].. ... sep[j]..list[j]..""
* list[i]..sep(i+1)..list[i+1]..sep(i+2).. ... sep(j)..list[j]..""
*/
static int xconcat (lua_State *L) {
size_t lsep;
int i, last, n;
luaL_checktype(L, 1, LUA_TTABLE);
int tr = lua_type(L, 2);
if (!lua_isnoneornil(L,2)) luaL_argcheck(L,
tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION ||
tr == LUA_TTABLE, 2, "string/function/table expected");
char *sep="";
if ( tr == LUA_TNUMBER || tr == LUA_TSTRING )
sep = (char *) luaL_optlstring(L, 2, "", &lsep);
i = luaL_optint(L, 3, 1);
last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
lua_pushstring(L,"");
if (i>last) return 1;
lua_checkstack(L,(last-i+1)*2);
lua_pushinteger(L,i);
lua_gettable(L,1);
n=1;
for (i++; i <= last; i++) {
switch (tr) {
case LUA_TFUNCTION: {
lua_pushvalue(L,2);
lua_pushinteger(L,i);
lua_call(L,1,1);
break;
}
case LUA_TTABLE: {
lua_pushinteger(L,i);
lua_gettable(L,2);
break;
}
default: lua_pushstring(L,sep);
}
lua_pushinteger(L,i);
lua_gettable(L,1);
n+=2;
}
lua_concat(L,n);
return 1;
}
/* xtable.insert(list,pos,...) enhancements:
* - accepts multiple values to be inserted
* - two-argument append functionality removed (yes, an enhancement)
*/
static int xinsert (lua_State *L) {
int n = aux_getn(L, 1); /* #list */
int pos = luaL_checkint(L, 2); /* where to insert */
int m = lua_gettop(L)-2; /* number of elements to be inserted */
luaL_argcheck(L,m>2,3,"two-argument insert no longer supported");
int i;
for (i = n; i >= pos; i--) { /* move up elements */
lua_rawgeti(L, 1, i);
lua_rawseti(L, 1, i+m); /* t[i+m] = t[i] */
}
for (i=pos+m-1; i>=pos; i--)
lua_rawseti(L, 1, i); /* t[i] = v */
return 0;
}
/* xtable.append(list,...) enhancements over table.insert(list,value):
* - accepts multiple values to be appended
*/
static int xappend (lua_State *L) {
int n = aux_getn(L, 1); /* #list */
int m = lua_gettop(L)-1; /* number of elements to be appended */
int i;
for (i=n+m; i>n; i--)
lua_rawseti(L, 1, i); /* t[i] = v */
return 0;
}
static const luaL_Reg tab_funcs[] = {
{"concat", xconcat},
{"insert", xinsert},
{"append", xappend},
{NULL, NULL}
};
LUAMOD_API int luaopen_xtable (lua_State *L) {
luaL_newlib(L, tab_funcs);
return 1;
}
Attachment:
test-xtable.lua
Description: Binary data