moonbridge

diff moonbridge_io.c @ 85:ef552870f1b6

Implementation of read and read_nb in I/O module
author jbe
date Mon Apr 06 22:58:51 2015 +0200 (2015-04-06)
parents 8a6e2a80fcad
children 9fa3a36733ff
line diff
     1.1 --- a/moonbridge_io.c	Mon Apr 06 15:41:37 2015 +0200
     1.2 +++ b/moonbridge_io.c	Mon Apr 06 22:58:51 2015 +0200
     1.3 @@ -16,6 +16,7 @@
     1.4  #include <lualib.h>
     1.5  
     1.6  #define MOONBR_IO_MAXSTRERRORLEN 80
     1.7 +#define MOONBR_IO_READBUFLEN 4096
     1.8  #define MOONBR_IO_WRITEBUFLEN 4096
     1.9  
    1.10  #define moonbr_io_errmsg() \
    1.11 @@ -30,6 +31,8 @@
    1.12    int fd;
    1.13    int issocket;
    1.14    int nonblocking;
    1.15 +  int readerr;
    1.16 +  int readbufcnt;
    1.17    int writeerr;
    1.18    size_t writeleft;
    1.19  #if LUA_VERSION_NUM >= 503
    1.20 @@ -41,6 +44,7 @@
    1.21  #endif
    1.22    size_t writeqoff;
    1.23    int writebufcnt;
    1.24 +  char readbuf[MOONBR_IO_READBUFLEN];
    1.25    char writebuf[MOONBR_IO_WRITEBUFLEN];
    1.26  } moonbr_io_handle_t;
    1.27  
    1.28 @@ -61,6 +65,77 @@
    1.29    }
    1.30  }
    1.31  
    1.32 +static int moonbr_io_read_impl(lua_State *L, int nonblocking) {
    1.33 +  moonbr_io_handle_t *handle;
    1.34 +  lua_Integer maxread;
    1.35 +  const char *terminatorstr;
    1.36 +  size_t terminatorlen;
    1.37 +  char terminator;
    1.38 +  luaL_Buffer luabuf;
    1.39 +  size_t luabufcnt = 0;
    1.40 +  int restcnt;
    1.41 +  char *terminatorpos;
    1.42 +  ssize_t result;
    1.43 +  handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
    1.44 +  maxread = luaL_optinteger(L, 2, 0);
    1.45 +  terminatorstr = luaL_optlstring(L, 3, "", &terminatorlen);
    1.46 +  if (terminatorlen) {
    1.47 +    luaL_argcheck(L, terminatorlen == 1, 3, "single byte expected");
    1.48 +    terminator = terminatorstr[0];
    1.49 +  }
    1.50 +  if (handle->fd < 0) luaL_error(L, "Attempt to read from a closed I/O handle");
    1.51 +  if (handle->readerr) {
    1.52 +    lua_pushnil(L);
    1.53 +    lua_pushliteral(L, "Previous read error");
    1.54 +    return 2;
    1.55 +  }
    1.56 +  moonbr_io_handle_set_nonblocking(L, handle, nonblocking);
    1.57 +  luaL_buffinit(L, &luabuf);
    1.58 +  while (1) {
    1.59 +    restcnt = -1;
    1.60 +    if (maxread > 0 && handle->readbufcnt >= maxread - luabufcnt) {
    1.61 +      restcnt = maxread - luabufcnt;
    1.62 +    } else if (terminatorlen) {
    1.63 +      terminatorpos = memchr(handle->readbuf, terminator, handle->readbufcnt);
    1.64 +      if (terminatorpos) restcnt = 1 + (terminatorpos - handle->readbuf);
    1.65 +    }
    1.66 +    if (restcnt >= 0) {
    1.67 +      luaL_addlstring(&luabuf, handle->readbuf, restcnt);
    1.68 +      handle->readbufcnt -= restcnt;
    1.69 +      memmove(handle->readbuf, handle->readbuf + restcnt, handle->readbufcnt);
    1.70 +      luaL_pushresult(&luabuf);
    1.71 +      return 1;
    1.72 +    }
    1.73 +    luaL_addlstring(&luabuf, handle->readbuf, handle->readbufcnt);
    1.74 +    luabufcnt += handle->readbufcnt;
    1.75 +    handle->readbufcnt = 0;
    1.76 +    do {
    1.77 +      result = read(handle->fd, handle->readbuf, MOONBR_IO_READBUFLEN);
    1.78 +    } while (result < 0 && (errno == EINTR));
    1.79 +    if (result == 0 || (nonblocking && result < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))) break;
    1.80 +    if (result < 0) {
    1.81 +      moonbr_io_errmsg();
    1.82 +      handle->readerr = 1;
    1.83 +      lua_pushnil(L);
    1.84 +      lua_pushstring(L, errmsg);
    1.85 +      return 2;
    1.86 +    }
    1.87 +    handle->readbufcnt += result;
    1.88 +  }
    1.89 +  luaL_addlstring(&luabuf, handle->readbuf, handle->readbufcnt);
    1.90 +  handle->readbufcnt = 0;
    1.91 +  luaL_pushresult(&luabuf);
    1.92 +  return 1;
    1.93 +}
    1.94 +
    1.95 +static int moonbr_io_read(lua_State *L) {
    1.96 +  return moonbr_io_read_impl(L, 0);
    1.97 +}
    1.98 +
    1.99 +static int moonbr_io_read_nb(lua_State *L) {
   1.100 +  return moonbr_io_read_impl(L, 1);
   1.101 +}
   1.102 +
   1.103  static int moonbr_io_write_impl(lua_State *L, int nonblocking, int flush) {
   1.104    moonbr_io_handle_t *handle;
   1.105    int i, top;
   1.106 @@ -221,6 +296,8 @@
   1.107    handle->fd = fd;
   1.108    handle->issocket = issocket;
   1.109    handle->nonblocking = -1;
   1.110 +  handle->readerr = 0;
   1.111 +  handle->readbufcnt = 0;
   1.112    handle->writeerr = 0;
   1.113    handle->writeleft = 0;
   1.114    handle->writeqin = 0;
   1.115 @@ -271,17 +348,19 @@
   1.116  }
   1.117  
   1.118  static int moonbr_io_getdummy(lua_State *L) {
   1.119 -  moonbr_io_pushhandle(L, 2, 0);
   1.120 +  moonbr_io_pushhandle(L, 0, 0);
   1.121    return 1;
   1.122  }
   1.123  
   1.124  static const struct luaL_Reg moonbr_io_handle_methods[] = {
   1.125 -  {"reset", moonbr_io_reset},
   1.126 -  {"close", moonbr_io_close},
   1.127 +  {"read", moonbr_io_read},
   1.128 +  {"read_nb", moonbr_io_read_nb},
   1.129    {"write", moonbr_io_write},
   1.130    {"write_nb", moonbr_io_write_nb},
   1.131    {"flush", moonbr_io_flush},
   1.132    {"flush_nb", moonbr_io_flush_nb},
   1.133 +  {"reset", moonbr_io_reset},
   1.134 +  {"close", moonbr_io_close},
   1.135    {NULL, NULL}
   1.136  };
   1.137  

Impressum / About Us