summaryrefslogtreecommitdiffstats
path: root/src/vector.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vector.h')
-rw-r--r--src/vector.h113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/vector.h b/src/vector.h
new file mode 100644
index 0000000..02ea804
--- /dev/null
+++ b/src/vector.h
@@ -0,0 +1,113 @@
+/**
+ \file
+
+ Typesafe dynamically sized arrays
+*/
+
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+/** A vector descriptor */
+typedef struct _vector_desc {
+ size_t allocated; /**< The number of elements currently allocated */
+ size_t length; /**< The actual number of elements in the vector */
+} vector_desc_t;
+
+/**
+ A type for a vector of \e type elements
+
+ \hideinitializer
+*/
+#define VECTOR(type) struct { \
+ vector_desc_t desc; \
+ type *data; \
+}
+
+bool _vector_resize(vector_desc_t *desc, void **data, size_t n, size_t elemsize);
+bool _vector_insert(vector_desc_t *desc, void **data, void *element, size_t pos, size_t elemsize);
+void _vector_delete(vector_desc_t *desc, void **data, size_t pos, size_t elemsize);
+
+/**
+ Resizes the vector \e a to \e n elements
+
+ \hideinitializer
+*/
+#define VECTOR_RESIZE(v, n) ({ \
+ __typeof__(v) *_v = &(v); \
+ _vector_resize(&_v->desc, (void **)&_v->data, (n), sizeof(*_v->data)); \
+})
+
+/**
+ Frees all resources used by the vector \e v
+
+ \hideinitializer
+*/
+#define VECTOR_FREE(v) free((v).data)
+
+/**
+ Returns the number of elements in the vector \e v
+
+ \hideinitializer
+*/
+#define VECTOR_LEN(v) ((v).desc.length)
+
+/**
+ Returns the element with index \e i in the vector \e v
+
+ \hideinitializer
+*/
+#define VECTOR_INDEX(v, i) ((v).data[i])
+
+/**
+ Returns a pointer to the vector elements of \e v
+
+ \hideinitializer
+*/
+#define VECTOR_DATA(v) ((v).data)
+
+/**
+ Inserts the element \e elem at index \e pos of vector \e v
+
+ \hideinitializer
+*/
+#define VECTOR_INSERT(v, elem, pos) ({ \
+ __typeof__(v) *_v = &(v); \
+ __typeof__(*_v->data) _e = (elem); \
+ _vector_insert(&_v->desc, (void **)&_v->data, &_e, (pos), sizeof(_e)); \
+})
+
+/**
+ Adds the element \e elem at the end of vector \e v
+
+ \hideinitializer
+*/
+#define VECTOR_ADD(v, elem) ({ \
+ __typeof__(v) *_v = &(v); \
+ __typeof__(*_v->data) _e = (elem); \
+ _vector_insert(&_v->desc, (void **)&_v->data, &_e, _v->desc.length, sizeof(_e)); \
+})
+
+/**
+ Deletes the element at index \e pos of vector \e v
+
+ \hideinitializer
+*/
+#define VECTOR_DELETE(v, pos) ({ \
+ __typeof__(v) *_v = &(v); \
+ _vector_delete(&_v->desc, (void **)&_v->data, (pos), sizeof(*_v->data)); \
+})
+
+/**
+ Performs a binary search on the vector \e v, returning a pointer to a matching vector element
+
+ \hideinitializer
+*/
+#define VECTOR_BSEARCH(key, v, cmp) ({ \
+ __typeof__(v) *_v = &(v); \
+ const __typeof__(*_v->data) *_key = (key); \
+ int (*_cmp)(__typeof__(_key), __typeof__(_key)) = (cmp); \
+ (__typeof__(_v->data))bsearch(_key, _v->data, _v->desc.length, sizeof(*_v->data), (int (*)(const void *, const void *))_cmp); \
+})