moonbridge
changeset 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 |
files | moonbridge_io.c |
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