diff options
author | Emil Renner Berthing <esmil@mailme.dk> | 2012-12-10 21:48:37 +0100 |
---|---|---|
committer | Emil Renner Berthing <esmil@mailme.dk> | 2012-12-17 10:11:06 +0100 |
commit | bce5e3beab432a359a3d27b9caaf02160e3fb2cc (patch) | |
tree | 4473f7a7ee056165e5ec6a25eb75a353c064de09 | |
parent | dfcd5ee52877c26f3fe9eb18ee8e5bbf99921636 (diff) | |
download | lem-bce5e3beab432a359a3d27b9caaf02160e3fb2cc.tar.gz lem-bce5e3beab432a359a3d27b9caaf02160e3fb2cc.tar.xz lem-bce5e3beab432a359a3d27b9caaf02160e3fb2cc.zip |
streams: add file:seek() method
-rw-r--r-- | lem/streams/core.c | 3 | ||||
-rw-r--r-- | lem/streams/file.c | 81 | ||||
-rwxr-xr-x | test/fwrite.lua | 4 |
3 files changed, 86 insertions, 2 deletions
diff --git a/lem/streams/core.c b/lem/streams/core.c index 3ddc397..da1d62b 100644 --- a/lem/streams/core.c +++ b/lem/streams/core.c @@ -189,6 +189,9 @@ luaopen_lem_streams_core(lua_State *L) /* mt.write = <file_write> */ lua_pushcfunction(L, file_write); lua_setfield(L, -2, "write"); + /* mt.seek = <file_seek> */ + lua_pushcfunction(L, file_seek); + lua_setfield(L, -2, "seek"); /* insert table */ lua_setfield(L, -2, "File"); diff --git a/lem/streams/file.c b/lem/streams/file.c index be44ce1..4fde951 100644 --- a/lem/streams/file.c +++ b/lem/streams/file.c @@ -22,9 +22,15 @@ struct file { int ret; union { struct lem_parser *p; - const char *out; + struct { + const char *out; + size_t out_size; + }; + struct { + off_t offset; + int whence; + }; }; - size_t out_size; struct lem_inputbuf buf; }; @@ -262,3 +268,74 @@ file_write(lua_State *T) lua_settop(T, 2); return lua_yield(T, 2); } + +/* + * file:seek() method + */ +static void +file_seek_work(struct lem_async *a) +{ + struct file *f = (struct file *)a; + off_t bytes = lseek(f->fd, f->offset, f->whence); + + if (bytes == (off_t)-1) { + f->ret = errno; + } else { + f->offset = bytes; + f->ret = 0; + } +} + +static void +file_seek_reap(struct lem_async *a) +{ + struct file *f = (struct file *)a; + lua_State *T = f->a.T; + + f->a.T = NULL; + + if (f->ret) { + lua_pushnil(T); + lua_pushstring(T, strerror(f->ret)); + lem_queue(T, 2); + return; + } + + lua_pushnumber(T, f->offset); + lem_queue(T, 1); +} + +static int +file_seek(lua_State *T) +{ + static const int mode[] = { SEEK_SET, SEEK_CUR, SEEK_END }; + static const char *const modenames[] = { "set", "cur", "end", NULL }; + struct file *f; + int op; + lua_Number offset; + + luaL_checktype(T, 1, LUA_TUSERDATA); + op = luaL_checkoption(T, 2, "cur", modenames); + offset = luaL_optnumber(T, 3, 0.); + f = lua_touserdata(T, 1); + f->offset = (off_t)offset; + luaL_argcheck(T, (lua_Number)f->offset == offset, 3, + "not an integer in proper range"); + if (f->fd < 0) { + lua_pushnil(T); + lua_pushliteral(T, "closed"); + return 2; + } + + if (f->a.T != NULL) { + lua_pushnil(T); + lua_pushliteral(T, "busy"); + return 2; + } + + f->whence = mode[op]; + lem_async_do(&f->a, T, file_seek_work, file_seek_reap); + + lua_settop(T, 1); + return lua_yield(T, 1); +} diff --git a/test/fwrite.lua b/test/fwrite.lua index ff4c484..f4e8856 100755 --- a/test/fwrite.lua +++ b/test/fwrite.lua @@ -44,6 +44,10 @@ for i = 1, threads do print(tostring(n) .. '-3') assert(file:write('\n')) print(tostring(n) .. '-4') + print(assert(file:seek("cur", -2))) + print(tostring(n) .. '-5') + assert(file:write('Dav!')) + print(tostring(n) .. '-6') threads = threads - 1 end, i) |