summaryrefslogtreecommitdiffstats
path: root/qbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'qbuf.c')
-rw-r--r--qbuf.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/qbuf.c b/qbuf.c
new file mode 100644
index 0000000..d225ce7
--- /dev/null
+++ b/qbuf.c
@@ -0,0 +1,62 @@
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "qbuf.h"
+
+void qbuf_init(struct qbuf *q, size_t length) {
+ assert(q && length);
+ memset(q, 0, sizeof(struct qbuf));
+
+ q->data = malloc(q->length = length*2);
+ assert(q->data);
+}
+
+void qbuf_done(struct qbuf *q) {
+ assert(q);
+ free(q->data);
+}
+
+static void move_to_front(struct qbuf *q) {
+ assert(q);
+
+ if (q->index+q->fill <= q->length/2)
+ return;
+
+ memmove(q->data, q->data+q->index, q->fill);
+ q->index = 0;
+}
+
+void* qbuf_push(struct qbuf *q, size_t *l) {
+ size_t m;
+ assert(q);
+
+ move_to_front(q);
+ m = q->length - q->fill - q->index;
+ *l = m;
+ return q->data + q->index + q->fill;
+}
+
+void qbuf_push_validate(struct qbuf *q, size_t l) {
+ assert(q);
+ q->fill += l;
+ assert(q->index+q->fill <= q->length);
+}
+
+void* qbuf_pull(struct qbuf *q, size_t *l) {
+ assert(q);
+ *l = q->fill;
+ return q->data + q->index;
+}
+
+void qbuf_pull_invalidate(struct qbuf *q, size_t l) {
+ assert(q);
+
+ assert(l <= q->fill);
+ q->fill -= l;
+ q->index += l;
+
+ assert(q->index+q->fill <= q->length);
+ if (!q->fill)
+ q->index = 0;
+}