moonbridge
diff moonbridge.c @ 68:ad06fc76906a
Extended io.poll(...) to check FILE buffers; Replaced method "readuntil" with "xread"
author | jbe |
---|---|
date | Sat Apr 04 17:19:12 2015 +0200 (2015-04-04) |
parents | c488f2ea29aa |
children | daef4a38cc98 |
line diff
1.1 --- a/moonbridge.c Sat Apr 04 11:42:34 2015 +0200 1.2 +++ b/moonbridge.c Sat Apr 04 17:19:12 2015 +0200 1.3 @@ -937,9 +937,9 @@ 1.4 } 1.5 1.6 /* Lua method for socket object to read from input stream until terminator */ 1.7 -static int moonbr_child_lua_readuntil_stream(lua_State *L) { 1.8 +static int moonbr_child_lua_xread_stream(lua_State *L) { 1.9 lua_getfield(L, 1, "input"); 1.10 - lua_getfield(L, -1, "readuntil"); 1.11 + lua_getfield(L, -1, "xread"); 1.12 lua_insert(L, 1); 1.13 lua_replace(L, 2); 1.14 lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); 1.15 @@ -1043,7 +1043,7 @@ 1.16 /* Methods of (bidirectional) socket object passed to handler */ 1.17 static luaL_Reg moonbr_child_lua_socket_functions[] = { 1.18 {"read", moonbr_child_lua_read_stream}, 1.19 - {"readuntil", moonbr_child_lua_readuntil_stream}, 1.20 + {"xread", moonbr_child_lua_xread_stream}, 1.21 {"lines", moonbr_child_lua_lines_stream}, 1.22 {"write", moonbr_child_lua_write_stream}, 1.23 {"flush", moonbr_child_lua_flush_stream}, 1.24 @@ -2283,11 +2283,43 @@ 1.25 #endif 1.26 stream = luaL_testudata(L, -1, LUA_FILEHANDLE); 1.27 if (stream) { 1.28 - fd = fileno(stream->f); 1.29 - } else { 1.30 - fd = lua_tointegerx(L, -1, &isnum); 1.31 - if (!isnum) luaL_error(L, "File descriptor is not an integer"); 1.32 + FILE *file = stream->f; 1.33 + int flags, chr; 1.34 + flockfile(file); 1.35 + fd = fileno_unlocked(file); 1.36 + if (ferror(file) || feof(file)) goto moonbr_io_poll_pending_shortcut; 1.37 + flags = fcntl(fd, F_GETFL, 0); 1.38 + if (flags == -1) goto moonbr_io_poll_pending_error; 1.39 + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_poll_pending_error; 1.40 + chr = getc_unlocked(file); 1.41 + if (chr == EOF) { 1.42 + if (ferror(file) && errno == EAGAIN) clearerr_unlocked(file); 1.43 + else goto moonbr_io_poll_pending_shortcut; 1.44 + } else { 1.45 + if (ungetc(chr, file) == EOF) { 1.46 + fcntl(fd, F_SETFL, flags); 1.47 + goto moonbr_io_poll_pending_error; 1.48 + } 1.49 + goto moonbr_io_poll_pending_shortcut; 1.50 + } 1.51 + if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_poll_pending_error; 1.52 + funlockfile(file); 1.53 + goto moonbr_io_poll_pending_cont; 1.54 + moonbr_io_poll_pending_shortcut: 1.55 + funlockfile(file); 1.56 + lua_pushboolean(L, 1); 1.57 + return 1; 1.58 + moonbr_io_poll_pending_error: 1.59 + funlockfile(file); 1.60 + { 1.61 + char errmsg[MOONBR_MAXSTRERRORLEN]; 1.62 + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.63 + return luaL_error(L, "Unexpected error while checking buffer of FILE handle: %s", errmsg); 1.64 + } 1.65 } 1.66 + fd = lua_tointegerx(L, -1, &isnum); 1.67 + if (!isnum) luaL_error(L, "File descriptor is not an integer"); 1.68 + moonbr_io_poll_pending_cont: 1.69 FD_SET(fd, &readfds); 1.70 if (fd+1 > nfds) nfds = fd+1; 1.71 lua_pop(L, 1); 1.72 @@ -2340,49 +2372,8 @@ 1.73 } 1.74 } 1.75 1.76 -/* New method for Lua file objects: check if non-blocking reading is possible */ 1.77 -static int moonbr_io_pending(lua_State *L) { 1.78 - luaL_Stream *stream; 1.79 - FILE *file; 1.80 - int fd, flags, chr; 1.81 - stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); 1.82 - if (!stream->closef) luaL_error(L, "attempt to use a closed file"); 1.83 - file = stream->f; 1.84 - flockfile(file); 1.85 - fd = fileno_unlocked(file); 1.86 - if (ferror(file) || feof(file)) { 1.87 - funlockfile(file); 1.88 - lua_pushboolean(L, 1); 1.89 - return 1; 1.90 - } 1.91 - flags = fcntl(fd, F_GETFL, 0); 1.92 - if (flags == -1) goto moonbr_io_pending_error; 1.93 - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_pending_error; 1.94 - chr = getc_unlocked(file); 1.95 - lua_pushboolean(L, 1); 1.96 - if (chr == EOF) { 1.97 - if (ferror(file) && errno == EAGAIN) { 1.98 - clearerr_unlocked(file); 1.99 - lua_pushboolean(L, 0); 1.100 - } 1.101 - } else { 1.102 - if (ungetc(chr, file) == EOF) goto moonbr_io_pending_error; 1.103 - } 1.104 - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_pending_error; 1.105 - funlockfile(file); 1.106 - return 1; 1.107 - moonbr_io_pending_error: 1.108 - funlockfile(file); 1.109 - { 1.110 - char errmsg[MOONBR_MAXSTRERRORLEN]; 1.111 - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ 1.112 - luaL_error(L, "Unexpected error in method \"pending\" of FILE handle: %s", errmsg); 1.113 - } 1.114 - return 0; 1.115 -} 1.116 - 1.117 /* New method for Lua file objects: read until terminator or length exceeded */ 1.118 -static int moonbr_io_readuntil(lua_State *L) { 1.119 +static int moonbr_io_xread(lua_State *L) { 1.120 luaL_Stream *stream; 1.121 FILE *file; 1.122 const char *terminatorstr; 1.123 @@ -2900,10 +2891,8 @@ 1.124 moonbr_terminate_error(); 1.125 } 1.126 lua_getfield(L, -1, "__index"); 1.127 - lua_pushcfunction(L, moonbr_io_pending); 1.128 - lua_setfield(L, -2, "pending"); 1.129 - lua_pushcfunction(L, moonbr_io_readuntil); 1.130 - lua_setfield(L, -2, "readuntil"); 1.131 + lua_pushcfunction(L, moonbr_io_xread); 1.132 + lua_setfield(L, -2, "xread"); 1.133 lua_pop(L, 2); 1.134 lua_pushcfunction(L, moonbr_timeout); 1.135 lua_setglobal(L, "timeout");