summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Renner Berthing <esmil@mailme.dk>2012-12-10 14:24:39 +0100
committerEmil Renner Berthing <esmil@mailme.dk>2012-12-17 10:11:06 +0100
commitdfcd5ee52877c26f3fe9eb18ee8e5bbf99921636 (patch)
treec6a537cba6e988ff4a9d45aec6a582aeaf97a86d
parent9e69d37f9e7a00b9902ebe5618904871397c7999 (diff)
downloadlem-dfcd5ee52877c26f3fe9eb18ee8e5bbf99921636.tar.gz
lem-dfcd5ee52877c26f3fe9eb18ee8e5bbf99921636.tar.xz
lem-dfcd5ee52877c26f3fe9eb18ee8e5bbf99921636.zip
streams: add file:write() method
-rw-r--r--lem/streams/core.c3
-rw-r--r--lem/streams/file.c70
-rwxr-xr-xtest/fwrite.lua61
3 files changed, 133 insertions, 1 deletions
diff --git a/lem/streams/core.c b/lem/streams/core.c
index b71dc06..3ddc397 100644
--- a/lem/streams/core.c
+++ b/lem/streams/core.c
@@ -186,6 +186,9 @@ luaopen_lem_streams_core(lua_State *L)
/* mt.readp = <file_readp> */
lua_pushcfunction(L, file_readp);
lua_setfield(L, -2, "readp");
+ /* mt.write = <file_write> */
+ lua_pushcfunction(L, file_write);
+ lua_setfield(L, -2, "write");
/* insert table */
lua_setfield(L, -2, "File");
diff --git a/lem/streams/file.c b/lem/streams/file.c
index 85fb5a0..be44ce1 100644
--- a/lem/streams/file.c
+++ b/lem/streams/file.c
@@ -20,7 +20,11 @@ struct file {
struct lem_async a;
int fd;
int ret;
- struct lem_parser *p;
+ union {
+ struct lem_parser *p;
+ const char *out;
+ };
+ size_t out_size;
struct lem_inputbuf buf;
};
@@ -194,3 +198,67 @@ file_readp(lua_State *T)
lem_async_do(&f->a, T, file_readp_work, file_readp_reap);
return lua_yield(T, lua_gettop(T));
}
+
+/*
+ * file:write() method
+ */
+static void
+file_write_work(struct lem_async *a)
+{
+ struct file *f = (struct file *)a;
+ ssize_t bytes = write(f->fd, f->out, f->out_size);
+
+ if (bytes < 0)
+ f->ret = errno;
+ else
+ f->ret = 0;
+}
+
+static void
+file_write_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_pushboolean(T, 1);
+ lem_queue(T, 1);
+}
+
+static int
+file_write(lua_State *T)
+{
+ struct file *f;
+ const char *out;
+ size_t out_size;
+
+ luaL_checktype(T, 1, LUA_TUSERDATA);
+ out = luaL_checklstring(T, 2, &out_size);
+
+ f = lua_touserdata(T, 1);
+ 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->out = out;
+ f->out_size = out_size;
+ lem_async_do(&f->a, T, file_write_work, file_write_reap);
+
+ lua_settop(T, 2);
+ return lua_yield(T, 2);
+}
diff --git a/test/fwrite.lua b/test/fwrite.lua
new file mode 100755
index 0000000..ff4c484
--- /dev/null
+++ b/test/fwrite.lua
@@ -0,0 +1,61 @@
+#!bin/lem
+--
+-- This file is part of LEM, a Lua Event Machine.
+-- Copyright 2011-2012 Emil Renner Berthing
+--
+-- LEM is free software: you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License as
+-- published by the Free Software Foundation, either version 3 of
+-- the License, or (at your option) any later version.
+--
+-- LEM is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with LEM. If not, see <http://www.gnu.org/licenses/>.
+--
+
+local utils = require 'lem.utils'
+local stream = require 'lem.streams'
+
+local write
+do
+ local stdout = stream.stdout
+ function write(str)
+ return stdout:write(str)
+ end
+end
+
+print("Press enter to read '" .. (arg[1] or arg[0]) .. "'")
+stream.stdin:read()
+
+local threads = 2
+for i = 1, threads do
+ utils.spawn(function(n)
+ local file = assert(stream.open('file' .. tostring(n) .. '.txt', 'w'))
+ assert(getmetatable(file) == stream.File, "Hmm...")
+
+ print(tostring(n) .. '-1')
+ assert(file:write('Hej!\n'))
+ print(tostring(n) .. '-2')
+ assert(file:write(tostring(n)))
+ print(tostring(n) .. '-3')
+ assert(file:write('\n'))
+ print(tostring(n) .. '-4')
+
+ threads = threads - 1
+ end, i)
+end
+
+local yield = utils.yield
+while threads > 0 do
+ write('.')
+ yield()
+end
+
+print "\nDone. Press enter to continue."
+stream.stdin:read()
+
+-- vim: set ts=2 sw=2 noet: