summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--bufferq.c88
-rw-r--r--bufferq.h13
-rw-r--r--test-bufferq.c14
4 files changed, 91 insertions, 26 deletions
diff --git a/Makefile b/Makefile
index 123b97d..76ef581 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ OBJS=$(SOURCES:.c=.o)
all: test-bufferq test-llist test-sine test-pull
-test-bufferq: test-bufferq.o bufferq.o
+test-bufferq: test-bufferq.o bufferq.o malloc.o
$(CC) $(CFLAGS) -o $@ $^
test-llist: test-llist.o
diff --git a/bufferq.c b/bufferq.c
index c4c3ec3..5261f35 100644
--- a/bufferq.c
+++ b/bufferq.c
@@ -4,6 +4,8 @@
#include "macro.h"
#include "bufferq.h"
+#define SA_BUFFERQ_CONCAT_DATA(x) ((void*) (uint8_t*) (x) + ALIGN(sizeof(sa_bufferq_item_t)))
+
int sa_bufferq_init(sa_bufferq_t *q, unsigned nchannels, size_t sample_size) {
sa_assert(q);
sa_assert(sample_size > 0);
@@ -42,19 +44,53 @@ void sa_bufferq_done(sa_bufferq_t *q) {
sa_free(q->last);
}
-static sa_bufferq_item_t* bufferq_item_new(size_t size) {
+static sa_bufferq_item_t* bufferq_item_new(const void *d, size_t size, int copy) {
sa_bufferq_item_t *i;
sa_assert(size > 0);
+
+ if (!copy) {
+ if (!(i = sa_new(sa_bufferq_item_t, 1)))
+ return i;
+ i->type = SA_BUFFERQ_ITEM_STATIC;
+ i->data = (void*) d;
+ } else {
+ if (!(i = sa_malloc(ALIGN(sizeof(sa_bufferq_item_t)) + size)))
+ return i;
+ i->type = SA_BUFFERQ_ITEM_CONCATENATED;
+ i->data = SA_BUFFERQ_CONCAT_DATA(i);
+ memcpy(i->data, d, size);
+ }
+
+ i->size = size;
+ SA_LLIST_ITEM_INIT(sa_bufferq_item_t, bufferq, i);
+
+ return i;
+}
+
+static sa_bufferq_item_t* bufferq_item_make_writable(sa_bufferq_item_t *i) {
+ void *d;
+ sa_assert(i);
- if (!(i = sa_malloc(ALIGN(sizeof(sa_bufferq_item_t)) + size)))
+ if (i->type == SA_BUFFERQ_ITEM_CONCATENATED || i->type == SA_BUFFERQ_ITEM_DYNAMIC)
return i;
- SA_LLIST_ITEM_INIT(sa_bufferq_item_t, bufferq, i);
+ if (!(d = sa_memdup(i->data, i->size)))
+ return NULL;
+ i->data = d;
+ i->type = SA_BUFFERQ_ITEM_DYNAMIC;
return i;
}
-int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence) {
+static void bufferq_item_free(sa_bufferq_item_t *i) {
+ sa_assert(i);
+
+ if (i->type == SA_BUFFERQ_ITEM_DYNAMIC)
+ sa_free(i->data);
+ sa_free(i);
+}
+
+int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence, int copy) {
int64_t idx;
sa_bufferq_item_t *i, *j;
@@ -103,13 +139,11 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t
if (l > i->idx - idx)
l = i->idx - idx;
-
- if (!(j = bufferq_item_new(l)))
- return SA_ERROR_OOM;
- memcpy(SA_BUFFERQ_ITEM_DATA(j), data, l);
+ if (!(j = bufferq_item_new(data, l, copy)))
+ return SA_ERROR_OOM;
+
j->idx = idx;
- j->size = l;
SA_LLIST_INSERT_BEFORE(sa_bufferq_item_t, bufferq, q->items[channel], i, j);
@@ -127,7 +161,10 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t
if (l > i->idx + i->size - idx)
l = i->idx + i->size - idx;
- memcpy((uint8_t*) SA_BUFFERQ_ITEM_DATA(i) + (idx - i->idx), data, l);
+ if (!(i = bufferq_item_make_writable(i)))
+ return SA_ERROR_OOM;
+
+ memcpy((uint8_t*) i->data + (idx - i->idx), data, l);
idx += l;
data += l;
@@ -138,12 +175,10 @@ int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t
if (nbytes > 0) {
sa_assert(!i);
- if (!(j = bufferq_item_new(nbytes)))
+ if (!(j = bufferq_item_new(data, nbytes, copy)))
return SA_ERROR_OOM;
- memcpy(SA_BUFFERQ_ITEM_DATA(j), data, nbytes);
j->idx = idx;
- j->size = nbytes;
if (q->last[channel])
SA_LLIST_INSERT_AFTER(sa_bufferq_item_t, bufferq, q->items[channel], q->last[channel], j);
@@ -186,7 +221,7 @@ int sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes) {
} else {
int64_t l;
- i[u] = (uint8_t*) SA_BUFFERQ_ITEM_DATA(q->items[u]) + q->read_index - q->items[u]->idx;
+ i[u] = (uint8_t*) q->items[u]->data + q->read_index - q->items[u]->idx;
l = q->items[u]->size - (q->read_index - q->items[u]->idx);
@@ -213,7 +248,6 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) {
q->read_index += bytes;
for (u = 0; u < q->nchannels; u++) {
-
sa_bufferq_item_t *i;
i = q->items[u];
@@ -223,7 +257,7 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) {
SA_LLIST_REMOVE(sa_bufferq_item_t, bufferq, q->items[u], i);
- sa_free(i);
+ bufferq_item_free(i);
i = n;
}
@@ -233,3 +267,25 @@ int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes) {
return SA_SUCCESS;
}
+
+int sa_bufferq_realloc(sa_bufferq_t *q) {
+ unsigned u;
+ sa_assert(q);
+
+ for (u = 0; u < q->nchannels; u++) {
+ sa_bufferq_item_t *i;
+
+ i = q->items[u];
+
+ while (i) {
+
+ if (!bufferq_item_make_writable(i))
+ return SA_ERROR_OOM;
+
+ i = i->bufferq_next;
+ }
+
+ }
+
+ return SA_SUCCESS;
+}
diff --git a/bufferq.h b/bufferq.h
index a645398..538bf4d 100644
--- a/bufferq.h
+++ b/bufferq.h
@@ -7,14 +7,20 @@
#include "llist.h"
#include "sydney.h"
+typedef enum sa_bufferq_item_type {
+ SA_BUFFERQ_ITEM_CONCATENATED,
+ SA_BUFFERQ_ITEM_DYNAMIC,
+ SA_BUFFERQ_ITEM_STATIC
+} sa_bufferq_item_type_t;
+
typedef struct sa_bufferq_item {
+ void *data;
int64_t idx;
size_t size;
+ sa_bufferq_item_type_t type;
SA_LLIST_ITEM(struct sa_bufferq_item, bufferq);
} sa_bufferq_item_t;
-#define SA_BUFFERQ_ITEM_DATA(x) ((void*) (uint8_t*) (x) + ALIGN(sizeof(sa_bufferq_item_t)))
-
typedef struct sa_bufferq {
SA_LLIST_HEAD(sa_bufferq_item_t, *items);
sa_bufferq_item_t **last;
@@ -27,7 +33,8 @@ int sa_bufferq_init(sa_bufferq_t *q, unsigned nchannels, size_t sample_size);
void sa_bufferq_done(sa_bufferq_t *q);
-int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence);
+int sa_bufferq_push(sa_bufferq_t *q, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence, int copy);
+int sa_bufferq_realloc(sa_bufferq_t *q);
int sa_bufferq_get(sa_bufferq_t *q, void *i[], size_t *bytes);
int sa_bufferq_drop(sa_bufferq_t *q, int64_t bytes);
diff --git a/test-bufferq.c b/test-bufferq.c
index 05fc35b..6c57384 100644
--- a/test-bufferq.c
+++ b/test-bufferq.c
@@ -6,12 +6,14 @@ int main(int argc, char *argv[]) {
sa_bufferq_init(&q, 1, 1);
- sa_bufferq_push(&q, 0, "{AAAAAAAA}", 10, 0, SA_SEEK_RELATIVE);
- sa_bufferq_push(&q, 0, "<BBBBBBBB>", 10, 5, SA_SEEK_RELATIVE);
- sa_bufferq_push(&q, 0, "[CCCC]", 6, -18, SA_SEEK_RELATIVE);
- sa_bufferq_push(&q, 0, "(DDDD)", 6, -3, SA_SEEK_ABSOLUTE);
- sa_bufferq_push(&q, 0, "XXX", 3, 10, SA_SEEK_RELATIVE_END);
- sa_bufferq_push(&q, 0, "YYYYY", 5, -4, SA_SEEK_RELATIVE);
+ sa_bufferq_push(&q, 0, "{AAAAAAAA}", 10, 0, SA_SEEK_RELATIVE, 0);
+ sa_bufferq_push(&q, 0, "<BBBBBBBB>", 10, 5, SA_SEEK_RELATIVE, 0);
+ sa_bufferq_push(&q, 0, "[CCCC]", 6, -18, SA_SEEK_RELATIVE, 0);
+ sa_bufferq_push(&q, 0, "(DDDD)", 6, -3, SA_SEEK_ABSOLUTE, 0);
+ sa_bufferq_push(&q, 0, "XXX", 3, 10, SA_SEEK_RELATIVE_END, 0);
+ sa_bufferq_push(&q, 0, "YYYYY", 5, -4, SA_SEEK_RELATIVE, 0);
+
+ sa_bufferq_realloc(&q);
for (;;) {
void *b[1];