diff options
Diffstat (limited to 'buffer.c')
-rw-r--r-- | buffer.c | 97 |
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; +} |