summaryrefslogtreecommitdiffstats
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..47bf7a7
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,65 @@
+#include <errno.h>
+#include "defs.h"
+#include "util.h"
+#include "cache.h"
+#include "stream.h"
+
+int stream_rewind(struct stream * const restrict in)
+{
+ int ret = 0;
+
+ in->cnode = in->cnode ? in->cache_l : NULL;
+ in->index = 0;
+
+ return ret;
+}
+
+int split(struct stream * const src, struct stream * const A, struct stream * const B)
+{
+ int ret = 0;
+ struct settings tmp_settings[2];
+
+ try(src->n < 2, err, EINVAL, "cannot split single element stream.");
+
+ /* setting up minimal stream basics */
+ A->n = src->n / 2;
+ B->n = src->n / 2 + (src->n & 1ul);
+ A->index = B->index = 0;
+ /* we only care about these three functions for these temporary streams */
+ A->get = B->get = src->get;
+ A->put = B->put = src->put;
+ A->copy = B->copy = src->copy;
+
+ tmp_settings[0] = *src->settings;
+ tmp_settings[1] = *src->settings;
+ A->settings = tmp_settings;
+ B->settings = tmp_settings + 1;
+
+ /* setting up A */
+ tmp_settings[0].ss = 0;
+ tmp_settings[0].to = A->n;
+ /* setting up B */
+ tmp_settings[1].ss = A->n;
+ tmp_settings[1].to = src->n;
+
+ if (src->settings->access == cached) {
+ A->fd = B->fd = -1; /* if we're splitting, these are for holding cache only */
+ A->type = B->type = stream_cache;
+ try_s((ret = cache_create(A)), err);
+ try_s((ret = src->copy(src, A)), err);
+ try_s((ret = cache_create(B)), err);
+ try_s((ret = src->copy(src, B)), err);
+ } else {
+ A->name = B->name = src->name;
+ A->type = B->type = stream_lite;
+ try_s((ret = stream_open(A)), err);
+ try_s((ret = src->copy(src, A)), err);
+ try_s((ret = stream_open(B)), err);
+ try_s((ret = src->copy(src, B)), err);
+ }
+
+ A->settings = B->settings = src->settings;
+
+err:
+ return ret;
+}