--- a/src/lua_func.c Thu May 14 21:45:43 2009 +0300
+++ b/src/lua_func.c Thu May 14 22:57:13 2009 +0300
@@ -70,6 +70,19 @@
return lua_toboolean(L, index);
}
+static void * _lua_arg_obj (lua_State *L, int index, const struct lua_type *type, bool optional)
+{
+ // not given?
+ if (!lua_isnoneornil(L, index))
+ return lua_type_get(L, type, index);
+
+ if (optional)
+ return NULL;
+
+ luaL_error(L, "missing value for required object argument <%d:%s>", index, type->name);
+ return NULL;
+}
+
/**
* Look up the arg index to use for the given index/name.
*
@@ -78,8 +91,8 @@
static int lua_arg_index (lua_State *L, int nargs, int index, const char *name)
{
// lookup from table?
- if (name && lua_istable(L, 2)) {
- // push the value from the field onto the stack
+ if (nargs == 2 && lua_istable(L, 2) && name) {
+ // push the value from the named field onto the stack
lua_getfield(L, 2, name);
// no named field?
@@ -119,6 +132,11 @@
return _lua_arg_bool(L, lua_arg_index(L, nargs, index, name), name, def);
}
+void * lua_arg_obj (lua_State *L, int nargs, int index, const struct lua_type *type, bool optional)
+{
+ return _lua_arg_obj(L, lua_arg_index(L, nargs, index, NULL), type, optional);
+}
+
void lua_args_parse (lua_State *L, const struct lua_func *func, void **obj_ptr, ...)
{
int argidx = 1, argtbl = 0, idx;
--- a/src/lua_func.h Thu May 14 21:45:43 2009 +0300
+++ b/src/lua_func.h Thu May 14 22:57:13 2009 +0300
@@ -82,6 +82,11 @@
bool lua_arg_bool (lua_State *L, int nargs, int index, const char *name, int def);
/**
+ * Return a userdata argument at the given fixed index
+ */
+void * lua_arg_obj (lua_State *L, int nargs, int index, const struct lua_type *type, bool optional);
+
+/**
* Parse function arguments as defined
*/
void lua_args_parse (lua_State *L, const struct lua_func *func, void **obj_ptr, ...);
--- a/src/lua_irc.c Thu May 14 21:45:43 2009 +0300
+++ b/src/lua_irc.c Thu May 14 22:57:13 2009 +0300
@@ -172,37 +172,48 @@
}
static struct lua_func lua_net_channels_func = LUA_FUNC(&lua_net_type, "channels",
- "return a list of channel objects",
+ "Return an iterater over the network's channels",
LUA_FUNC_ARG_END
);
+static int lua_net_channels_iter (lua_State *L)
+{
+ int nargs = lua_gettop(L);
+ struct lua_net *lua_net = lua_arg_obj(L, nargs, 1, &lua_net_type, false);
+ struct lua_chan *lua_chan = lua_arg_obj(L, nargs, 2, &lua_chan_type, true);
+ struct irc_chan *chan_next;
+
+ // get next item from current
+ if (lua_chan)
+ chan_next = TAILQ_NEXT(lua_chan->chan, net_channels);
+ else
+ chan_next = TAILQ_FIRST(&lua_net->net->channels);
+
+ // push return value - next item
+ if (chan_next)
+ lua_chan_create(L, chan_next);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
static int lua_net_channels (lua_State *L)
{
struct lua_net *lua_net;
- struct irc_chan *chan;
- int i = 1;
// parse args
lua_args_parse(L, &lua_net_channels_func, (void *) &lua_net);
- // create table to return
- lua_newtable(L);
-
- // iter
- TAILQ_FOREACH(chan, &lua_net->net->channels, net_channels) {
- // push index
- lua_pushinteger(L, i);
+ // push iter func
+ lua_pushcfunction(L, lua_net_channels_iter);
- // push value as new lua_chan
- lua_chan_create(L, chan);
+ // push invariant state - the lua_net
+ lua_pushvalue(L, 1);
- // store in table
- lua_settable(L, -3);
- }
-
- // return table
- return 1;
+ // return iter three-tuple
+ return 2;
}
static struct lua_method lua_net_methods[] = LUA_METHODS(
@@ -335,37 +346,49 @@
}
static struct lua_func lua_client_networks_func = LUA_FUNC(&lua_client_type, "channels",
- "Build list of client's networks",
+ "Return an iterator over the client's networks",
LUA_FUNC_ARG_END
);
+static int lua_client_networks_iter (lua_State *L)
+{
+ int nargs = lua_gettop(L);
+ struct lua_client *lua_client = lua_arg_obj(L, nargs, 1, &lua_client_type, false);
+ struct lua_net *lua_net = lua_arg_obj(L, nargs, 2, &lua_net_type, true);
+ struct irc_net *net_next;
+
+ if (lua_net)
+ // return next
+ net_next = TAILQ_NEXT(lua_net->net, client_networks);
+ else
+ // return first
+ net_next = TAILQ_FIRST(&lua_client->client->networks);
+
+ // build and return next value
+ if (net_next)
+ lua_net_create(L, net_next);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
static int lua_client_networks (lua_State *L)
{
struct lua_client *lua_client;
- struct irc_net *net;
- int i = 1;
// parse args
lua_args_parse(L, &lua_client_networks_func, (void *) &lua_client);
- // create new table
- lua_newtable(L);
-
- // append each channel
- TAILQ_FOREACH(net, &lua_client->client->networks, client_networks) {
- // index
- lua_pushinteger(L, i);
+ // push iter func
+ lua_pushcfunction(L, lua_client_networks_iter);
- // push new lua_net
- lua_net_create(L, net);
+ // push invariant state - the lua_client
+ lua_pushvalue(L, 1);
- // store
- lua_settable(L, -3);
- }
-
- // ok, return the table
- return 1;
+ // return three-tuple
+ return 2;
}
static struct lua_func lua_client_quit_func = LUA_FUNC(&lua_client_type, "quit",
--- a/src/lua_type.c Thu May 14 21:45:43 2009 +0300
+++ b/src/lua_type.c Thu May 14 22:57:13 2009 +0300
@@ -57,6 +57,7 @@
void *ud;
// validate the userdata arg
+ // XXX: the luaL_checkudata actually raises an error itself
if ((ud = luaL_checkudata(L, index, type->name)) == NULL) {
luaL_error(L, "bad type argument: `%s` expected", type->name); return NULL;