# HG changeset patch # User Tero Marttila # Date 1242331033 -10800 # Node ID 8eb839fbabbad2e0dbcfb8feca57d95ee6410632 # Parent b74185e1357a6877968be5213d936fe998e55034 replace lua_client_networks/lua_network_channels with iterators diff -r b74185e1357a -r 8eb839fbabba src/lua_func.c --- 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; diff -r b74185e1357a -r 8eb839fbabba src/lua_func.h --- 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, ...); diff -r b74185e1357a -r 8eb839fbabba src/lua_irc.c --- 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", diff -r b74185e1357a -r 8eb839fbabba src/lua_type.c --- 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;