# HG changeset patch # User jbe # Date 1430437567 -7200 # Node ID 9ca22af4d4b1e2a8032f15ab2d1665956ecd092e # Parent f148bd2b3d05a56b24a14dcfcfb07c3f512b9b00 Added methods "read_call" and "read_yield" diff -r f148bd2b3d05 -r 9ca22af4d4b1 moonbridge_io.c --- a/moonbridge_io.c Sat Apr 18 01:33:38 2015 +0200 +++ b/moonbridge_io.c Fri May 01 01:46:07 2015 +0200 @@ -71,6 +71,18 @@ int nonblocking; } moonbr_io_listener_t; +static int moonbr_io_yield(lua_State *L) { + return lua_yield(L, 0); +} + +#if LUA_VERSION_NUM >= 503 +static int moonbr_io_cont_returnall(lua_State *L, int status, lua_KContext ctx) { +#else +static int moonbr_io_cont_returnall(lua_State *L) { +#endif + return lua_gettop(L); +} + static void moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) { int flags; if (handle->nonblocking == nonblocking) return; @@ -265,6 +277,109 @@ return moonbr_io_read_impl(L, 1, 1); } +#if LUA_VERSION_NUM >= 503 +static int moonbr_io_read_cont(lua_State *L, int status, lua_KContext ctx) { +#else +static int moonbr_io_read_cont(lua_State *L) { +#endif + size_t len, remaining; + const char *terminatorstr = NULL; + size_t terminatorlen = 0; + const char *chunk; + size_t chunklen; +#if !(LUA_VERSION_NUM >= 503) + int ctx = 0; + lua_getctx(L, &ctx); +#endif + remaining = lua_tointeger(L, 3); + while (1) { + lua_pushcfunction(L, moonbr_io_read_nb); + lua_pushvalue(L, 1); + lua_pushvalue(L, 3); + lua_pushvalue(L, 4); + lua_call(L, 3, 2); + if (lua_isnil(L, -2)) { + return 2; + } else if (!lua_toboolean(L, -2)) { + if (ctx) { + lua_pushnil(L); + lua_pushliteral(L, "Unexpected EOF"); + } + return 2; + } + len = lua_rawlen(L, -2); + if (!len) { + lua_pop(L, 2); + } else { + lua_pop(L, 1); + if (!terminatorstr) { + terminatorstr = lua_tolstring(L, 4, &terminatorlen); + if (!terminatorstr) terminatorstr = ""; + } + if (terminatorlen) chunk = lua_tolstring(L, -1, &chunklen); + if (ctx == 0) { + lua_replace(L, 5); + ctx = 1; + } else if (ctx == 1) { + lua_pushvalue(L, 5); + lua_newtable(L); + lua_replace(L, 5); + lua_rawseti(L, 5, 2); + lua_rawseti(L, 5, 1); + ctx = 2; + } else { + lua_rawseti(L, 5, lua_rawlen(L, 5) + 1); + } + if (remaining) { + if (len >= remaining) break; + remaining -= len; + lua_pushinteger(L, remaining); + lua_replace(L, 3); + } + if (terminatorlen && chunk[chunklen-1] == terminatorstr[0]) break; + } + lua_pushvalue(L, 2); + lua_pushvalue(L, 1); + lua_pushliteral(L, "r"); + lua_callk(L, 2, 0, ctx, moonbr_io_read_cont); + } + if (ctx == 1) { + lua_pushvalue(L, 5); + } else { + luaL_Buffer buf; + lua_Integer i, chunkcount; + chunkcount = lua_rawlen(L, 5); + luaL_buffinit(L, &buf); + for (i=1; i<=chunkcount && i>0; i++) { + lua_rawgeti(L, 5, i); + luaL_addvalue(&buf); + } + luaL_pushresult(&buf); + } + return 1; +} + +static int moonbr_io_read_call(lua_State *L) { + lua_settop(L, 4); + lua_pushnil(L); +#if LUA_VERSION_NUM >= 503 + return moonbr_io_read_cont(L, 0, 0); +#else + return moonbr_io_read_cont(L); +#endif +} + +static int moonbr_io_read_yield(lua_State *L) { + int args; + lua_pushcfunction(L, moonbr_io_read_call); + lua_insert(L, 1); + args = lua_gettop(L); + lua_pushcfunction(L, moonbr_io_yield); + lua_insert(L, 3); + lua_callk(L, args, LUA_MULTRET, 0, moonbr_io_cont_returnall); + return lua_gettop(L); +} + static int moonbr_io_write_impl(lua_State *L, int nonblocking, int flush) { moonbr_io_handle_t *handle; int i, top; @@ -1116,6 +1231,8 @@ static const struct luaL_Reg moonbr_io_handle_methods[] = { {"read", moonbr_io_read}, {"read_nb", moonbr_io_read_nb}, + {"read_call", moonbr_io_read_call}, + {"read_yield", moonbr_io_read_yield}, {"drain", moonbr_io_drain}, {"drain_nb", moonbr_io_drain_nb}, {"write", moonbr_io_write}, diff -r f148bd2b3d05 -r 9ca22af4d4b1 reference.txt --- a/reference.txt Sat Apr 18 01:33:38 2015 +0200 +++ b/reference.txt Fri May 01 01:46:07 2015 +0200 @@ -155,6 +155,12 @@ second return value) are returned. +### socket:read_call(waitfunc, maxlen, terminator) + +Same as socket:read(maxlen, terminator), but calls waitfunc(socket, "r") (in an +infinite loop) as long as the reading is blocked. + + ### socket:read_nb(maxlen, terminator) Read up to maxlen bytes, until an optional termination character is encountered @@ -172,6 +178,11 @@ second return value) are returned. +### socket:read_yield(maxlen, terminator) + +Alias for socket:read_call(coroutine.yield, maxlen, terminator) + + ### socket.remote_ip4 Remote IPv4 address used for the connection. Encoded as 4 raw bytes in form of