lua-users home
lua-l archive

Re: Multiple assignment, numeric table keys

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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


AltStyle によって変換されたページ (->オリジナル) /