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");

Impressum / About Us