summaryrefslogtreecommitdiffstats
path: root/lib/libdvec/include/dvec.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libdvec/include/dvec.h')
-rw-r--r--lib/libdvec/include/dvec.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/lib/libdvec/include/dvec.h b/lib/libdvec/include/dvec.h
new file mode 100644
index 0000000..3dfed36
--- /dev/null
+++ b/lib/libdvec/include/dvec.h
@@ -0,0 +1,173 @@
+#pragma once
+
+#include "allocator.h"
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define DVEC_ITER(dvec, p) (p) = NULL; ((p) = dvec_iter_fwd((dvec), (p)));
+#define DVEC_ITER_BWD(dvec, p) (p) = NULL; ((p) = dvec_iter_bwd((dvec), (p)));
+
+#define DVEC_STRERR_INIT \
+ [DVEC_OK] = "Success", \
+ [DVEC_LOCKED] = "Data vector locked"
+
+#ifdef LIBDVEC_ASSERT_ARGS
+#include "stdlib.h"
+#define LIBDVEC_ABORT_ON_ARGS(cond) do { if (cond) abort(); } while (0)
+#else
+#define LIBDVEC_ABORT_ON_ARGS(cond)
+#endif
+
+#ifdef LIBDVEC_ASSERT_ALLOC
+#include "stdlib.h"
+#define LIBDVEC_ABORT_ON_ALLOC(cond) do { if (cond) abort(); } while (0)
+#else
+#define LIBDVEC_ABORT_ON_ALLOC(cond)
+#endif
+
+enum {
+ DVEC_OK = 0,
+ DVEC_LOCKED = 1,
+};
+
+struct dvec {
+ size_t dsize;
+ size_t len, cap;
+ uint8_t *data;
+ uint8_t locked : 1; /* prevents resizes */
+ uint8_t fused : 1; /* single allocation w/ data */
+ const struct allocator *allocator;
+};
+
+typedef bool (*dvec_sort_order_fn)(const void *p1, const void *p2, void *u);
+typedef int (*dvec_search_cmp_fn)(const void *cur, void *user);
+
+int dvec_init(struct dvec *dvec, size_t dsize, size_t cap,
+ const struct allocator *allocator);
+int dvec_deinit(struct dvec *dvec);
+
+struct dvec *dvec_alloc(size_t dsize, size_t cap,
+ const struct allocator *allocator, int *rc);
+struct dvec *dvec_alloc_fused(size_t dsize, size_t cap,
+ const struct allocator *allocator, int *rc);
+int dvec_free(struct dvec *dvec);
+
+int dvec_copy(struct dvec *dst, struct dvec *src);
+void dvec_move(struct dvec *dst, struct dvec *src);
+void dvec_swap(struct dvec *dst, struct dvec *src);
+
+void dvec_clear(struct dvec *dvec);
+int dvec_reserve(struct dvec *dvec, size_t cap);
+int dvec_shrink(struct dvec *dvec);
+
+int dvec_add(struct dvec *dvec, size_t index, size_t count);
+void dvec_rm(struct dvec *dvec, size_t index, size_t count);
+void dvec_replace(struct dvec *dvec, size_t index,
+ const void *data, size_t count);
+
+void *dvec_iter_fwd(const struct dvec *dvec, const void *p);
+void *dvec_iter_bwd(const struct dvec *dvec, const void *p);
+
+int dvec_quick_sort(struct dvec *dvec, const struct allocator *allocator,
+ void *tmp, bool reverse, dvec_sort_order_fn in_order, void *user);
+int dvec_quick_sort_ex(struct dvec *dvec, const struct allocator *allocator,
+ void *tmp, bool reverse, dvec_sort_order_fn in_order, void *user);
+
+ssize_t dvec_binary_search(struct dvec *dvec, dvec_search_cmp_fn search_cmp,
+ void *user, ssize_t *lower, ssize_t *higher);
+
+static inline void *
+dvec_at(const struct dvec *dvec, size_t index)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec || index >= dvec->len);
+
+ return dvec->data + index * dvec->dsize;
+}
+
+static inline void *
+dvec_at_back(const struct dvec *dvec, size_t index)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec || !index || index >= dvec->len);
+
+ return dvec->data + (dvec->len - 1 - index) * dvec->dsize;
+}
+
+static inline void *
+dvec_front(const struct dvec *dvec)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec);
+
+ return dvec->data;
+}
+
+static inline void *
+dvec_back(const struct dvec *dvec)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec);
+
+ return dvec->data + (dvec->len - 1) * dvec->dsize;
+}
+
+static inline bool
+dvec_empty(const struct dvec *dvec)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec);
+
+ return !dvec->len;
+}
+
+static inline size_t
+dvec_len(const struct dvec *dvec)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec);
+
+ return dvec->len;
+}
+
+static inline int
+dvec_add_back(struct dvec *dvec, size_t count)
+{
+ return dvec_add(dvec, dvec->len, count);
+}
+
+static inline void
+dvec_rm_back(struct dvec *dvec, size_t count)
+{
+ dvec_rm(dvec, dvec->len - count, count);
+}
+
+static inline void
+dvec_lock(struct dvec *dvec, bool lock)
+{
+ dvec->locked = lock;
+}
+
+static inline void *
+dvec_push(struct dvec *dvec)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec);
+
+ dvec_reserve(dvec, dvec->len + 1);
+
+ return dvec->data + dvec->len++ * dvec->dsize;
+}
+
+static inline void *
+dvec_pop(struct dvec *dvec)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec || !dvec->len);
+
+ return dvec->data + --dvec->len * dvec->dsize;
+}
+
+static inline size_t
+dvec_idx(struct dvec *dvec, const void *p)
+{
+ LIBDVEC_ABORT_ON_ARGS(!dvec || p < dvec->data
+ || p >= dvec->data + dvec->dsize * dvec->len);
+
+ return (size_t) ((uint8_t *)p - dvec->data) / dvec->dsize;
+}