summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--stream.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/stream.c b/stream.c
index f9cdb6d..a7219ac 100644
--- a/stream.c
+++ b/stream.c
@@ -1,6 +1,9 @@
#include "stream.h"
+#include <errno.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <lauxlib.h>
#include <lua.h>
@@ -12,6 +15,8 @@
int stream_push_new(lua_State * L, const int fd)
{
struct stream * s = lua_newuserdata(L, sizeof(struct stream));
+ memset(s, 0, sizeof(struct stream));
+
s->fd = fd;
if (1 == luaL_newmetatable(L, "stream"))
@@ -91,16 +96,40 @@ int stream_read(lua_State * L)
s->in.data = buffer;
}
- return stream_readk(L, LUA_OK, 0); // Intentionally do not pop Stream that's on top of the stack.
+ return stream_readk(L, LUA_OK, (lua_KContext) s); // Intentionally do not pop Stream that's on top of the stack.
}
/// Continuation function and core implementation of the reading operation from a stream.
/// \param L Lua state running reading operation
/// \param status TODO
-/// \param ctx TODO
+/// \param ctx Address of the Stream that is being read
/// \param Number of the results pushed to the stack
int stream_readk(lua_State * L, int status, lua_KContext ctx)
{
- lua_pop(L, 0);
- return 0;
+ struct stream * s = (struct stream *) ctx;
+
+ int length = read(s->fd, s->in.data, 1023); // TODO: Allow user to control amount of bytes being read.
+
+ if (-1 == length)
+ {
+ if (EWOULDBLOCK == errno || EAGAIN == errno)
+ {
+ lua_yieldk(L, 0, ctx, stream_readk);
+ }
+ else
+ {
+ lua_pop(L, 1);
+ lua_pushstring(L, strerror(errno));
+ return lua_error(L);
+ }
+ }
+
+ s->in.data[length] = 0;
+ s->in.length = length;
+ s->in.offset = 0;
+
+ lua_pushstring(L, s->in.data);
+ lua_remove(L, -2);
+
+ return 1;
}