moonbridge
changeset 140:9ca22af4d4b1
Added methods "read_call" and "read_yield"
author | jbe |
---|---|
date | Fri May 01 01:46:07 2015 +0200 (2015-05-01) |
parents | f148bd2b3d05 |
children | 845e3dce3774 |
files | moonbridge_io.c reference.txt |
line diff
1.1 --- a/moonbridge_io.c Sat Apr 18 01:33:38 2015 +0200 1.2 +++ b/moonbridge_io.c Fri May 01 01:46:07 2015 +0200 1.3 @@ -71,6 +71,18 @@ 1.4 int nonblocking; 1.5 } moonbr_io_listener_t; 1.6 1.7 +static int moonbr_io_yield(lua_State *L) { 1.8 + return lua_yield(L, 0); 1.9 +} 1.10 + 1.11 +#if LUA_VERSION_NUM >= 503 1.12 +static int moonbr_io_cont_returnall(lua_State *L, int status, lua_KContext ctx) { 1.13 +#else 1.14 +static int moonbr_io_cont_returnall(lua_State *L) { 1.15 +#endif 1.16 + return lua_gettop(L); 1.17 +} 1.18 + 1.19 static void moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) { 1.20 int flags; 1.21 if (handle->nonblocking == nonblocking) return; 1.22 @@ -265,6 +277,109 @@ 1.23 return moonbr_io_read_impl(L, 1, 1); 1.24 } 1.25 1.26 +#if LUA_VERSION_NUM >= 503 1.27 +static int moonbr_io_read_cont(lua_State *L, int status, lua_KContext ctx) { 1.28 +#else 1.29 +static int moonbr_io_read_cont(lua_State *L) { 1.30 +#endif 1.31 + size_t len, remaining; 1.32 + const char *terminatorstr = NULL; 1.33 + size_t terminatorlen = 0; 1.34 + const char *chunk; 1.35 + size_t chunklen; 1.36 +#if !(LUA_VERSION_NUM >= 503) 1.37 + int ctx = 0; 1.38 + lua_getctx(L, &ctx); 1.39 +#endif 1.40 + remaining = lua_tointeger(L, 3); 1.41 + while (1) { 1.42 + lua_pushcfunction(L, moonbr_io_read_nb); 1.43 + lua_pushvalue(L, 1); 1.44 + lua_pushvalue(L, 3); 1.45 + lua_pushvalue(L, 4); 1.46 + lua_call(L, 3, 2); 1.47 + if (lua_isnil(L, -2)) { 1.48 + return 2; 1.49 + } else if (!lua_toboolean(L, -2)) { 1.50 + if (ctx) { 1.51 + lua_pushnil(L); 1.52 + lua_pushliteral(L, "Unexpected EOF"); 1.53 + } 1.54 + return 2; 1.55 + } 1.56 + len = lua_rawlen(L, -2); 1.57 + if (!len) { 1.58 + lua_pop(L, 2); 1.59 + } else { 1.60 + lua_pop(L, 1); 1.61 + if (!terminatorstr) { 1.62 + terminatorstr = lua_tolstring(L, 4, &terminatorlen); 1.63 + if (!terminatorstr) terminatorstr = ""; 1.64 + } 1.65 + if (terminatorlen) chunk = lua_tolstring(L, -1, &chunklen); 1.66 + if (ctx == 0) { 1.67 + lua_replace(L, 5); 1.68 + ctx = 1; 1.69 + } else if (ctx == 1) { 1.70 + lua_pushvalue(L, 5); 1.71 + lua_newtable(L); 1.72 + lua_replace(L, 5); 1.73 + lua_rawseti(L, 5, 2); 1.74 + lua_rawseti(L, 5, 1); 1.75 + ctx = 2; 1.76 + } else { 1.77 + lua_rawseti(L, 5, lua_rawlen(L, 5) + 1); 1.78 + } 1.79 + if (remaining) { 1.80 + if (len >= remaining) break; 1.81 + remaining -= len; 1.82 + lua_pushinteger(L, remaining); 1.83 + lua_replace(L, 3); 1.84 + } 1.85 + if (terminatorlen && chunk[chunklen-1] == terminatorstr[0]) break; 1.86 + } 1.87 + lua_pushvalue(L, 2); 1.88 + lua_pushvalue(L, 1); 1.89 + lua_pushliteral(L, "r"); 1.90 + lua_callk(L, 2, 0, ctx, moonbr_io_read_cont); 1.91 + } 1.92 + if (ctx == 1) { 1.93 + lua_pushvalue(L, 5); 1.94 + } else { 1.95 + luaL_Buffer buf; 1.96 + lua_Integer i, chunkcount; 1.97 + chunkcount = lua_rawlen(L, 5); 1.98 + luaL_buffinit(L, &buf); 1.99 + for (i=1; i<=chunkcount && i>0; i++) { 1.100 + lua_rawgeti(L, 5, i); 1.101 + luaL_addvalue(&buf); 1.102 + } 1.103 + luaL_pushresult(&buf); 1.104 + } 1.105 + return 1; 1.106 +} 1.107 + 1.108 +static int moonbr_io_read_call(lua_State *L) { 1.109 + lua_settop(L, 4); 1.110 + lua_pushnil(L); 1.111 +#if LUA_VERSION_NUM >= 503 1.112 + return moonbr_io_read_cont(L, 0, 0); 1.113 +#else 1.114 + return moonbr_io_read_cont(L); 1.115 +#endif 1.116 +} 1.117 + 1.118 +static int moonbr_io_read_yield(lua_State *L) { 1.119 + int args; 1.120 + lua_pushcfunction(L, moonbr_io_read_call); 1.121 + lua_insert(L, 1); 1.122 + args = lua_gettop(L); 1.123 + lua_pushcfunction(L, moonbr_io_yield); 1.124 + lua_insert(L, 3); 1.125 + lua_callk(L, args, LUA_MULTRET, 0, moonbr_io_cont_returnall); 1.126 + return lua_gettop(L); 1.127 +} 1.128 + 1.129 static int moonbr_io_write_impl(lua_State *L, int nonblocking, int flush) { 1.130 moonbr_io_handle_t *handle; 1.131 int i, top; 1.132 @@ -1116,6 +1231,8 @@ 1.133 static const struct luaL_Reg moonbr_io_handle_methods[] = { 1.134 {"read", moonbr_io_read}, 1.135 {"read_nb", moonbr_io_read_nb}, 1.136 + {"read_call", moonbr_io_read_call}, 1.137 + {"read_yield", moonbr_io_read_yield}, 1.138 {"drain", moonbr_io_drain}, 1.139 {"drain_nb", moonbr_io_drain_nb}, 1.140 {"write", moonbr_io_write},
2.1 --- a/reference.txt Sat Apr 18 01:33:38 2015 +0200 2.2 +++ b/reference.txt Fri May 01 01:46:07 2015 +0200 2.3 @@ -155,6 +155,12 @@ 2.4 second return value) are returned. 2.5 2.6 2.7 +### socket:read_call(waitfunc, maxlen, terminator) 2.8 + 2.9 +Same as socket:read(maxlen, terminator), but calls waitfunc(socket, "r") (in an 2.10 +infinite loop) as long as the reading is blocked. 2.11 + 2.12 + 2.13 ### socket:read_nb(maxlen, terminator) 2.14 2.15 Read up to maxlen bytes, until an optional termination character is encountered 2.16 @@ -172,6 +178,11 @@ 2.17 second return value) are returned. 2.18 2.19 2.20 +### socket:read_yield(maxlen, terminator) 2.21 + 2.22 +Alias for socket:read_call(coroutine.yield, maxlen, terminator) 2.23 + 2.24 + 2.25 ### socket.remote_ip4 2.26 2.27 Remote IPv4 address used for the connection. Encoded as 4 raw bytes in form of