summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Renner Berthing <esmil@mailme.dk>2012-12-10 21:48:37 +0100
committerEmil Renner Berthing <esmil@mailme.dk>2012-12-17 10:11:06 +0100
commitbce5e3beab432a359a3d27b9caaf02160e3fb2cc (patch)
tree4473f7a7ee056165e5ec6a25eb75a353c064de09
parentdfcd5ee52877c26f3fe9eb18ee8e5bbf99921636 (diff)
downloadlem-bce5e3beab432a359a3d27b9caaf02160e3fb2cc.tar.gz
lem-bce5e3beab432a359a3d27b9caaf02160e3fb2cc.tar.xz
lem-bce5e3beab432a359a3d27b9caaf02160e3fb2cc.zip
streams: add file:seek() method
-rw-r--r--lem/streams/core.c3
-rw-r--r--lem/streams/file.c81
-rwxr-xr-xtest/fwrite.lua4
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)