summaryrefslogtreecommitdiff
path: root/vector.c
diff options
context:
space:
mode:
Diffstat (limited to 'vector.c')
-rw-r--r--vector.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/vector.c b/vector.c
new file mode 100644
index 0000000..57f62d7
--- /dev/null
+++ b/vector.c
@@ -0,0 +1,37 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "vector.h"
+
+#define VECTOR_TOOBIG(alloc,elemsize,arrayoff) ((SIZE_MAX - (arrayoff)) / (alloc) < (elemsize))
+#define VECTOR_ALLOCSIZE(alloc,elemsize,arrayoff) ((arrayoff) + (alloc) * (elemsize))
+
+void *vector_init(size_t alloc, size_t elemsize, size_t arrayoff)
+{
+ if (VECTOR_TOOBIG(alloc, elemsize, arrayoff)) return NULL;
+ struct vector *v = malloc(VECTOR_ALLOCSIZE(alloc, elemsize, arrayoff));
+ if (!v) return NULL;
+
+ *v = (struct vector) {
+ .alloc = alloc,
+ .elemsize = elemsize,
+ .arrayoff = arrayoff,
+ };
+ return v;
+}
+
+void *vector_append(struct vector **vp)
+{
+ struct vector *v = *vp;
+ if (v->count >= v->alloc) {
+ size_t alloc = 2 * v->alloc;
+ if (VECTOR_TOOBIG(alloc, v->elemsize, v->arrayoff)) return NULL;
+ v = realloc(v, VECTOR_ALLOCSIZE(alloc, v->elemsize, v->arrayoff));
+ if (!v) return NULL;
+ v->alloc = alloc;
+ *vp = v;
+ }
+ return (char*)v + v->arrayoff + v->count++ * v->elemsize;
+}
+