moonbridge

changeset 69:daef4a38cc98

Work on io.poll(...) and file handle methods "xread", "xread_nb", "write_nb"
author jbe
date Sat Apr 04 21:01:41 2015 +0200 (2015-04-04)
parents ad06fc76906a
children 360a1860bb14
files moonbridge.c
line diff
     1.1 --- a/moonbridge.c	Sat Apr 04 17:19:12 2015 +0200
     1.2 +++ b/moonbridge.c	Sat Apr 04 21:01:41 2015 +0200
     1.3 @@ -936,7 +936,7 @@
     1.4    return lua_gettop(L);
     1.5  }
     1.6  
     1.7 -/* Lua method for socket object to read from input stream until terminator */
     1.8 +/* Lua method for socket object to read from input stream using xread */
     1.9  static int moonbr_child_lua_xread_stream(lua_State *L) {
    1.10    lua_getfield(L, 1, "input");
    1.11    lua_getfield(L, -1, "xread");
    1.12 @@ -946,6 +946,16 @@
    1.13    return lua_gettop(L);
    1.14  }
    1.15  
    1.16 +/* Lua method for socket object to read from input stream using xread_nb */
    1.17 +static int moonbr_child_lua_xread_nb_stream(lua_State *L) {
    1.18 +  lua_getfield(L, 1, "input");
    1.19 +  lua_getfield(L, -1, "xread_nb");
    1.20 +  lua_insert(L, 1);
    1.21 +  lua_replace(L, 2);
    1.22 +  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
    1.23 +  return lua_gettop(L);
    1.24 +}
    1.25 +
    1.26  /* Lua method for socket object to iterate over input stream */
    1.27  static int moonbr_child_lua_lines_stream(lua_State *L) {
    1.28    lua_getfield(L, 1, "input");
    1.29 @@ -966,6 +976,16 @@
    1.30    return lua_gettop(L);
    1.31  }
    1.32  
    1.33 +/* Lua method for socket object to write to output stream using write_nb */
    1.34 +static int moonbr_child_lua_write_nb_stream(lua_State *L) {
    1.35 +  lua_getfield(L, 1, "input");
    1.36 +  lua_getfield(L, -1, "write_nb");
    1.37 +  lua_insert(L, 1);
    1.38 +  lua_replace(L, 2);
    1.39 +  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
    1.40 +  return lua_gettop(L);
    1.41 +}
    1.42 +
    1.43  /* Lua method for socket object to flush the output stream */
    1.44  static int moonbr_child_lua_flush_stream(lua_State *L) {
    1.45    lua_getfield(L, 1, "output");
    1.46 @@ -1042,13 +1062,15 @@
    1.47  
    1.48  /* Methods of (bidirectional) socket object passed to handler */
    1.49  static luaL_Reg moonbr_child_lua_socket_functions[] = {
    1.50 -  {"read", moonbr_child_lua_read_stream},
    1.51 -  {"xread", moonbr_child_lua_xread_stream},
    1.52 -  {"lines", moonbr_child_lua_lines_stream},
    1.53 -  {"write", moonbr_child_lua_write_stream},
    1.54 -  {"flush", moonbr_child_lua_flush_stream},
    1.55 -  {"close", moonbr_child_lua_close_both_streams},
    1.56 -  {"cancel", moonbr_child_lua_cancel_both_streams},
    1.57 +  {"read",     moonbr_child_lua_read_stream},
    1.58 +  {"xread",    moonbr_child_lua_xread_stream},
    1.59 +  {"xread_nb", moonbr_child_lua_xread_nb_stream},
    1.60 +  {"lines",    moonbr_child_lua_lines_stream},
    1.61 +  {"write",    moonbr_child_lua_write_stream},
    1.62 +  {"write_nb", moonbr_child_lua_write_nb_stream},
    1.63 +  {"flush",    moonbr_child_lua_flush_stream},
    1.64 +  {"close",    moonbr_child_lua_close_both_streams},
    1.65 +  {"cancel",   moonbr_child_lua_cancel_both_streams},
    1.66    {NULL, NULL}
    1.67  };
    1.68  
    1.69 @@ -2372,49 +2394,88 @@
    1.70    }
    1.71  }
    1.72  
    1.73 -/* New method for Lua file objects: read until terminator or length exceeded */
    1.74 -static int moonbr_io_xread(lua_State *L) {
    1.75 +/* New methods for Lua file objects: read until terminator or length exceeded (optional non-blocking) */
    1.76 +static int moonbr_io_xread_impl(lua_State *L, int nonblock) {
    1.77    luaL_Stream *stream;
    1.78 -  FILE *file;
    1.79 +  lua_Integer maxlen;
    1.80    const char *terminatorstr;
    1.81    size_t terminatorlen;
    1.82 +  FILE *file;
    1.83 +  int fd, flags, chr, terminator;
    1.84    luaL_Buffer buf;
    1.85 -  lua_Integer maxlen;
    1.86 -  char terminator;
    1.87 -  int byte;
    1.88 +  int wouldblock = 0;
    1.89    stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
    1.90 -  terminatorstr = luaL_checklstring(L, 2, &terminatorlen);
    1.91 -  luaL_argcheck(L, terminatorlen == 1, 2, "single byte expected");
    1.92 -  maxlen = luaL_optinteger(L, 3, 0);
    1.93 +  maxlen = luaL_optinteger(L, 2, 0);
    1.94 +  terminatorstr = luaL_optlstring(L, 3, "", &terminatorlen);
    1.95 +  luaL_argcheck(L, terminatorlen <= 1, 3, "single byte expected");
    1.96    if (!stream->closef) luaL_error(L, "attempt to use a closed file");
    1.97    file = stream->f;
    1.98 -  luaL_buffinit(L, &buf);
    1.99 +  if (ferror(file)) {
   1.100 +    lua_pushnil(L);
   1.101 +    lua_pushliteral(L, "Previous error condition on file handle");
   1.102 +    return 2;
   1.103 +  }
   1.104 +  if (nonblock) {
   1.105 +    fd = fileno(file);
   1.106 +    flags = fcntl(fd, F_GETFL, 0);
   1.107 +    if (flags == -1) goto moonbr_io_xread_impl_error;
   1.108 +    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_xread_impl_error;
   1.109 +  }
   1.110    if (!maxlen) maxlen = -1;
   1.111 -  terminator = terminatorstr[0];
   1.112 -  flockfile(file);
   1.113 +  terminator = terminatorlen ? terminatorstr[0] : -1;
   1.114 +  luaL_buffinit(L, &buf);
   1.115    while (maxlen > 0 ? maxlen-- : maxlen) {
   1.116 -    byte = getc_unlocked(file);
   1.117 -    if (byte == EOF) {
   1.118 +    chr = getc(file);
   1.119 +    if (chr == EOF) {
   1.120        if (ferror(file)) {
   1.121 -        char errmsg[MOONBR_MAXSTRERRORLEN];
   1.122 -        strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.123 -        funlockfile(file);
   1.124 -        lua_pushnil(L);
   1.125 -        lua_pushstring(L, errmsg);
   1.126 -        return 2;
   1.127 -      } else {
   1.128 -        break;
   1.129 +        if (nonblock && errno == EAGAIN) {
   1.130 +          clearerr(file);
   1.131 +          wouldblock = 1;
   1.132 +        } else {
   1.133 +          char errmsg[MOONBR_MAXSTRERRORLEN];
   1.134 +          strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.135 +          if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_impl_error;
   1.136 +          lua_pushnil(L);
   1.137 +          lua_pushstring(L, errmsg);
   1.138 +          return 2;
   1.139 +        }
   1.140        }
   1.141 +      break;
   1.142      }
   1.143 -    luaL_addchar(&buf, byte);
   1.144 -    if (byte == terminator) break;
   1.145 +    luaL_addchar(&buf, chr);
   1.146 +    if (chr == terminator) break;
   1.147 +  }
   1.148 +  if (nonblock) {
   1.149 +    if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_impl_error;
   1.150    }
   1.151 -  funlockfile(file);
   1.152    luaL_pushresult(&buf);
   1.153 -  if (!lua_rawlen(L, -1)) lua_pushnil(L);
   1.154 -  return 1;
   1.155 +  if (wouldblock || lua_rawlen(L, -1)) {
   1.156 +    return 1;
   1.157 +  } else {
   1.158 +    lua_pushboolean(L, 0);
   1.159 +    lua_pushliteral(L, "End of file");
   1.160 +    return 2;
   1.161 +  }
   1.162 +  moonbr_io_xread_impl_error:
   1.163 +  {
   1.164 +    char errmsg[MOONBR_MAXSTRERRORLEN];
   1.165 +    strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.166 +    return luaL_error(L, "Unexpected error in xread method: %s", errmsg);
   1.167 +  }
   1.168 +}
   1.169 +static int moonbr_io_xread(lua_State *L) {
   1.170 +  return moonbr_io_xread_impl(L, 0);
   1.171 +}
   1.172 +static int moonbr_io_xread_nb(lua_State *L) {
   1.173 +  return moonbr_io_xread_impl(L, 1);
   1.174  }
   1.175  
   1.176 +/* New methods for Lua file objects: non-blocking writing */
   1.177 +static int moonbr_io_write_nb(lua_State *L) {
   1.178 +  return luaL_error(L, "Not implemented");  // TODO
   1.179 +}
   1.180 +
   1.181 +/* New global function timeout(...) */
   1.182  static int moonbr_timeout(lua_State *L) {
   1.183    struct itimerval oldval;
   1.184    if (lua_isnoneornil(L, 1) && lua_isnoneornil(L, 2)) {
   1.185 @@ -2893,6 +2954,10 @@
   1.186      lua_getfield(L, -1, "__index");
   1.187      lua_pushcfunction(L, moonbr_io_xread);
   1.188      lua_setfield(L, -2, "xread");
   1.189 +    lua_pushcfunction(L, moonbr_io_xread_nb);
   1.190 +    lua_setfield(L, -2, "xread_nb");
   1.191 +    lua_pushcfunction(L, moonbr_io_write_nb);
   1.192 +    lua_setfield(L, -2, "write_nb");
   1.193      lua_pop(L, 2);
   1.194      lua_pushcfunction(L, moonbr_timeout);
   1.195      lua_setglobal(L, "timeout");

Impressum / About Us