summaryrefslogtreecommitdiffhomepage
path: root/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'buffer.c')
-rw-r--r--buffer.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/buffer.c b/buffer.c
new file mode 100644
index 0000000..cadfb7d
--- /dev/null
+++ b/buffer.c
@@ -0,0 +1,97 @@
+#include "buffer.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <lua.h>
+
+#include "stream.h"
+
+void grow(lua_State * L, struct buffer * b)
+{
+ int allocated = b->allocated + 1024;
+
+ if (8192 < allocated)
+ {
+ lua_pushliteral(L, "Too large buffer");
+ lua_error(L);
+ }
+
+ void * buffer = realloc(b->data, allocated);
+
+ if (NULL == buffer)
+ {
+ lua_pushliteral(L, "Could not grow buffer");
+ lua_error(L);
+ }
+
+ b->data = buffer;
+ b->allocated = allocated;
+}
+
+int read_more(lua_State * L, struct stream * s, int minimum_length, lua_KContext ctx)
+{
+ const int free_space = s->in.allocated + s->in.offset - s->in.length - 1;
+
+ while (free_space < minimum_length)
+ {
+ grow(L, &s->in);
+ }
+
+ if (0 < s->in.offset)
+ {
+ memmove(s->in.data, s->in.data + s->in.offset, s->in.length - s->in.offset);
+ s->in.offset = 0;
+ s->in.length -= s->in.offset;
+ }
+
+ int length = read(s->fd, s->in.data + s->in.length, free_space);
+
+ if (-1 == length)
+ {
+ if (EWOULDBLOCK == errno || EAGAIN == errno)
+ {
+ return lua_yieldk(L, 0, ctx, stream_readk);
+ }
+ else
+ {
+ lua_pushstring(L, strerror(errno));
+ return lua_error(L);
+ }
+ }
+
+ s->in.length += length;
+
+ return length;
+}
+
+int prepare_at_least(lua_State * L, struct stream * s, int minimum_length, lua_KContext ctx)
+{
+ const int remaining_bytes = s->in.length - s->in.next;
+
+ if (remaining_bytes < minimum_length)
+ {
+ return read_more(L, s, minimum_length, ctx);
+ }
+
+ return remaining_bytes;
+}
+
+int until(struct buffer * b, const char * pattern, int pattern_length)
+{
+ while (b->next + pattern_length <= b->length)
+ {
+ if (0 == strncmp(&b->data[b->next], pattern, pattern_length))
+ {
+ return b->next;
+ }
+ else
+ {
+ b->next++;
+ }
+ }
+
+ return -1;
+}